From 1a54426af6aa79c25c7732b64065261c1ef1cfd4 Mon Sep 17 00:00:00 2001
From: Mono Mono <monomono@disroot.org>
Date: Sat, 17 Aug 2024 12:49:43 -0500
Subject: [PATCH 1/9] style(models): minor fix.

---
 tienda_ilusion/don_confiao/models.py | 1 -
 1 file changed, 1 deletion(-)

diff --git a/tienda_ilusion/don_confiao/models.py b/tienda_ilusion/don_confiao/models.py
index 62d6fd6..5e48b3d 100644
--- a/tienda_ilusion/don_confiao/models.py
+++ b/tienda_ilusion/don_confiao/models.py
@@ -12,7 +12,6 @@ class Customer(models.Model):
     def __str__(self):
         return self.name
 
-
 class MeasuringUnits(models.TextChoices):
     UNIT = 'UNIT', _('Unit')
 

From 204bdbcb33b29e2f4b8b49fc667b7346d1bc8b29 Mon Sep 17 00:00:00 2001
From: Mono Mono <monomono@disroot.org>
Date: Sat, 17 Aug 2024 12:51:38 -0500
Subject: [PATCH 2/9] limit to CASH methods type in purchases.

---
 tienda_ilusion/don_confiao/forms.py           |  3 +-
 .../tests/test_purchase_with_payment.py       | 68 +++++++++++--------
 2 files changed, 40 insertions(+), 31 deletions(-)

diff --git a/tienda_ilusion/don_confiao/forms.py b/tienda_ilusion/don_confiao/forms.py
index 0e877ea..0142b04 100644
--- a/tienda_ilusion/don_confiao/forms.py
+++ b/tienda_ilusion/don_confiao/forms.py
@@ -50,8 +50,7 @@ class PurchaseSummaryForm(forms.Form):
         widget=readonly_number_widget
     )
     payment_method = forms.ChoiceField(
-        choices=PaymentMethods.choices,
-        widget=forms.Select(attrs={'disabled': 'disabled'})
+        choices=[(PaymentMethods.CASH, PaymentMethods.CASH)],
     )
 
 
diff --git a/tienda_ilusion/don_confiao/tests/test_purchase_with_payment.py b/tienda_ilusion/don_confiao/tests/test_purchase_with_payment.py
index a27904c..bee9de2 100644
--- a/tienda_ilusion/don_confiao/tests/test_purchase_with_payment.py
+++ b/tienda_ilusion/don_confiao/tests/test_purchase_with_payment.py
@@ -1,37 +1,47 @@
 from django.test import Client, TestCase
 
-from ..models import Payment, Sale
+from ..models import Payment, Sale, Product, Customer
 
 
 class TestPurchaseWithPayment(TestCase):
     def setUp(self):
         self.client = Client()
+        self.product = Product()
+        self.product.name = "Arroz"
+        self.product.price = 5000
+        self.product.save()
+        customer = Customer()
+        customer.name = "Noelba Lopez"
+        customer.save()
+        self.customer = customer
 
