Coverage for website/sales/tests/test_admin.py: 93.75%

366 statements  

« prev     ^ index     » next       coverage.py v7.6.7, created at 2025-08-14 10:31 +0000

1from django.contrib.admin import AdminSite 

2from django.contrib.auth.models import Permission 

3from django.contrib.contenttypes.models import ContentType 

4from django.test import Client, RequestFactory, TestCase 

5from django.urls import reverse 

6from django.utils import timezone 

7 

8from activemembers.models import Committee, MemberGroupMembership 

9from members.models import Member 

10from payments.models import Payment 

11from payments.services import create_payment 

12from sales import payables 

13from sales.admin.order_admin import OrderAdmin 

14from sales.admin.shift_admin import ShiftAdmin 

15from sales.models.order import Order, OrderItem 

16from sales.models.product import Product, ProductList 

17from sales.models.shift import Shift 

18 

19 

20class OrderAdminTest(TestCase): 

21 fixtures = [ 

22 "members.json", 

23 "bank_accounts.json", 

24 "member_groups.json", 

25 "products.json", 

26 ] 

27 

28 @classmethod 

29 def setUpTestData(cls) -> None: 

30 """Create the following test data: 

31 

32 o0: an empty order 

33 o1: an unpaid order of 2 beer 

34 o2: an order of 2 soda that doesn't need a payment 

35 o3: an unpaid order with 2 beer and 2 wine 

36 o4: a paid order with 2 wine 

37 o5: a paid order with 2 beer and 2 wine 

38 o6: an unpaid order of 2 soda that does need a payment (custom) 

39 """ 

40 payables.register() 

41 

42 cls.user = Member.objects.filter(last_name="Wiggers").first() 

43 

44 cls.beer = Product.objects.get(name="beer") 

45 cls.wine = Product.objects.get(name="wine") 

46 cls.soda = Product.objects.get(name="soda") 

47 

48 cls.normal = ProductList.objects.get( 

49 name="normal", 

50 ) 

51 cls.free = ProductList.objects.get( 

52 name="free", 

53 ) 

54 

55 cls.shift = Shift.objects.create( 

56 start=timezone.now(), 

57 end=timezone.now() + timezone.timedelta(hours=1), 

58 product_list=cls.normal, 

59 ) 

60 

61 cls.o0 = Order.objects.create(shift=cls.shift) 

62 cls.o1 = Order.objects.create(shift=cls.shift) 

63 OrderItem.objects.create( 

64 order=cls.o1, 

65 product=cls.shift.product_list.product_items.get(product=cls.beer), 

66 amount=2, 

67 ) 

68 cls.o2 = Order.objects.create(shift=cls.shift) 

69 OrderItem.objects.create( 

70 order=cls.o2, 

71 product=cls.shift.product_list.product_items.get(product=cls.soda), 

72 amount=2, 

73 ) 

74 cls.o3 = Order.objects.create(shift=cls.shift) 

75 OrderItem.objects.create( 

76 order=cls.o3, 

77 product=cls.shift.product_list.product_items.get(product=cls.beer), 

78 amount=2, 

79 ) 

80 OrderItem.objects.create( 

81 order=cls.o3, 

82 product=cls.shift.product_list.product_items.get(product=cls.wine), 

83 amount=2, 

84 ) 

85 cls.o4 = Order.objects.create(shift=cls.shift) 

86 OrderItem.objects.create( 

87 order=cls.o4, 

88 product=cls.shift.product_list.product_items.get(product=cls.wine), 

89 amount=2, 

90 ) 

91 cls.o5 = Order.objects.create(shift=cls.shift) 

92 OrderItem.objects.create( 

93 order=cls.o5, 

94 product=cls.shift.product_list.product_items.get(product=cls.beer), 

95 amount=2, 

96 ) 

97 OrderItem.objects.create( 

98 order=cls.o5, 

99 product=cls.shift.product_list.product_items.get(product=cls.wine), 

100 amount=2, 

101 ) 

102 cls.o4.payment = create_payment( 

103 cls.o4, processed_by=cls.user, pay_type=Payment.CASH 

104 ) 

105 cls.o4.save() 

