Coverage for apps/appointments/reports/app_report.py: 3%

203 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2024-05-09 16:59 -0600

1import functools 

2from io import BytesIO 

3 

4import xlsxwriter 

5from django.core.files.base import ContentFile 

6 

7from apps.products.models import Product 

8 

9from ..models import Appointment, AppointmentCharge 

10 

11 

12def create_appointment_report(instance: Appointment): 

13 """ 

14 Reporte General 

15 """ 

16 

17 from_date = instance.from_date 

18 until_date = instance.to_date 

19 practitioner = instance.practitioner 

20 organization = instance.organization 

21 

22 # Create a workbook and add a worksheet. 

23 output = BytesIO() 

24 workbook_name = f"Reporte General del {from_date} al {until_date}.xlsx" 

25 workbook = xlsxwriter.Workbook(output) 

26 worksheet_name = f"Por fecha" 

27 worksheet = workbook.add_worksheet(worksheet_name) 

28 

29 # get the queryset for appointment charges 

30 queryset = Appointment.objects.filter( 

31 organization=instance.organization, 

32 date__gte=instance.from_date, 

33 date__lte=instance.to_date, 

34 ).order_by("date", "start_timestamp") 

35 

36 if instance.practitioner is not None: 

37 queryset.filter(practitioner__in=instance.owner_practitioners()) 

38 

39 # Write image for report (row 1) 

40 worksheet.set_row(0, 40) 

41 worksheet.embed_image(0, 1, "./app/TualLogo.png") 

42 

43 # Write title of table (rows 2 and 3) 

44 title_format = workbook.add_format( 

45 { 

46 "bold": True, 

47 "font_color": "red", 

48 "font_size": 30, 

49 } 

50 ) 

51 

52 subtitle_format = workbook.add_format({"bold": True, "italic": True}) 

53 

54 worksheet.merge_range(2, 1, 2, 3, "Reporte General", title_format) 

55 worksheet.merge_range(3, 1, 3, 3, f"Del {from_date} al {until_date}", subtitle_format) 

56 

57 # Row 4 empty 

58 

59 # Write headers of table (row 5 and 6) 

60 header_row_format = workbook.add_format({"bold": True, "italic": True, "bg_color": "#50C878"}) 

61 date_row_format = workbook.add_format( 

62 {"num_format": "[$-x-sysdate]dddd, mmmm dd, yyyy", "align": "left", "bold": True, "bg_color": "#E2E2E2"} 

63 ) 

64 date_row_money_format = workbook.add_format( 

65 { 

66 "num_format": "$#,##0.00", 

67 "bg_color": "#E2E2E2", 

68 "bold": True, 

69 } 

70 ) 

71 date_row_money_format_red = workbook.add_format( 

72 { 

73 "num_format": "$#,##0.00", 

74 "bg_color": "#E2E2E2", 

75 "bold": True, 

76 "font_color": "red", 

77 } 

78 ) 

79 patient_row_time_format = workbook.add_format({"num_format": "h:mm AM/PM", "align": "center"}) 

80 patient_row_money_format = workbook.add_format({"num_format": "$#,##0.00"}) 

81 patient_row_money_format_red = workbook.add_format( 

82 { 

83 "num_format": "$#,##0.00", 

84 "font_color": "red", 

85 } 

86 ) 

87 

88 appointment_charge_row_money_format = workbook.add_format({"font_size": 8, "num_format": "$#,##0.00"}) 

89 appointment_charge_row_money_format_red = workbook.add_format( 

90 { 

91 "font_size": 8, 

92 "num_format": "$#,##0.00", 

93 "font_color": "red", 

94 } 

95 ) 

96 appointment_charge_row_text_format = workbook.add_format( 

97 { 

98 "font_size": 8, 

99 } 

100 ) 

101 

102 start_row_for_headers = 5 

103 

104 worksheet.write(start_row_for_headers, 1, "Fecha", header_row_format) 

105 worksheet.write(start_row_for_headers, 2, "Hora Consulta", header_row_format) 

106 worksheet.write(start_row_for_headers, 3, "Tipo de Consulta", header_row_format) 

107 worksheet.write(start_row_for_headers, 4, "Paciente", header_row_format) 

108 worksheet.write(start_row_for_headers, 5, "Tipo de Servicio", header_row_format) 

109 worksheet.write(start_row_for_headers, 6, "Servicio", header_row_format) 

110 worksheet.write(start_row_for_headers, 7, "Cantidad", header_row_format) 