-    # def test_generate_payment_when_it_has_payment(self):
-    #     quantity = 2
-    #     unit_price = 2500
-    #     total = 5000
-    #     response = self.client.post(
-    #         '/don_confiao/comprar',
-    #         {
-    #             "customer": "Noelba Lopez",
-    #             "date": "2024-07-27",
-    #             "phone": "3010101000",
-    #             "description": "Venta de contado",
-    #             "saleline_set-TOTAL_FORMS": "1",
-    #             "saleline_set-INITIAL_FORMS": "0",
-    #             "saleline_set-MIN_NUM_FORMS": "0",
-    #             "saleline_set-MAX_NUM_FORMS": "1000",
-    #             "saleline_set-0-product": "Papayita",
-    #             "saleline_set-0-quantity": str(quantity),
-    #             "saleline_set-0-unit_price": str(unit_price),
-    #             "saleline_set-0-description": "Linea de Venta",
-    #             "saleline_set-0-sale": "",
-    #             "saleline_set-0-id": "",
-    #         }
-    #     )
-    #     purchases = Sale.objects.all()
-    #     self.assertEqual(1, len(purchases))
-    #     payments = Payment.objects.all()
-    #     self.assertEqual(1, len(payments))
-    #     self.assertEqual(total, payments[0].ammount)
+    def test_generate_payment_when_it_has_payment(self):
+        quantity = 2
+        unit_price = 2500
+        total = 5000
+        response = self.client.post(
+            '/don_confiao/comprar',
+            {
+                "customer": str(self.customer.id),
+                "date": "2024-07-27",
+                "phone": "3010101000",
+                "description": "Venta de contado",
+                "saleline_set-TOTAL_FORMS": "1",
+                "saleline_set-INITIAL_FORMS": "0",
+                "saleline_set-MIN_NUM_FORMS": "0",
+                "saleline_set-MAX_NUM_FORMS": "1000",
+                "saleline_set-0-product": str(self.product.id),
+                "saleline_set-0-quantity": str(quantity),
+                "saleline_set-0-unit_price": str(unit_price),
+                "saleline_set-0-description": "Linea de Venta",
+                "saleline_set-0-sale": "",
+                "saleline_set-0-id": "",
+                "quantity_lines": "1",
+                "quantity_products": str(quantity),
+                "ammount": str(quantity * unit_price),
+                "payment_method": "CASH",
+            }
+        )
+        purchases = Sale.objects.all()
+        self.assertEqual(1, len(purchases))
+        payments = Payment.objects.all()

From 4c0c4737ac376a36bb3e79b46604792bb70e806e Mon Sep 17 00:00:00 2001
From: Mono Mono <monomono@disroot.org>
Date: Sat, 17 Aug 2024 14:29:20 -0500
Subject: [PATCH 3/9] migration(Customer): default None.

---
 .../migrations/0029_alter_customer_name.py     | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 tienda_ilusion/don_confiao/migrations/0029_alter_customer_name.py

diff --git a/tienda_ilusion/don_confiao/migrations/0029_alter_customer_name.py b/tienda_ilusion/don_confiao/migrations/0029_alter_customer_name.py
new file mode 100644
index 0000000..dcbceb0
--- /dev/null
+++ b/tienda_ilusion/don_confiao/migrations/0029_alter_customer_name.py
@@ -0,0 +1,18 @@
+# Generated by Django 5.0.6 on 2024-08-17 19:28
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('don_confiao', '0028_alter_customer_address'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='customer',
+            name='name',
+            field=models.CharField(default=None, max_length=100),
+        ),
+    ]

From 2a9a73c4305ee1ae5fea2d80198f09eeb0cfd568 Mon Sep 17 00:00:00 2001
From: Mono Mono <monomono@disroot.org>
Date: Sat, 17 Aug 2024 14:34:10 -0500
Subject: [PATCH 4/9] refactor(Forms): rename varible.

---
 tienda_ilusion/don_confiao/forms.py | 2 +-
 tienda_ilusion/don_confiao/views.py | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/tienda_ilusion/don_confiao/forms.py b/tienda_ilusion/don_confiao/forms.py
index 0142b04..241dac3 100644
--- a/tienda_ilusion/don_confiao/forms.py
+++ b/tienda_ilusion/don_confiao/forms.py
@@ -54,7 +54,7 @@ class PurchaseSummaryForm(forms.Form):
     )
 
 
