Coverage for apps/payments/models.py: 91%

61 statements  

« prev     ^ index     » next       coverage.py v6.4.4, created at 2024-05-23 08:26 -0600

1from django.db import models 

2from djmoney.models.fields import MoneyField 

3from djmoney.money import Money 

4from django.utils.functional import cached_property 

5 

6from base.models import RandomSlugModel, TimeStampedModel 

7 

8 

9class OrganizationPaymentMethod(RandomSlugModel, TimeStampedModel): 

10 """ 

11 Model for Organization Payment Method 

12 """ 

13 

14 organization = models.ForeignKey( 

15 "organizations.Organization", on_delete=models.PROTECT, related_name="payment_methods" 

16 ) 

17 

18 name = models.CharField(max_length=128) 

19 is_active = models.BooleanField(default=True) 

20 sat_id = models.CharField(max_length=2, editable=False) 

21 

22 class Meta: 

23 ordering = ["organization", "created_at"] 

24 verbose_name = "Metodo de Pago" 

25 verbose_name_plural = "Metodos de Pago" 

26 

27 def __str__(self): 

28 return self.name 

29 

30 @property 

31 def short_name(self): 

32 return self.name[:10] if len(self.name) > 10 else self.name 

33 

34 

35class Payment(RandomSlugModel, TimeStampedModel): 

36 """ 

37 Model for Payment 

38 """ 

39 

40 created_by = models.ForeignKey("users.User", on_delete=models.PROTECT, null=True, blank=True, editable=False) 

41 payment_method = models.ForeignKey("payments.OrganizationPaymentMethod", on_delete=models.PROTECT) 

42 

43 appointment = models.ForeignKey("appointments.Appointment", on_delete=models.CASCADE, related_name="payments", null=True) 

44 

45 date = models.DateField(auto_now_add=True) 

46 amount = MoneyField(max_digits=14, decimal_places=2, default_currency="MXN", default=0) 

47 

48 # allocated_amount = MoneyField(max_digits=14, decimal_places=2, default_currency="MXN", default=0, editable=False) 

49 # pending_to_allocate_amount = MoneyField( 

50 # max_digits=14, decimal_places=2, default_currency="MXN", default=0, editable=False 

51 # ) 

52 is_invoiceable = models.BooleanField(default=False) 

53 

54 class Meta: 

55 ordering = ["date"] 

56 verbose_name = "Pago" 

57 verbose_name_plural = "Pagos" 

58 

59 @property 

60 def allocated_amount(self): 

61 agg = self.allocations.aggregate(allocated_amount=models.Sum("amount")).get("allocated_amount", None) or 0 

62 return Money(agg or 0, "MXN") 

63 

64 @property 

65 def pending_to_allocate_amount(self): 

66 self.amount - self.allocated_amount 

67 

68 @cached_property 

69 def patient(self): 

70 "For backwards compatibility" 

71 return getattr(self.appointment, 'patient', None) 

72 

73 def __str__(self): 

74 return f"Pago del {self.date} por {self.amount} de {self.patient}" 

75 

76 

77class PaymentAllocation(RandomSlugModel, TimeStampedModel): 

78 """ 

79 Model for Payment Allocation 

80 """ 

81 

82 payment = models.ForeignKey("payments.Payment", on_delete=models.CASCADE, related_name="allocations") 

83 appointment_charge = models.ForeignKey( 

84 "appointments.AppointmentCharge", on_delete=models.CASCADE, related_name="payments" 

85 ) 

86 

87 amount = MoneyField(max_digits=14, decimal_places=2, default_currency="MXN", default=0) 

88 invoiced_amount = MoneyField(max_digits=14, decimal_places=2, default_currency="MXN", default=0) 

89 

90 class Meta: 

91 ordering = ["created_at"] 

92 verbose_name = "Aplicacion de Pago" 

93 verbose_name_plural = "Aplicaciones de Pago" 

94 

95 @property 

96 def is_invoiceable(self): 

97 return self.payment.is_invoiceable 

98 

99 @cached_property 

100 def is_external(self): 

101 return self.appointment_charge.appointment != self.payment.appointment 

102 

103 def __str__(self): 

104 external = f" (EXTERNO!)" if self.is_external else "" 

105 return f"Distribucion de Pago {self.payment.random_slug} al adeudo {self.appointment_charge.random_slug}" + external 

106 

107 

108class PaymentExport(RandomSlugModel, TimeStampedModel): 

109 """ 

110 Model for Payment exports 

111 """ 

112 

113 organization = models.ForeignKey("organizations.Organization", on_delete=models.CASCADE) 

114 practitioner = models.ForeignKey("practitioners.Practitioner", on_delete=models.CASCADE, blank=True, null=True) 

115 

116 from_date = models.DateField() 

117 to_date = models.DateField() 

118 export_file = models.FileField(upload_to="appointmentcharge/exports/", blank=True, null=True) 

119 

120 class Meta: 

121 ordering = ["organization", "practitioner", "-created_at"]