106 cls.o5.payment = create_payment( 

107 cls.o5, processed_by=cls.user, pay_type=Payment.CASH 

108 ) 

109 cls.o5.save() 

110 cls.o6 = Order.objects.create(shift=cls.shift) 

111 OrderItem.objects.create( 

112 order=cls.o6, 

113 product=cls.shift.product_list.product_items.get(product=cls.soda), 

114 amount=2, 

115 total=1, 

116 ) 

117 

118 cls.cie = Committee.objects.get(pk=1) 

119 MemberGroupMembership.objects.create(group=cls.cie, member=cls.user) 

120 content_type = ContentType.objects.get_for_model(Order) 

121 permission1 = Permission.objects.get( 

122 content_type=content_type, codename="add_order" 

123 ) 

124 permission2 = Permission.objects.get( 

125 content_type=content_type, codename="change_order" 

126 ) 

127 permission3 = Permission.objects.get( 

128 content_type=content_type, codename="delete_order" 

129 ) 

130 permission4 = Permission.objects.get( 

131 content_type=content_type, codename="view_order" 

132 ) 

133 cls.cie.permissions.add(permission1) 

134 cls.cie.permissions.add(permission2) 

135 cls.cie.permissions.add(permission3) 

136 cls.cie.permissions.add(permission4) 

137 

138 def setUp(self) -> None: 

139 self.client = Client() 

140 self.client.force_login(self.user) 

141 self.factory = RequestFactory() 

142 self.site = AdminSite() 

143 self.admin = OrderAdmin(Order, admin_site=self.site) 

144 self.rf = RequestFactory() 

145 

146 self.client.logout() 

147 self.client.force_login(self.user) 

148 

149 def test_change_form_view_rendering_correctly(self) -> None: 

150 for o in [self.o0, self.o1, self.o2, self.o3, self.o4, self.o5, self.o6]: 

151 response = self.client.get(f"/admin/sales/order/{o.id}/change/") 

152 self.assertEqual(200, response.status_code) 

153 

154 def test_change_list_view_rendering_correctly(self) -> None: 

155 response = self.client.get("/admin/sales/order/") 

156 self.assertEqual(200, response.status_code) 

157 

158 def test_view_permissions(self): 

159 with self.subTest("View as super user"): 

160 request = self.rf.get( 

161 reverse("admin:sales_order_change", args=[self.o1.pk]) 

162 ) 

163 request.user = self.user 

164 request.member = self.user 

165 self.assertTrue(self.admin.has_view_permission(request, self.o1)) 

166 

167 with self.subTest("View without permissions"): 

168 self.user.is_superuser = False 

169 self.user.save() 

170 self.client.logout() 

171 self.client.force_login(self.user) 

172 request = self.rf.get( 

173 reverse("admin:sales_order_change", args=[self.o1.pk]) 

174 ) 

175 request.user = self.user 

176 request.member = self.user 

177 self.assertFalse(self.admin.has_view_permission(request, self.o1)) 

178 

179 with self.subTest("View as shift manager"): 

180 self.shift.managers.add(self.cie) 

181 self.shift.save() 

182 self.client.logout() 

183 self.client.force_login(self.user) 

184 request = self.rf.get( 

185 reverse("admin:sales_order_change", args=[self.o1.pk]) 

186 ) 

187 request.user = self.user 

188 request.member = self.user 

189 self.assertTrue(self.admin.has_view_permission(request, self.o1)) 

190 

191 def test_change_permissions(self): 

192 with self.subTest("Change as super user"): 

193 request = self.rf.get( 

194 reverse("admin:sales_order_change", args=[self.o1.pk]) 

195 ) 

196 request.user = self.user 

197 request.member = self.user 

198 self.assertTrue(self.admin.has_change_permission(request, self.o1)) 

199 self.assertTrue( 

200 self.admin.inlines[0].has_change_permission( 

201 self.admin, request, self.o1 

202 ) 

203 ) 

204 

205 with self.subTest("Change without permissions"): 

206 self.user.is_superuser = False 

207 self.user.save() 

208 self.client.logout() 

209 self.client.force_login(self.user) 