-LineaFormSet = inlineformset_factory(
+SaleLineFormSet = inlineformset_factory(
     Sale,
     SaleLine,
     extra=1,
diff --git a/tienda_ilusion/don_confiao/views.py b/tienda_ilusion/don_confiao/views.py
index 563a6a6..7152f8e 100644
--- a/tienda_ilusion/don_confiao/views.py
+++ b/tienda_ilusion/don_confiao/views.py
@@ -5,7 +5,7 @@ from django.core.exceptions import ValidationError
 from django.views.generic import ListView
 
 from .models import Sale, Product, ProductCategory, Payment
-from .forms import ImportProductsForm, PurchaseForm, LineaFormSet, ReconciliationJarForm, PurchaseSummaryForm
+from .forms import ImportProductsForm, PurchaseForm, SaleLineFormSet, ReconciliationJarForm, PurchaseSummaryForm
 
 import csv
 import io
@@ -18,7 +18,7 @@ def index(request):
 def buy(request):
     if request.method == "POST":
         sale_form = PurchaseForm(request.POST)
-        sale_linea_form = LineaFormSet(request.POST)
+        sale_linea_form = SaleLineFormSet(request.POST)
         sale_summary_form = PurchaseSummaryForm(request.POST)
         if sale_form.is_valid() and sale_linea_form.is_valid():
             sale = sale_form.save()
@@ -29,7 +29,7 @@ def buy(request):
             return HttpResponseRedirect("compras")
     else:
         sale_form = PurchaseForm()
-        sale_linea_form = LineaFormSet()
+        sale_linea_form = SaleLineFormSet()
         sale_summary_form = PurchaseSummaryForm()
     return render(
         request,

From a401029082c61bbab205a8f591875e21b0808ab7 Mon Sep 17 00:00:00 2001
From: Mono Mono <monomono@disroot.org>
Date: Sat, 17 Aug 2024 14:50:49 -0500
Subject: [PATCH 5/9] fix view(Buy): rewrite save process.

---
 tienda_ilusion/don_confiao/views.py | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/tienda_ilusion/don_confiao/views.py b/tienda_ilusion/don_confiao/views.py
index 7152f8e..f89f383 100644
--- a/tienda_ilusion/don_confiao/views.py
+++ b/tienda_ilusion/don_confiao/views.py
@@ -20,12 +20,10 @@ def buy(request):
         sale_form = PurchaseForm(request.POST)
         sale_linea_form = SaleLineFormSet(request.POST)
         sale_summary_form = PurchaseSummaryForm(request.POST)
-        if sale_form.is_valid() and sale_linea_form.is_valid():
+        if sale_form.is_valid() and sale_linea_form.is_valid() and sale_summary_form.is_valid():
             sale = sale_form.save()
-            lines = sale_linea_form.save(commit=False)
-            for line in lines:
-                line.sale = sale
-                line.save()
+            sale_linea_form.instance = sale
+            sale_linea_form.save()
             return HttpResponseRedirect("compras")
     else:
         sale_form = PurchaseForm()

From 7eb8f40d7aa711b428596bc1f6be5f7b0b09932f Mon Sep 17 00:00:00 2001
From: Mono Mono <monomono@disroot.org>
Date: Sat, 17 Aug 2024 14:57:46 -0500
Subject: [PATCH 6/9] style(views): minor fix.

---
 tienda_ilusion/don_confiao/views.py | 17 +++++++++++------
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/tienda_ilusion/don_confiao/views.py b/tienda_ilusion/don_confiao/views.py
index f89f383..0b5d969 100644
--- a/tienda_ilusion/don_confiao/views.py
+++ b/tienda_ilusion/don_confiao/views.py
@@ -18,23 +18,28 @@ def index(request):
 def buy(request):
     if request.method == "POST":
         sale_form = PurchaseForm(request.POST)
-        sale_linea_form = SaleLineFormSet(request.POST)
+        line_formset = SaleLineFormSet(request.POST)
         sale_summary_form = PurchaseSummaryForm(request.POST)
-        if sale_form.is_valid() and sale_linea_form.is_valid() and sale_summary_form.is_valid():
+        forms_are_valid = all([
+            sale_form.is_valid(),
+            line_formset.is_valid(),
+            sale_summary_form.is_valid()
+        ])
+        if forms_are_valid:
             sale = sale_form.save()
-            sale_linea_form.instance = sale
-            sale_linea_form.save()
+            line_formset.instance = sale
+            line_formset.save()
             return HttpResponseRedirect("compras")
     else:
         sale_form = PurchaseForm()
-        sale_linea_form = SaleLineFormSet()
+        line_formset = SaleLineFormSet()
         sale_summary_form = PurchaseSummaryForm()
     return render(
         request,
         'don_confiao/purchase.html',
         {
             'sale_form': sale_form,
-            'linea_formset': sale_linea_form,
+            'linea_formset': line_formset,
             'summary_form': sale_summary_form,
         }
     )

From 1f37e57e00092f68a0eaf9d2cd99166ebaabcf3a Mon Sep 17 00:00:00 2001
From: Mono Mono <monomono@disroot.org>
Date: Sat, 17 Aug 2024 15:07:43 -0500
Subject: [PATCH 7/9] feat(Buy): add transaction on buy process.

---
 tienda_ilusion/don_confiao/views.py | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/tienda_ilusion/don_confiao/views.py b/tienda_ilusion/don_confiao/views.py
index 0b5d969..7c837bc 100644
--- a/tienda_ilusion/don_confiao/views.py
+++ b/tienda_ilusion/don_confiao/views.py
@@ -1,8 +1,7 @@
 from django.shortcuts import render
 from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
-from django.template import loader
-from django.core.exceptions import ValidationError
 from django.views.generic import ListView
+from django.db import transaction
 
 from .models import Sale, Product, ProductCategory, Payment
 from .forms import ImportProductsForm, PurchaseForm, SaleLineFormSet, ReconciliationJarForm, PurchaseSummaryForm
@@ -26,9 +25,10 @@ def buy(request):
             sale_summary_form.is_valid()
         ])
         if forms_are_valid:
-            sale = sale_form.save()
-            line_formset.instance = sale
-            line_formset.save()
+            with transaction.atomic():
+                sale = sale_form.save()
+                line_formset.instance = sale
+                line_formset.save()
             return HttpResponseRedirect("compras")
     else:
         sale_form = PurchaseForm()

From 0c95c216662fb5871e8392a9d85e7cd3b077becd Mon Sep 17 00:00:00 2001
From: Mono Mono <monomono@disroot.org>
Date: Sat, 17 Aug 2024 16:39:29 -0500
Subject: [PATCH 8/9] feat(Payments): Generate cash payment with purchase.

---
 tienda_ilusion/don_confiao/models.py          | 23 ++++++++++++++++++-
 .../tests/test_purchase_with_payment.py       |  6 ++++-
 tienda_ilusion/don_confiao/views.py           | 10 ++++++--
 3 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/tienda_ilusion/don_confiao/models.py b/tienda_ilusion/don_confiao/models.py
index 5e48b3d..71772d1 100644
--- a/tienda_ilusion/don_confiao/models.py
+++ b/tienda_ilusion/don_confiao/models.py
@@ -3,6 +3,7 @@ from django.utils.translation import gettext_lazy as _
 from django.core.exceptions import ValidationError
 
 from decimal import Decimal
+from datetime import datetime
 
 
 class Customer(models.Model):
@@ -118,7 +119,7 @@ class ReconciliationJar(models.Model):
             self.payment_set.add(payment)
         self.is_valid = True
 
-        
+
 class Payment(models.Model):
     date_time = models.DateTimeField()
     type_payment = models.CharField(
@@ -144,3 +145,23 @@ class Payment(models.Model):
                 reconciliation_jar=None
             )
         )
