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
« 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
6from base.models import RandomSlugModel, TimeStampedModel
9class OrganizationPaymentMethod(RandomSlugModel, TimeStampedModel):
10 """
11 Model for Organization Payment Method
12 """
14 organization = models.ForeignKey(
15 "organizations.Organization", on_delete=models.PROTECT, related_name="payment_methods"
16 )
18 name = models.CharField(max_length=128)
19 is_active = models.BooleanField(default=True)
20 sat_id = models.CharField(max_length=2, editable=False)
22 class Meta:
23 ordering = ["organization", "created_at"]
24 verbose_name = "Metodo de Pago"
25 verbose_name_plural = "Metodos de Pago"
27 def __str__(self):
28 return self.name
30 @property
31 def short_name(self):
32 return self.name[:10] if len(self.name) > 10 else self.name
35class Payment(RandomSlugModel, TimeStampedModel):
36 """
37 Model for Payment
38 """
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)
43 appointment = models.ForeignKey("appointments.Appointment", on_delete=models.CASCADE, related_name="payments", null=True)
45 date = models.DateField(auto_now_add=True)
46 amount = MoneyField(max_digits=14, decimal_places=2, default_currency="MXN", default=0)
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)
54 class Meta:
55 ordering = ["date"]
56 verbose_name = "Pago"
57 verbose_name_plural = "Pagos"
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")
64 @property
65 def pending_to_allocate_amount(self):
66 self.amount - self.allocated_amount
68 @cached_property
69 def patient(self):
70 "For backwards compatibility"
71 return getattr(self.appointment, 'patient', None)
73 def __str__(self):
74 return f"Pago del {self.date} por {self.amount} de {self.patient}"
77class PaymentAllocation(RandomSlugModel, TimeStampedModel):
78 """
79 Model for Payment Allocation
80 """
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 )
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)
90 class Meta:
91 ordering = ["created_at"]
92 verbose_name = "Aplicacion de Pago"
93 verbose_name_plural = "Aplicaciones de Pago"
95 @property
96 def is_invoiceable(self):
97 return self.payment.is_invoiceable
99 @cached_property
100 def is_external(self):
101 return self.appointment_charge.appointment != self.payment.appointment
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
108class PaymentExport(RandomSlugModel, TimeStampedModel):
109 """
110 Model for Payment exports
111 """
113 organization = models.ForeignKey("organizations.Organization", on_delete=models.CASCADE)
114 practitioner = models.ForeignKey("practitioners.Practitioner", on_delete=models.CASCADE, blank=True, null=True)
116 from_date = models.DateField()
117 to_date = models.DateField()
118 export_file = models.FileField(upload_to="appointmentcharge/exports/", blank=True, null=True)
120 class Meta:
121 ordering = ["organization", "practitioner", "-created_at"]