210 request = self.rf.get( 

211 reverse("admin:sales_order_change", args=[self.o1.pk]) 

212 ) 

213 request.user = self.user 

214 request.member = self.user 

215 self.assertFalse(self.admin.has_change_permission(request, self.o1)) 

216 self.assertFalse( 

217 self.admin.inlines[0].has_change_permission( 

218 self.admin, request, self.o1 

219 ) 

220 ) 

221 

222 with self.subTest("Change as shift manager"): 

223 self.shift.managers.add(self.cie) 

224 self.shift.save() 

225 self.client.logout() 

226 self.client.force_login(self.user) 

227 request = self.rf.get( 

228 reverse("admin:sales_order_change", args=[self.o1.pk]) 

229 ) 

230 request.user = self.user 

231 request.member = self.user 

232 self.assertTrue(self.admin.has_change_permission(request, self.o1)) 

233 self.assertTrue( 

234 self.admin.inlines[0].has_change_permission( 

235 self.admin, request, self.o1 

236 ) 

237 ) 

238 

239 def test_change_permission_paid(self): 

240 request = self.rf.get(reverse("admin:sales_order_change", args=[self.o4.pk])) 

241 request.user = self.user 

242 request.member = self.user 

243 self.assertFalse(self.admin.has_change_permission(request, self.o4)) 

244 self.assertFalse( 

245 self.admin.inlines[0].has_change_permission(self.admin, request, self.o4) 

246 ) 

247 

248 def test_change_permission_locked(self): 

249 self.shift.locked = True 

250 self.shift.save() 

251 

252 request = self.rf.get(reverse("admin:sales_order_change", args=[self.o1.pk])) 

253 request.user = self.user 

254 request.member = self.user 

255 self.assertFalse(self.admin.has_change_permission(request, self.o1)) 

256 self.assertFalse(self.admin.has_change_permission(request, self.o1)) 

257 

258 def test_delete_permissions(self): 

259 with self.subTest("Delete as super user"): 

260 request = self.rf.get( 

261 reverse("admin:sales_order_delete", args=[self.o1.pk]) 

262 ) 

263 request.user = self.user 

264 request.member = self.user 

265 self.assertTrue(self.admin.has_delete_permission(request, self.o1)) 

266 self.assertTrue( 

267 self.admin.inlines[0].has_delete_permission( 

268 self.admin, request, self.o1 

269 ) 

270 ) 

271 

272 with self.subTest("Delete without permissions"): 

273 self.user.is_superuser = False 

274 self.user.save() 

275 self.client.logout() 

276 self.client.force_login(self.user) 

277 request = self.rf.get( 

278 reverse("admin:sales_order_delete", args=[self.o1.pk]) 

279 ) 

280 request.user = self.user 

281 request.member = self.user 

282 self.assertFalse(self.admin.has_delete_permission(request, self.o1)) 

283 self.assertFalse( 

284 self.admin.inlines[0].has_delete_permission( 

285 self.admin, request, self.o1 

286 ) 

287 ) 

288 

289 with self.subTest("Delete as shift manager"): 

290 self.shift.managers.add(self.cie) 

291 self.shift.save() 

292 self.client.logout() 

293 self.client.force_login(self.user) 

294 request = self.rf.get( 

295 reverse("admin:sales_order_delete", args=[self.o1.pk]) 

296 ) 

297 request.user = self.user 

298 request.member = self.user 

299 self.assertTrue(self.admin.has_delete_permission(request, self.o1)) 

300 self.assertTrue( 

301 self.admin.inlines[0].has_delete_permission( 

302 self.admin, request, self.o1 

303 ) 

304 ) 

305 

306 def test_delete_permission_paid(self): 

307 request = self.rf.get(reverse("admin:sales_order_delete", args=[self.o4.pk])) 

308 request.user = self.user 

309 request.member = self.user 

310 self.assertFalse(self.admin.has_delete_permission(request, self.o4)) 

311 self.assertFalse( 

312 self.admin.inlines[0].has_delete_permission(self.admin, request, self.o4) 

313 ) 

314 

315 def test_delete_permission_locked(self): 

316 self.shift.locked = True 