+
+    @classmethod
+    def total_payment_from_sale(cls, payment_method, sale):
+        payment = cls()
+        payment.date_time = datetime.today()
+        payment.type_payment = payment_method
+        payment.amount = sale.get_total()
+        payment.clean()
+        payment.save()
+
+        payment_sale = PaymentSale()
+        payment_sale.payment = payment
+        payment_sale.sale = sale
+        payment_sale.clean()
+        payment_sale.save()
+
+
+class PaymentSale(models.Model):
+    payment = models.ForeignKey(Payment, on_delete=models.CASCADE)
+    sale = models.ForeignKey(Sale, on_delete=models.CASCADE)
diff --git a/tienda_ilusion/don_confiao/tests/test_purchase_with_payment.py b/tienda_ilusion/don_confiao/tests/test_purchase_with_payment.py
index bee9de2..962aaa2 100644
--- a/tienda_ilusion/don_confiao/tests/test_purchase_with_payment.py
+++ b/tienda_ilusion/don_confiao/tests/test_purchase_with_payment.py
@@ -19,7 +19,7 @@ class TestPurchaseWithPayment(TestCase):
         quantity = 2
         unit_price = 2500
         total = 5000
-        response = self.client.post(
+        self.client.post(
             '/don_confiao/comprar',
             {
                 "customer": str(self.customer.id),
@@ -42,6 +42,10 @@ class TestPurchaseWithPayment(TestCase):
                 "payment_method": "CASH",
             }
         )
+
         purchases = Sale.objects.all()
         self.assertEqual(1, len(purchases))
         payments = Payment.objects.all()
+        self.assertEqual(1, len(payments))
+        self.assertEqual(total, payments[0].amount)
+        self.assertEqual('CASH', payments[0].type_payment)
diff --git a/tienda_ilusion/don_confiao/views.py b/tienda_ilusion/don_confiao/views.py
index 7c837bc..63169c4 100644
--- a/tienda_ilusion/don_confiao/views.py
+++ b/tienda_ilusion/don_confiao/views.py
@@ -3,7 +3,7 @@ from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
 from django.views.generic import ListView
 from django.db import transaction
 
-from .models import Sale, Product, ProductCategory, Payment
+from .models import Sale, Product, ProductCategory, Payment, PaymentMethods
 from .forms import ImportProductsForm, PurchaseForm, SaleLineFormSet, ReconciliationJarForm, PurchaseSummaryForm
 
 import csv
@@ -13,7 +13,6 @@ import io
 def index(request):
     return render(request, 'don_confiao/index.html')
 
-
 def buy(request):
     if request.method == "POST":
         sale_form = PurchaseForm(request.POST)
@@ -24,11 +23,18 @@ def buy(request):
             line_formset.is_valid(),
             sale_summary_form.is_valid()
         ])