111 worksheet.write(start_row_for_headers, 8, "Precio Unitario", header_row_format) 

112 worksheet.write(start_row_for_headers, 9, "Venta", header_row_format) 

113 worksheet.write(start_row_for_headers, 10, "Costo Consultorio", header_row_format) 

114 worksheet.write(start_row_for_headers, 11, "Costo Proveedores", header_row_format) 

115 worksheet.write(start_row_for_headers, 12, "Costo Total", header_row_format) 

116 worksheet.write(start_row_for_headers, 13, "Utilidad", header_row_format) 

117 worksheet.write(start_row_for_headers, 14, "Pagado", header_row_format) 

118 worksheet.write(start_row_for_headers, 15, "Adeudado", header_row_format) 

119 worksheet.write(start_row_for_headers, 16, "Facturación", header_row_format) 

120 

121 worksheet.set_column("K:N", None, None, {"level": 1, "hidden": False}) 

122 worksheet.set_column("O:O", None, None, {"collapsed": True}) 

123 worksheet.set_column(8, 15, 13) 

124 

125 # Start with the content 

126 ########## 

127 

128 row = start_row_for_headers + 1 

129 current_date = None 

130 current_appointment = None 

131 date_rows = [] 

132 patient_rows = [] 

133 date_totals_row_values = [0, 0, 0, 0, 0, 0, 0] 

134 patient_totals_row_values = [0, 0, 0, 0, 0, 0, 0] 

135 product_totals_row_values = {} 

136 initial_date_row = row 

137 initial_patient_row = row + 1 

138 

139 for appointment in queryset: 

140 

141 if appointment.date != current_date: 

142 

143 worksheet.write( 

144 initial_date_row, 

145 8, 

146 "", 

147 date_row_money_format, 

148 ) 

149 worksheet.write( 

150 initial_date_row, 

151 9, 

152 date_totals_row_values[0], 

153 date_row_money_format, 

154 ) 

155 worksheet.write( 

156 initial_date_row, 

157 10, 

158 date_totals_row_values[1], 

159 date_row_money_format, 

160 ) 

161 worksheet.write( 

162 initial_date_row, 

163 11, 

164 date_totals_row_values[2], 

165 date_row_money_format, 

166 ) 

167 worksheet.write( 

168 initial_date_row, 

169 12, 

170 date_totals_row_values[3], 

171 date_row_money_format, 

172 ) 

173 worksheet.write( 

174 initial_date_row, 

175 13, 

176 date_totals_row_values[4], 

177 date_row_money_format, 

178 ) 

179 worksheet.write( 

180 initial_date_row, 

181 14, 

182 date_totals_row_values[5], 

183 date_row_money_format, 

184 ) 

185 worksheet.write( 

186 initial_date_row, 

187 15, 

188 date_totals_row_values[6], 

189 date_row_money_format_red, 

190 ) 

191 

192 date_totals_row_values = [0, 0, 0, 0, 0, 0, 0] 

193 date_current_row_values = [0, 0, 0, 0, 0, 0, 0] 

194 

195 initial_date_row = row 

196 date_rows.append(row) 

197 worksheet.merge_range(row, 1, row, 7, appointment.date, date_row_format) 

198 row += 1 

199 current_appointment = None 

200 patient_rows = [] 

201 

202 if appointment != current_appointment: 

203 

204 worksheet.write( 

205 initial_patient_row, 

206 8, 

207 "", 

208 patient_row_money_format, 

209 ) 

210 worksheet.write( 

211 initial_patient_row, 

212 9, 

213 patient_totals_row_values[0], 

214 patient_row_money_format, 

215 ) 

216 worksheet.write( 

217 initial_patient_row, 

218 10, 

219 patient_totals_row_values[1], 

220 patient_row_money_format, 

221 ) 

222 worksheet.write( 

223 initial_patient_row, 

224 11, 

225 patient_totals_row_values[2], 

226 patient_row_money_format, 

227 ) 

228 worksheet.write( 

229 initial_patient_row, 

230 12, 

231 patient_totals_row_values[3], 

232 patient_row_money_format, 

233 ) 

234 worksheet.write( 

235 initial_patient_row, 

236 13, 

237 patient_totals_row_values[4], 

238 patient_row_money_format, 

239 ) 

240 worksheet.write( 

241 initial_patient_row, 

242 14, 

243 patient_totals_row_values[5], 

244 patient_row_money_format, 

245 ) 

246 worksheet.write( 

247 initial_patient_row, 

248 15, 

249 patient_totals_row_values[6], 

250 patient_row_money_format_red, 

251 ) 