317 self.shift.save() 

318 

319 request = self.rf.get(reverse("admin:sales_order_delete", args=[self.o1.pk])) 

320 request.user = self.user 

321 request.member = self.user 

322 self.assertFalse(self.admin.has_delete_permission(request, self.o1)) 

323 self.assertFalse( 

324 self.admin.inlines[0].has_delete_permission(self.admin, request, self.o4) 

325 ) 

326 

327 def test_add_permission(self): 

328 with self.subTest("Create as super user"): 

329 request = self.rf.get(reverse("admin:sales_order_add")) 

330 request.user = self.user 

331 request.member = self.user 

332 self.assertTrue(self.admin.has_add_permission(request)) 

333 

334 with self.subTest("Create without permissions"): 

335 self.user.is_superuser = False 

336 self.user.save() 

337 self.client.logout() 

338 self.client.force_login(self.user) 

339 request = self.rf.get(reverse("admin:sales_order_add")) 

340 request.user = self.user 

341 request.member = self.user 

342 self.assertFalse(self.admin.has_add_permission(request)) 

343 

344 with self.subTest("Create as shift manager"): 

345 self.shift.managers.add(self.cie) 

346 self.shift.save() 

347 self.client.logout() 

348 self.client.force_login(self.user) 

349 request = self.rf.get(reverse("admin:sales_order_add")) 

350 request.user = self.user 

351 request.member = self.user 

352 self.assertTrue(self.admin.has_add_permission(request)) 

353 

354 with self.subTest("Create as shift manager no active shift"): 

355 self.shift.locked = True 

356 self.shift.save() 

357 request = self.rf.get(reverse("admin:sales_order_add")) 

358 request.user = self.user 

359 request.member = self.user 

360 self.assertFalse(self.admin.has_add_permission(request)) 

361 

362 def test_custom_prices_readonly(self): 

363 with self.subTest("Custom prices as super user"): 

364 request = self.rf.get(reverse("admin:sales_order_add")) 

365 request.user = self.user 

366 request.member = self.user 

367 

368 self.assertFalse("discount" in self.admin.get_readonly_fields(request)) 

369 self.assertFalse( 

370 "total" 

371 in self.admin.inlines[0].get_readonly_fields(self.admin, request) 

372 ) 

373 

374 with self.subTest("Custom prices regular user"): 

375 self.user.is_superuser = False 

376 self.user.save() 

377 self.shift.managers.add(self.cie) 

378 self.shift.save() 

379 self.client.logout() 

380 self.client.force_login(self.user) 

381 

382 request = self.rf.get(reverse("admin:sales_order_add")) 

383 request.user = self.user 

384 request.member = self.user 

385 

386 self.assertTrue("discount" in self.admin.get_readonly_fields(request)) 

387 self.assertTrue( 

388 "total" 

389 in self.admin.inlines[0].get_readonly_fields(self.admin, request) 

390 ) 

391 

392 

393class ShiftAdminTest(TestCase): 

394 fixtures = [ 

395 "members.json", 

396 "bank_accounts.json", 

397 "member_groups.json", 

398 "products.json", 

399 ] 

400 

401 @classmethod 

402 def setUpTestData(cls) -> None: 

403 """Create the following test data: 

404 

405 o0: an empty order 

406 o1: an unpaid order of 2 beer 

407 o2: an order of 2 soda that doesn't need a payment 

408 o3: an unpaid order with 2 beer and 2 wine 

409 o4: a paid order with 2 wine 

410 o5: a paid order with 2 beer and 2 wine 

411 o6: an unpaid order of 2 soda that does need a payment (custom) 

412 """ 

413 payables.register() 

414 

415 cls.user = Member.objects.filter(last_name="Wiggers").first() 

416 

417 cls.beer = Product.objects.get(name="beer") 

418 cls.wine = Product.objects.get(name="wine") 

419 cls.soda = Product.objects.get(name="soda") 

420 

421 cls.normal = ProductList.objects.get( 

422 name="normal", 

423 ) 

424 cls.free = ProductList.objects.get( 

425 name="free", 

426 ) 

427 