+        payment_method = request.POST.get('payment_method')
+        valid_payment_methods = [PaymentMethods.CASH]
+        valid_payment_method = payment_method in valid_payment_methods
         if forms_are_valid:
             with transaction.atomic():
                 sale = sale_form.save()
                 line_formset.instance = sale
                 line_formset.save()
+                Payment.total_payment_from_sale(
+                    payment_method,
+                    sale
+                )
             return HttpResponseRedirect("compras")
     else:
         sale_form = PurchaseForm()

From f847a0e16a960a0c4c1f79353ab7175152262240 Mon Sep 17 00:00:00 2001
From: Mono Mono <monomono@disroot.org>
Date: Sat, 17 Aug 2024 16:40:13 -0500
Subject: [PATCH 9/9] migation.

---
 .../migrations/0030_paymentsale.py            | 22 +++++++++++++++++++
 1 file changed, 22 insertions(+)
 create mode 100644 tienda_ilusion/don_confiao/migrations/0030_paymentsale.py

diff --git a/tienda_ilusion/don_confiao/migrations/0030_paymentsale.py b/tienda_ilusion/don_confiao/migrations/0030_paymentsale.py
new file mode 100644
index 0000000..77d4522
--- /dev/null
+++ b/tienda_ilusion/don_confiao/migrations/0030_paymentsale.py
@@ -0,0 +1,22 @@
+# Generated by Django 5.0.6 on 2024-08-17 21:00
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('don_confiao', '0029_alter_customer_name'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='PaymentSale',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('payment', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='don_confiao.payment')),
+                ('sale', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='don_confiao.sale')),
+            ],
+        ),
+    ]