252 patient_totals_row_values = [0, 0, 0, 0, 0, 0, 0] 

253 patient_current_row_values = [0, 0, 0, 0, 0, 0, 0] 

254 

255 initial_patient_row = row 

256 patient_rows.append(row) 

257 worksheet.set_row(row, None, None, {"level": 1, "collapsed": True}) 

258 worksheet.write(row, 2, getattr(appointment, "start_time", "Sin Hora"), patient_row_time_format) 

259 worksheet.write(row, 3, getattr(appointment.type_of, "name", ""), patient_row_time_format) 

260 worksheet.merge_range(row, 4, row, 8, getattr(appointment.patient, "full_name", "Paciente sin Nombre")) 

261 

262 row += 1 

263 

264 for appointment_charge in appointment.charges.all(): 

265 

266 worksheet.write(row, 5, appointment_charge.product._meta.verbose_name, appointment_charge_row_text_format) 

267 worksheet.write(row, 6, appointment_charge.product.name, appointment_charge_row_text_format) 

268 worksheet.write(row, 7, appointment_charge.quantity, appointment_charge_row_text_format) 

269 worksheet.write(row, 8, appointment_charge.price.amount, appointment_charge_row_money_format) 

270 worksheet.write(row, 9, appointment_charge.total_price.amount, appointment_charge_row_money_format) 

271 worksheet.write(row, 10, appointment_charge.total_shared_cost.amount, appointment_charge_row_money_format) 

272 worksheet.write(row, 11, appointment_charge.total_hard_cost.amount, appointment_charge_row_money_format) 

273 worksheet.write( 

274 row, 

275 12, 

276 appointment_charge.total_shared_cost.amount + appointment_charge.total_hard_cost.amount, 

277 appointment_charge_row_money_format, 

278 ) 

279 worksheet.write( 

280 row, 

281 13, 

282 appointment_charge.total_price.amount 

283 - (appointment_charge.total_shared_cost.amount + appointment_charge.total_hard_cost.amount), 

284 appointment_charge_row_money_format, 

285 ) 

286 worksheet.write(row, 14, appointment_charge.paid_amount.amount, appointment_charge_row_money_format) 

287 worksheet.write(row, 15, appointment_charge.pending_amount.amount, appointment_charge_row_money_format_red) 

288 worksheet.write(row, 16, appointment_charge.pk) 

289 worksheet.set_row(row, None, None, {"level": 2, "hidden": False}) 

290 

291 patient_current_row_values = [ 

292 appointment_charge.total_price.amount, 

293 appointment_charge.total_shared_cost.amount, 

294 appointment_charge.total_hard_cost.amount, 

295 appointment_charge.total_shared_cost.amount + appointment_charge.total_hard_cost.amount, 

296 appointment_charge.total_price.amount 

297 - (appointment_charge.total_shared_cost.amount + appointment_charge.total_hard_cost.amount), 

298 appointment_charge.paid_amount.amount, 

299 appointment_charge.pending_amount.amount, 

300 ] 

301 patient_totals_row_values = list( 

302 map(lambda x, y: x + y, patient_totals_row_values, patient_current_row_values) 

303 ) 

304 

305 date_current_row_values = [ 

306 appointment_charge.total_price.amount, 

307 appointment_charge.total_shared_cost.amount, 

308 appointment_charge.total_hard_cost.amount, 

309 appointment_charge.total_shared_cost.amount + appointment_charge.total_hard_cost.amount, 

310 appointment_charge.total_price.amount 

311 - (appointment_charge.total_shared_cost.amount + appointment_charge.total_hard_cost.amount), 

312 appointment_charge.paid_amount.amount, 

313 appointment_charge.pending_amount.amount, 

314 ] 

315 date_totals_row_values = list(map(lambda x, y: x + y, date_totals_row_values, date_current_row_values)) 

316 

317 product_current_row_values = [ 

318 appointment_charge.quantity, 

319 appointment_charge.total_price.amount, 

320 appointment_charge.total_shared_cost.amount, 

321 appointment_charge.total_hard_cost.amount, 

322 appointment_charge.total_shared_cost.amount + appointment_charge.total_hard_cost.amount, 

323 appointment_charge.total_price.amount 

324 - (appointment_charge.total_shared_cost.amount + appointment_charge.total_hard_cost.amount), 

325 appointment_charge.paid_amount.amount, 

326 appointment_charge.pending_amount.amount, 

327 ] 

328 