428 cls.shift = Shift.objects.create( 

429 start=timezone.now(), 

430 end=timezone.now() + timezone.timedelta(hours=1), 

431 product_list=cls.normal, 

432 ) 

433 

434 cls.o0 = Order.objects.create(shift=cls.shift) 

435 cls.o1 = Order.objects.create(shift=cls.shift) 

436 OrderItem.objects.create( 

437 order=cls.o1, 

438 product=cls.shift.product_list.product_items.get(product=cls.beer), 

439 amount=2, 

440 ) 

441 cls.o2 = Order.objects.create(shift=cls.shift) 

442 OrderItem.objects.create( 

443 order=cls.o2, 

444 product=cls.shift.product_list.product_items.get(product=cls.soda), 

445 amount=2, 

446 ) 

447 cls.o3 = Order.objects.create(shift=cls.shift) 

448 OrderItem.objects.create( 

449 order=cls.o3, 

450 product=cls.shift.product_list.product_items.get(product=cls.beer), 

451 amount=2, 

452 ) 

453 OrderItem.objects.create( 

454 order=cls.o3, 

455 product=cls.shift.product_list.product_items.get(product=cls.wine), 

456 amount=2, 

457 ) 

458 cls.o4 = Order.objects.create(shift=cls.shift) 

459 OrderItem.objects.create( 

460 order=cls.o4, 

461 product=cls.shift.product_list.product_items.get(product=cls.wine), 

462 amount=2, 

463 ) 

464 cls.o5 = Order.objects.create(shift=cls.shift) 

465 OrderItem.objects.create( 

466 order=cls.o5, 

467 product=cls.shift.product_list.product_items.get(product=cls.beer), 

468 amount=2, 

469 ) 

470 OrderItem.objects.create( 

471 order=cls.o5, 

472 product=cls.shift.product_list.product_items.get(product=cls.wine), 

473 amount=2, 

474 ) 

475 cls.o4.payment = create_payment( 

476 cls.o4, processed_by=cls.user, pay_type=Payment.CASH 

477 ) 

478 cls.o4.save() 

479 cls.o5.payment = create_payment( 

480 cls.o5, processed_by=cls.user, pay_type=Payment.CASH 

481 ) 

482 cls.o5.save() 

483 cls.o6 = Order.objects.create(shift=cls.shift) 

484 OrderItem.objects.create( 

485 order=cls.o6, 

486 product=cls.shift.product_list.product_items.get(product=cls.soda), 

487 amount=2, 

488 total=1, 

489 ) 

490 

491 cls.cie = Committee.objects.get(pk=1) 

492 MemberGroupMembership.objects.create(group=cls.cie, member=cls.user) 

493 content_type = ContentType.objects.get_for_model(Shift) 

494 permission1 = Permission.objects.get( 

495 content_type=content_type, codename="add_shift" 

496 ) 

497 permission2 = Permission.objects.get( 

498 content_type=content_type, codename="change_shift" 

499 ) 

500 permission3 = Permission.objects.get( 

501 content_type=content_type, codename="delete_shift" 

502 ) 

503 permission4 = Permission.objects.get( 

504 content_type=content_type, codename="view_shift" 

505 ) 

506 cls.cie.permissions.add(permission1) 

507 cls.cie.permissions.add(permission2) 

508 cls.cie.permissions.add(permission3) 

509 cls.cie.permissions.add(permission4) 

510 

511 def setUp(self) -> None: 

512 self.client = Client() 

513 self.client.force_login(self.user) 

514 self.factory = RequestFactory() 

515 self.site = AdminSite() 

516 self.admin = ShiftAdmin(Shift, admin_site=self.site) 

517 self.rf = RequestFactory() 

518 

519 self.client.logout() 

520 self.client.force_login(self.user) 

521 

522 def test_change_form_view_rendering_correctly(self) -> None: 

523 response = self.client.get(f"/admin/sales/shift/{self.shift.id}/change/") 

524 self.assertEqual(200, response.status_code) 

525 

526 def test_change_list_view_rendering_correctly(self) -> None: 

527 response = self.client.get("/admin/sales/shift/") 

528 self.assertEqual(200, response.status_code) 

529 

