#69 feat(Reconciliation):get purchases for reconciliation endpoint.
This commit is contained in:
		| @@ -0,0 +1,29 @@ | ||||
| # Generated by Django 5.0.6 on 2024-11-18 03:16 | ||||
|  | ||||
| import django.db.models.deletion | ||||
| from django.db import migrations, models | ||||
|  | ||||
|  | ||||
| class Migration(migrations.Migration): | ||||
|  | ||||
|     dependencies = [ | ||||
|         ('don_confiao', '0033_sale_payment_method'), | ||||
|     ] | ||||
|  | ||||
|     operations = [ | ||||
|         migrations.AddField( | ||||
|             model_name='sale', | ||||
|             name='reconciliation', | ||||
|             field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.RESTRICT, related_name='Sales', to='don_confiao.reconciliationjar'), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='payment', | ||||
|             name='type_payment', | ||||
|             field=models.CharField(choices=[('CASH', 'Efectivo'), ('CONFIAR', 'Confiar'), ('BANCOLOMBIA', 'Bancolombia')], default='CASH', max_length=30), | ||||
|         ), | ||||
|         migrations.AlterField( | ||||
|             model_name='sale', | ||||
|             name='payment_method', | ||||
|             field=models.CharField(choices=[('CASH', 'Efectivo'), ('CONFIAR', 'Confiar'), ('BANCOLOMBIA', 'Bancolombia')], default='CASH', max_length=30), | ||||
|         ), | ||||
|     ] | ||||
| @@ -62,6 +62,38 @@ class Product(models.Model): | ||||
|         return products_list | ||||
|  | ||||
|  | ||||
| class ReconciliationJar(models.Model): | ||||
|     is_valid = models.BooleanField(default=False) | ||||
|     date_time = models.DateTimeField() | ||||
|     description = models.CharField(max_length=255, null=True, blank=True) | ||||
|     reconcilier = models.CharField(max_length=255, null=False, blank=False) | ||||
|     cash_taken = models.DecimalField(max_digits=9, decimal_places=2) | ||||
|     cash_discrepancy = models.DecimalField(max_digits=9, decimal_places=2) | ||||
|  | ||||
|     def clean(self): | ||||
|         if not self.is_valid: | ||||
|             payments = Payment.get_reconciliation_jar_summary().payments | ||||
|         else: | ||||
|             payments = self.payment_set.all() | ||||
|  | ||||
|         payments_amount = Decimal(sum([p.amount for p in payments])) | ||||
|         reconciliation_ammount = Decimal(sum([ | ||||
|             self.cash_taken, | ||||
|             self.cash_discrepancy, | ||||
|         ])) | ||||
|  | ||||
|         equal_ammounts = reconciliation_ammount.compare(payments_amount) == Decimal('0') | ||||
|         if not equal_ammounts: | ||||
|             raise ValidationError( | ||||
|                 {"cash_taken": _("The taken ammount has discrepancy.")} | ||||
|             ) | ||||
|  | ||||
|     def add_payments(self, payments): | ||||
|         for payment in payments: | ||||
|             self.payment_set.add(payment) | ||||
|         self.is_valid = True | ||||
|  | ||||
|  | ||||
| class Sale(models.Model): | ||||
|     customer = models.ForeignKey(Customer, on_delete=models.PROTECT) | ||||
|     date = models.DateField("Date") | ||||
| @@ -74,6 +106,12 @@ class Sale(models.Model): | ||||
|         blank=False, | ||||
|         null=False | ||||
|     ) | ||||
|     reconciliation = models.ForeignKey( | ||||
|         ReconciliationJar, | ||||
|         on_delete=models.RESTRICT, | ||||
|         related_name='Sales', | ||||
|         null=True | ||||
|     ) | ||||
|  | ||||
|     def __str__(self): | ||||
|         return f"{self.date} {self.customer}" | ||||
| @@ -122,38 +160,6 @@ class ReconciliationJarSummary(): | ||||
|         return self._payments | ||||
|  | ||||
|  | ||||
| class ReconciliationJar(models.Model): | ||||
|     is_valid = models.BooleanField(default=False) | ||||
|     date_time = models.DateTimeField() | ||||
|     description = models.CharField(max_length=255, null=True, blank=True) | ||||
|     reconcilier = models.CharField(max_length=255, null=False, blank=False) | ||||
|     cash_taken = models.DecimalField(max_digits=9, decimal_places=2) | ||||
|     cash_discrepancy = models.DecimalField(max_digits=9, decimal_places=2) | ||||
|  | ||||
|     def clean(self): | ||||
|         if not self.is_valid: | ||||
|             payments = Payment.get_reconciliation_jar_summary().payments | ||||
|         else: | ||||
|             payments = self.payment_set.all() | ||||
|  | ||||
|         payments_amount = Decimal(sum([p.amount for p in payments])) | ||||
|         reconciliation_ammount = Decimal(sum([ | ||||
|             self.cash_taken, | ||||
|             self.cash_discrepancy, | ||||
|         ])) | ||||
|  | ||||
|         equal_ammounts = reconciliation_ammount.compare(payments_amount) == Decimal('0') | ||||
|         if not equal_ammounts: | ||||
|             raise ValidationError( | ||||
|                 {"cash_taken": _("The taken ammount has discrepancy.")} | ||||
|             ) | ||||
|  | ||||
|     def add_payments(self, payments): | ||||
|         for payment in payments: | ||||
|             self.payment_set.add(payment) | ||||
|         self.is_valid = True | ||||
|  | ||||
|  | ||||
| class Payment(models.Model): | ||||
|     date_time = models.DateTimeField() | ||||
|     type_payment = models.CharField( | ||||
|   | ||||
							
								
								
									
										111
									
								
								tienda_ilusion/don_confiao/tests/test_jar_reconciliation.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								tienda_ilusion/don_confiao/tests/test_jar_reconciliation.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | ||||
| from django.test import TestCase, Client | ||||
| from ..models import Sale, Product, SaleLine, Customer, ReconciliationJar | ||||
|  | ||||
| import json | ||||
|  | ||||
| class TestJarReconcliation(TestCase): | ||||
|     def setUp(self): | ||||
|         customer = Customer() | ||||
|         customer.name = 'Alejo Mono' | ||||
|         customer.save() | ||||
|  | ||||
|         self.client = Client() | ||||
|  | ||||
|         purchase = Sale() | ||||
|         purchase.customer = customer | ||||
|         purchase.date = "2024-07-30" | ||||
|         purchase.payment_method = 'CASH' | ||||
|         purchase.clean() | ||||
|         purchase.save() | ||||
|  | ||||
|         product = Product() | ||||
|         product.name = "cafe" | ||||
|         product.price = "72500" | ||||
|         product.save() | ||||
|  | ||||
|         line = SaleLine() | ||||
|         line.sale = purchase | ||||
|         line.product = product | ||||
|         line.quantity = "11" | ||||
|         line.unit_price = "72500" | ||||
|         line.save() | ||||
|         self.purchase = purchase | ||||
|  | ||||
|         purchase2 = Sale() | ||||
|         purchase2.customer = customer | ||||
|         purchase2.date = "2024-07-30" | ||||
|         purchase.payment_method = 'CASH' | ||||
|         purchase2.clean() | ||||
|         purchase2.save() | ||||
|  | ||||
|         line2 = SaleLine() | ||||
|         line2.sale = purchase2 | ||||
|         line2.product = product | ||||
|         line2.quantity = "27" | ||||
|         line2.unit_price = "72500" | ||||
|         line2.save() | ||||
|         self.purchase2 = purchase2 | ||||
|  | ||||
|         purchase3 = Sale() | ||||
|         purchase3.customer = customer | ||||
|         purchase3.date = "2024-07-30" | ||||
|         purchase3.payment_method = 'CASH' | ||||
|         purchase3.clean() | ||||
|         purchase3.save() | ||||
|  | ||||
|         line3 = SaleLine() | ||||
|         line3.sale = purchase3 | ||||
|         line3.product = product | ||||
|         line3.quantity = "37" | ||||
|         line3.unit_price = "72500" | ||||
|         line3.save() | ||||
|         self.purchase3 = purchase3 | ||||
|  | ||||
|         purchase4 = Sale() | ||||
|         purchase4.customer = customer | ||||
|         purchase4.date = "2024-07-30" | ||||
|         purchase4.payment_method = 'CONFIAR' | ||||
|         purchase4.clean() | ||||
|         purchase4.save() | ||||
|  | ||||
|         line4 = SaleLine() | ||||
|         line4.sale = purchase4 | ||||
|         line4.product = product | ||||
|         line4.quantity = "47" | ||||
|         line4.unit_price = "72500" | ||||
|         line4.save() | ||||
|         self.purchase4 = purchase4 | ||||
|  | ||||
|     def test_create_reconciliation_jar(self): | ||||
|         reconciliation = self._create_reconciliation() | ||||
|         self.assertTrue(isinstance(reconciliation, ReconciliationJar)) | ||||
|  | ||||
|     def test_get_purchases_for_reconciliation(self): | ||||
|         # link purchase to reconciliation to exclude from list | ||||
|         reconciliation = self._create_reconciliation() | ||||
|         self.purchase3.reconciliation = reconciliation | ||||
|         self.purchase3.clean() | ||||
|         self.purchase3.save() | ||||
|  | ||||
|         url = '/don_confiao/purchases/for_reconciliation' | ||||
|         response = self.client.get(url) | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|  | ||||
|         rawContent = response.content.decode('utf-8') | ||||
|         content = json.loads(rawContent) | ||||
|  | ||||
|         self.assertIn('CASH', content.keys()) | ||||
|         self.assertIn('CONFIAR', content.keys()) | ||||
|         self.assertEqual(2, len(content.get('CASH'))) | ||||
|         self.assertEqual(1, len(content.get('CONFIAR'))) | ||||
|         self.assertNotIn(str(37*72500), rawContent) | ||||
|         self.assertIn(str(47*72500), rawContent) | ||||
|  | ||||
|     def _create_reconciliation(self): | ||||
|         reconciliation = ReconciliationJar() | ||||
|         reconciliation.date_time = "2024-07-30" | ||||
|         reconciliation.cash_taken = 0 | ||||
|         reconciliation.cash_discrepancy = 0 | ||||
|         reconciliation.clean() | ||||
|         reconciliation.save() | ||||
|         return reconciliation | ||||
| @@ -28,5 +28,6 @@ urlpatterns = [ | ||||
|     path("resumen_compra/<int:id>", views.purchase_summary, name="purchase_summary"), | ||||
|     path("resumen_compra_json/<int:id>", views.purchase_json_summary, name="purchase_json_summary"), | ||||
|     path("payment_methods/all/select_format", views.payment_methods_to_select, name="payment_methods_to_select"), | ||||
|     path('purchases/for_reconciliation', views.sales_for_reconciliation, name='sales_for_reconciliation'), | ||||
|     path('api/', include(router.urls)), | ||||
| ] | ||||
|   | ||||
| @@ -178,6 +178,24 @@ def payment_methods_to_select(request): | ||||
|     return JsonResponse(methods, safe=False) | ||||
|  | ||||
|  | ||||
| def sales_for_reconciliation(request): | ||||
|     sales = Sale.objects.filter(reconciliation=None) | ||||
|     grouped_sales = {} | ||||
|     for sale in sales: | ||||
|         if sale.payment_method not in grouped_sales.keys(): | ||||
|             grouped_sales[sale.payment_method] = [] | ||||
|         grouped_sales[sale.payment_method].append({ | ||||
|             'id': sale.id, | ||||
|             'date': sale.date, | ||||
|             'payment_method': sale.payment_method, | ||||
|             'customer': { | ||||
|                 'id': sale.customer.id, | ||||
|                 'name': sale.customer.name, | ||||
|             }, | ||||
|             'total': sale.get_total(), | ||||
|         }) | ||||
|     return JsonResponse(grouped_sales, safe=False) | ||||
|  | ||||
| def _mask_phone(phone): | ||||
|     digits = str(phone)[-3:] if phone else " " * 3 | ||||
|     return "X" * 7 + digits | ||||
|   | ||||
		Reference in New Issue
	
	Block a user