329 product_totals_row_values[appointment_charge.product.pk] = list( 

330 map( 

331 lambda x, y: x + y, 

332 product_totals_row_values.setdefault(appointment_charge.product.pk, [0, 0, 0, 0, 0, 0, 0, 0]), 

333 product_current_row_values, 

334 ) 

335 ) 

336 

337 row += 1 

338 current_date = appointment_charge.appointment.date 

339 current_appointment = appointment_charge.appointment 

340 

341 worksheet.write( 

342 initial_date_row, 

343 8, 

344 "", 

345 date_row_money_format, 

346 ) 

347 worksheet.write( 

348 initial_date_row, 

349 9, 

350 date_totals_row_values[0], 

351 date_row_money_format, 

352 ) 

353 worksheet.write( 

354 initial_date_row, 

355 10, 

356 date_totals_row_values[1], 

357 date_row_money_format, 

358 ) 

359 worksheet.write( 

360 initial_date_row, 

361 11, 

362 date_totals_row_values[2], 

363 date_row_money_format, 

364 ) 

365 worksheet.write( 

366 initial_date_row, 

367 12, 

368 date_totals_row_values[3], 

369 date_row_money_format, 

370 ) 

371 worksheet.write( 

372 initial_date_row, 

373 13, 

374 date_totals_row_values[4], 

375 date_row_money_format, 

376 ) 

377 worksheet.write( 

378 initial_date_row, 

379 14, 

380 date_totals_row_values[5], 

381 date_row_money_format, 

382 ) 

383 worksheet.write( 

384 initial_date_row, 

385 15, 

386 date_totals_row_values[6], 

387 date_row_money_format_red, 

388 ) 

389 

390 worksheet.write( 

391 initial_patient_row, 

392 8, 

393 "", 

394 patient_row_money_format, 

395 ) 

396 

397 worksheet.write( 

398 initial_patient_row, 

399 9, 

400 patient_totals_row_values[0], 

401 patient_row_money_format, 

402 ) 

403 worksheet.write( 

404 initial_patient_row, 

405 10, 

406 patient_totals_row_values[1], 

407 patient_row_money_format, 

408 ) 

409 worksheet.write( 

410 initial_patient_row, 

411 11, 

412 patient_totals_row_values[2], 

413 patient_row_money_format, 

414 ) 

415 worksheet.write( 

416 initial_patient_row, 

417 12, 

418 patient_totals_row_values[3], 

419 patient_row_money_format, 

420 ) 

421 worksheet.write( 

422 initial_patient_row, 

423 13, 

424 patient_totals_row_values[4], 

425 patient_row_money_format, 

426 ) 

427 worksheet.write( 

428 initial_patient_row, 

429 14, 

430 patient_totals_row_values[5], 

431 patient_row_money_format, 

432 ) 

433 worksheet.write( 

434 initial_patient_row, 

435 15, 

436 patient_totals_row_values[6], 

437 patient_row_money_format_red, 

438 ) 

439 

440 # Resumen por tipo de productos 

441 category_row_format = workbook.add_format( 

442 { 

443 # "bg_color": "#8A39E3", 

444 "bg_color": "#9FC095", 

445 "bold": True, 

446 } 

447 ) 

448 category_row_money_format = workbook.add_format( 

449 { 

450 "num_format": "$#,##0.00", 

451 # "bg_color": "#8A39E3", 

452 "bg_color": "#9FC095", 

453 "bold": True, 

454 } 

455 ) 

456 category_row_money_format_red = workbook.add_format( 

457 { 

458 "num_format": "$#,##0.00", 

459 # "bg_color": "#8A39E3", 

460 "bg_color": "#9FC095", 

461 "font_color": "red", 

462 "bold": True, 

463 } 

464 ) 

465 

466 product_row_money_format = workbook.add_format( 

467 { 

468 "num_format": "$#,##0.00", 

469 } 

470 ) 

471 product_row_money_format_red = workbook.add_format( 

472 { 

473 "num_format": "$#,##0.00", 

474 "font_color": "red", 

475 } 

476 ) 

477 product_row_format = workbook.add_format({}) 

478 row += 5 

479 current_category = None 

480 current_product = None 

481 category_rows = [] 

482 category_totals_row_values = [0, 0, 0, 0, 0, 0, 0, 0] 

483 initial_category_row = row 

484 

485 new_category_dict = {} 

486 

487 for product_pk, product_totals_list in product_totals_row_values.items(): 

488 

489 product = Product.objects.get(pk=product_pk) 

490 category = product._meta.verbose_name_plural 

491 