530 def test_view_permissions(self): 

531 with self.subTest("View as super user"): 

532 request = self.rf.get( 

533 reverse("admin:sales_shift_change", args=[self.shift.pk]) 

534 ) 

535 request.user = self.user 

536 request.member = self.user 

537 self.assertTrue(self.admin.has_view_permission(request, self.shift)) 

538 

539 with self.subTest("View without permissions"): 

540 self.user.is_superuser = False 

541 self.user.save() 

542 self.client.logout() 

543 self.client.force_login(self.user) 

544 request = self.rf.get( 

545 reverse("admin:sales_shift_change", args=[self.shift.pk]) 

546 ) 

547 request.user = self.user 

548 request.member = self.user 

549 self.assertFalse(self.admin.has_view_permission(request, self.shift)) 

550 

551 with self.subTest("View as shift manager"): 

552 self.shift.managers.add(self.cie) 

553 self.shift.save() 

554 self.client.logout() 

555 self.client.force_login(self.user) 

556 request = self.rf.get( 

557 reverse("admin:sales_shift_change", args=[self.shift.pk]) 

558 ) 

559 request.user = self.user 

560 request.member = self.user 

561 self.assertTrue(self.admin.has_view_permission(request, self.shift)) 

562 

563 def has_change_permission(self): 

564 with self.subTest("Change as super user"): 

565 request = self.rf.get( 

566 reverse("admin:sales_shift_change", args=[self.shift.pk]) 

567 ) 

568 request.user = self.user 

569 request.member = self.user 

570 self.assertTrue(self.admin.has_change_permission(request, self.shift)) 

571 

572 with self.subTest("Change without permissions"): 

573 self.user.is_superuser = False 

574 self.user.save() 

575 self.client.logout() 

576 self.client.force_login(self.user) 

577 request = self.rf.get( 

578 reverse("admin:sales_shift_change", args=[self.shift.pk]) 

579 ) 

580 request.user = self.user 

581 request.member = self.user 

582 self.assertFalse(self.admin.has_change_permission(request, self.shift)) 

583 

584 with self.subTest("Change as shift manager"): 

585 self.shift.managers.add(self.cie) 

586 self.shift.save() 

587 self.client.logout() 

588 self.client.force_login(self.user) 

589 request = self.rf.get( 

590 reverse("admin:sales_shift_change", args=[self.shift.pk]) 

591 ) 

592 request.user = self.user 

593 request.member = self.user 

594 self.assertTrue(self.admin.has_change_permission(request, self.shift)) 

595 

596 def test_change_permission_locked(self): 

597 self.shift.locked = True 

598 self.shift.save() 

599 

600 request = self.rf.get(reverse("admin:sales_shift_change", args=[self.shift.pk])) 

601 request.user = self.user 

602 request.member = self.user 

603 self.assertFalse(self.admin.has_change_permission(request, self.shift)) 

604 

605 def test_delete_permissions(self): 

606 with self.subTest("Delete as super user"): 

607 request = self.rf.get( 

608 reverse("admin:sales_shift_delete", args=[self.shift.pk]) 

609 ) 

610 request.user = self.user 

611 request.member = self.user 

612 self.assertTrue(self.admin.has_delete_permission(request, self.shift)) 

613 

614 with self.subTest("Delete without permissions"): 

615 self.user.is_superuser = False 

616 self.user.save() 

617 self.client.logout() 

618 self.client.force_login(self.user) 

619 request = self.rf.get( 

620 reverse("admin:sales_shift_delete", args=[self.shift.pk]) 

621 ) 

622 request.user = self.user 

623 request.member = self.user 

624 self.assertFalse(self.admin.has_delete_permission(request, self.shift)) 

625 

626 with self.subTest("Delete as shift manager"): 

627 self.shift.managers.add(self.cie) 

628 self.shift.save() 

629 self.client.logout() 

630 self.client.force_login(self.user) 

631 request = self.rf.get( 

632 reverse("admin:sales_shift_delete", args=[self.shift.pk]) 

633 ) 

634 request.user = self.user 

635 request.member = self.user 

636 self.assertTrue(self.admin.has_delete_permission(request, self.shift))