492 if not category in new_category_dict: 

493 new_category_dict[category] = {} 

494 

495 new_category_dict[category][product_pk] = product_totals_list 

496 

497 for category, products in new_category_dict.items(): 

498 

499 if category != current_category: 

500 current_category = category 

501 

502 worksheet.write( 

503 initial_category_row, 

504 7, 

505 category_totals_row_values[0], 

506 category_row_format, 

507 ) 

508 

509 worksheet.write( 

510 initial_category_row, 

511 8, 

512 "", 

513 category_row_money_format, 

514 ) 

515 

516 worksheet.write( 

517 initial_category_row, 

518 9, 

519 category_totals_row_values[1], 

520 category_row_money_format, 

521 ) 

522 worksheet.write( 

523 initial_category_row, 

524 10, 

525 category_totals_row_values[2], 

526 category_row_money_format, 

527 ) 

528 worksheet.write( 

529 initial_category_row, 

530 11, 

531 category_totals_row_values[3], 

532 category_row_money_format, 

533 ) 

534 worksheet.write( 

535 initial_category_row, 

536 12, 

537 category_totals_row_values[4], 

538 category_row_money_format, 

539 ) 

540 worksheet.write( 

541 initial_category_row, 

542 13, 

543 category_totals_row_values[5], 

544 category_row_money_format, 

545 ) 

546 worksheet.write( 

547 initial_category_row, 

548 14, 

549 category_totals_row_values[6], 

550 category_row_money_format, 

551 ) 

552 worksheet.write( 

553 initial_category_row, 

554 15, 

555 category_totals_row_values[7], 

556 category_row_money_format_red, 

557 ) 

558 

559 category_totals_row_values = [0, 0, 0, 0, 0, 0, 0, 0] 

560 initial_category_row = row 

561 worksheet.merge_range(row, 1, row, 6, category, category_row_format) 

562 row += 1 

563 

564 for product_pk, product_totals_list in products.items(): 

565 product = Product.objects.get(pk=product_pk) 

566 

567 worksheet.write(row, 3, product.name, product_row_format) 

568 worksheet.write(row, 7, product_totals_list[0], product_row_format) 

569 worksheet.write(row, 9, product_totals_list[1], product_row_money_format) 

570 worksheet.write(row, 10, product_totals_list[2], product_row_money_format) 

571 worksheet.write(row, 11, product_totals_list[3], product_row_money_format) 

572 worksheet.write(row, 12, product_totals_list[4], product_row_money_format) 

573 worksheet.write(row, 13, product_totals_list[5], product_row_money_format) 

574 worksheet.write(row, 14, product_totals_list[6], product_row_money_format) 

575 worksheet.write(row, 15, product_totals_list[7], product_row_money_format_red) 

576 

577 category_totals_row_values = list(map(lambda x, y: x + y, category_totals_row_values, product_totals_list)) 

578 

579 row += 1 

580 

581 worksheet.write( 

582 initial_category_row, 

583 7, 

584 category_totals_row_values[0], 

585 category_row_format, 

586 ) 

587 worksheet.write( 

588 initial_category_row, 

589 8, 

590 "", 

591 category_row_money_format, 

592 ) 

593 worksheet.write( 

594 initial_category_row, 

595 9, 

596 category_totals_row_values[1], 

597 category_row_money_format, 

598 ) 

599 worksheet.write( 

600 initial_category_row, 

601 10, 

602 category_totals_row_values[2], 

603 category_row_money_format, 

604 ) 

605 worksheet.write( 

606 initial_category_row, 

607 11, 

608 category_totals_row_values[3], 

609 category_row_money_format, 

610 ) 

611 worksheet.write( 

612 initial_category_row, 

613 12, 

614 category_totals_row_values[4], 

615 category_row_money_format, 

616 ) 

617 worksheet.write( 

618 initial_category_row, 

619 13, 

620 category_totals_row_values[5], 

621 category_row_money_format, 

622 ) 

623 worksheet.write( 

624 initial_category_row, 

625 14, 

626 category_totals_row_values[6], 

627 category_row_money_format, 

628 ) 

629 worksheet.write( 

630 initial_category_row, 

631 15, 

632 category_totals_row_values[7], 

633 category_row_money_format_red, 

634 ) 

635 

636 worksheet.autofit() 

637 

638 workbook.close() 

639 xlsx_data = output.getvalue() 

640 

641 xlsx_file = ContentFile(xlsx_data) 

642 

643 instance.export_file.save(workbook_name, xlsx_file) 

644 instance.save()