From a9ab0f4ee715365bb0d1233f11a83f3392e6abac Mon Sep 17 00:00:00 2001 From: Mono Mono Date: Sat, 27 Jul 2024 15:21:04 -0500 Subject: [PATCH 1/8] test: move to tests folder. --- tienda_ilusion/don_confiao/{ => tests}/test_billing.py | 2 +- .../don_confiao/{ => tests}/test_reconciliation_jar_client.py | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) rename tienda_ilusion/don_confiao/{ => tests}/test_billing.py (98%) rename tienda_ilusion/don_confiao/{ => tests}/test_reconciliation_jar_client.py (93%) diff --git a/tienda_ilusion/don_confiao/test_billing.py b/tienda_ilusion/don_confiao/tests/test_billing.py similarity index 98% rename from tienda_ilusion/don_confiao/test_billing.py rename to tienda_ilusion/don_confiao/tests/test_billing.py index 89a5a43..69f6047 100644 --- a/tienda_ilusion/don_confiao/test_billing.py +++ b/tienda_ilusion/don_confiao/tests/test_billing.py @@ -1,6 +1,6 @@ from django.test import TestCase from django.core.exceptions import ValidationError -from .models import Payment, ReconciliationJar +from ..models import Payment, ReconciliationJar class TestBilling(TestCase): diff --git a/tienda_ilusion/don_confiao/test_reconciliation_jar_client.py b/tienda_ilusion/don_confiao/tests/test_reconciliation_jar_client.py similarity index 93% rename from tienda_ilusion/don_confiao/test_reconciliation_jar_client.py rename to tienda_ilusion/don_confiao/tests/test_reconciliation_jar_client.py index ad58d0e..ae9ba90 100644 --- a/tienda_ilusion/don_confiao/test_reconciliation_jar_client.py +++ b/tienda_ilusion/don_confiao/tests/test_reconciliation_jar_client.py @@ -1,9 +1,7 @@ from django.test import Client, TestCase from django.contrib.auth.models import AnonymousUser, User -#from django.conf import settings -#from .views import import_products, products -from .models import Payment +from ..models import Payment class TestReconciliationJarClient(TestCase): -- 2.45.2 From 599b62771c9b36e2d7ca0ada9b89b44ef4b6d221 Mon Sep 17 00:00:00 2001 From: Mono Mono Date: Sat, 27 Jul 2024 15:43:29 -0500 Subject: [PATCH 2/8] minor fix. --- tienda_ilusion/don_confiao/forms.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tienda_ilusion/don_confiao/forms.py b/tienda_ilusion/don_confiao/forms.py index 1c739f1..78d9080 100644 --- a/tienda_ilusion/don_confiao/forms.py +++ b/tienda_ilusion/don_confiao/forms.py @@ -1,4 +1,6 @@ from django import forms +from django.forms.models import inlineformset_factory + from django.forms.widgets import DateInput, DateTimeInput from .models import Sale, SaleLine, ReconciliationJar @@ -33,13 +35,14 @@ class PurchaseLineForm(forms.ModelForm): ] -LineaFormSet = forms.models.inlineformset_factory( +LineaFormSet = inlineformset_factory( Sale, SaleLine, extra=1, fields='__all__' ) + class ReconciliationJarForm(forms.ModelForm): class Meta: model = ReconciliationJar -- 2.45.2 From b4b6144611b7eae5373ee893699c1f7a7e661766 Mon Sep 17 00:00:00 2001 From: Mono Mono Date: Sat, 27 Jul 2024 17:12:52 -0500 Subject: [PATCH 3/8] view: calculando resumen de compra. --- tienda_ilusion/don_confiao/forms.py | 5 ++- .../don_confiao/static/js/sale_summary.js | 33 +++++++++++++++++++ .../templates/don_confiao/purchase.html | 6 ++-- .../tests/test_purchase_with_payment.py | 32 ++++++++++++++++++ tienda_ilusion/don_confiao/views.py | 6 ++-- 5 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 tienda_ilusion/don_confiao/static/js/sale_summary.js create mode 100644 tienda_ilusion/don_confiao/tests/test_purchase_with_payment.py diff --git a/tienda_ilusion/don_confiao/forms.py b/tienda_ilusion/don_confiao/forms.py index 78d9080..5d4efbb 100644 --- a/tienda_ilusion/don_confiao/forms.py +++ b/tienda_ilusion/don_confiao/forms.py @@ -34,6 +34,10 @@ class PurchaseLineForm(forms.ModelForm): "description", ] +class PurchaseSummaryForm(forms.Form): + quantity_lines = forms.IntegerField() + quantity_products = forms.IntegerField() + ammount = forms.DecimalField(max_digits=10, decimal_places=2) LineaFormSet = inlineformset_factory( Sale, @@ -42,7 +46,6 @@ LineaFormSet = inlineformset_factory( fields='__all__' ) - class ReconciliationJarForm(forms.ModelForm): class Meta: model = ReconciliationJar diff --git a/tienda_ilusion/don_confiao/static/js/sale_summary.js b/tienda_ilusion/don_confiao/static/js/sale_summary.js new file mode 100644 index 0000000..49ffe1b --- /dev/null +++ b/tienda_ilusion/don_confiao/static/js/sale_summary.js @@ -0,0 +1,33 @@ +const complete_form = document.getElementById('complete_form_purchase') +const quantityLines = document.getElementById('id_quantity_lines'); +const quantityProducts = document.getElementById('id_quantity_products'); +const ammountInput = document.getElementById('id_ammount'); +const idPrefix = 'id_saleline_set-'; + +complete_form.addEventListener('change', function(event){ + if (event.target.matches('[id^="${idPrefix}"][id$="-quantity"]')) { + calculateSummary(); + } + if (event.target.matches('[id^="id_saleline_set-"][id$="-unit_price"]')) { + calculateSummary(); + } +}); + + +function calculateSummary() { + let quantity = 0; + let ammount = 0; + const quantityInputs = document.querySelectorAll('[id^="id_saleline_set-"][id$="-quantity"]'); + const ids = Array.prototype.map.call(quantityInputs, function(input) { + return input.id.match(/\d+/)[0]; + }); + ids.forEach(function(id) { + let lineQuantity = document.getElementById(`id_saleline_set-${id}-quantity`) + let linePrice = document.getElementById(`id_saleline_set-${id}-unit_price`) + quantity += parseFloat(lineQuantity.value); + ammount += parseFloat(linePrice.value) * parseFloat(lineQuantity.value); + }); + quantityProducts.value = quantity; + quantityLines.value = quantityInputs.length; + ammountInput.value = ammount; +} diff --git a/tienda_ilusion/don_confiao/templates/don_confiao/purchase.html b/tienda_ilusion/don_confiao/templates/don_confiao/purchase.html index d174357..b9caf9d 100644 --- a/tienda_ilusion/don_confiao/templates/don_confiao/purchase.html +++ b/tienda_ilusion/don_confiao/templates/don_confiao/purchase.html @@ -1,8 +1,8 @@ {% load static %} -
+ {% csrf_token %} - {{ sale_form}} + {{ sale_form }} {{ linea_formset.management_form }}
{% for form in linea_formset %} @@ -13,7 +13,9 @@
{% endfor %} + {{ summary_form }}
+
diff --git a/tienda_ilusion/don_confiao/tests/test_purchase_with_payment.py b/tienda_ilusion/don_confiao/tests/test_purchase_with_payment.py new file mode 100644 index 0000000..d906b97 --- /dev/null +++ b/tienda_ilusion/don_confiao/tests/test_purchase_with_payment.py @@ -0,0 +1,32 @@ +from django.test import Client, TestCase + +from ..models import Payment, Sale + +class TestPurchaseWithPayment(TestCase): + def setUp(self): + self.client = Client() + + def test_generate_payment_when_it_has_payment(self): + 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": "2", + "saleline_set-0-unit_price": "22030", + "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)) diff --git a/tienda_ilusion/don_confiao/views.py b/tienda_ilusion/don_confiao/views.py index efa121d..9b29415 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 +from .forms import ImportProductsForm, PurchaseForm, LineaFormSet, ReconciliationJarForm, PurchaseSummaryForm import csv import io @@ -29,12 +29,14 @@ def buy(request): else: sale_form = PurchaseForm() sale_linea_form = LineaFormSet() + sale_summary_form = PurchaseSummaryForm() return render( request, 'don_confiao/purchase.html', { 'sale_form': sale_form, - 'linea_formset': sale_linea_form + 'linea_formset': sale_linea_form, + 'summary_form': sale_summary_form, } ) -- 2.45.2 From c993225daf78896c2a2e18e9ab0a46f4ed25e8de Mon Sep 17 00:00:00 2001 From: Mono Mono Date: Sat, 27 Jul 2024 17:29:09 -0500 Subject: [PATCH 4/8] refactor: string to variable. --- .../don_confiao/static/js/sale_summary.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tienda_ilusion/don_confiao/static/js/sale_summary.js b/tienda_ilusion/don_confiao/static/js/sale_summary.js index 49ffe1b..5545163 100644 --- a/tienda_ilusion/don_confiao/static/js/sale_summary.js +++ b/tienda_ilusion/don_confiao/static/js/sale_summary.js @@ -3,12 +3,16 @@ const quantityLines = document.getElementById('id_quantity_lines'); const quantityProducts = document.getElementById('id_quantity_products'); const ammountInput = document.getElementById('id_ammount'); const idPrefix = 'id_saleline_set-'; +const quantitySuffix = '-quantity'; +const priceSuffix = '-unit_price'; +const quantityRegexSelector = `[id^="${idPrefix}"][id$="${quantitySuffix}"]`; +const priceRegexSelector = `[id^="${idPrefix}"][id$="${priceSuffix}"]`; complete_form.addEventListener('change', function(event){ - if (event.target.matches('[id^="${idPrefix}"][id$="-quantity"]')) { + if (event.target.matches(quantityRegexSelector)) { calculateSummary(); } - if (event.target.matches('[id^="id_saleline_set-"][id$="-unit_price"]')) { + if (event.target.matches(priceRegexSelector)) { calculateSummary(); } }); @@ -17,13 +21,13 @@ complete_form.addEventListener('change', function(event){ function calculateSummary() { let quantity = 0; let ammount = 0; - const quantityInputs = document.querySelectorAll('[id^="id_saleline_set-"][id$="-quantity"]'); + const quantityInputs = document.querySelectorAll(quantityRegexSelector); const ids = Array.prototype.map.call(quantityInputs, function(input) { return input.id.match(/\d+/)[0]; }); ids.forEach(function(id) { - let lineQuantity = document.getElementById(`id_saleline_set-${id}-quantity`) - let linePrice = document.getElementById(`id_saleline_set-${id}-unit_price`) + let lineQuantity = document.getElementById(`${idPrefix}${id}${quantitySuffix}`) + let linePrice = document.getElementById(`${idPrefix}${id}${priceSuffix}`) quantity += parseFloat(lineQuantity.value); ammount += parseFloat(linePrice.value) * parseFloat(lineQuantity.value); }); -- 2.45.2 From 83bab7818253ba0c09f07bd517944592f9f8e752 Mon Sep 17 00:00:00 2001 From: Mono Mono Date: Sat, 27 Jul 2024 17:30:33 -0500 Subject: [PATCH 5/8] view: Convertidos a solo lecturas los campos de resumen de compra. --- tienda_ilusion/don_confiao/forms.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tienda_ilusion/don_confiao/forms.py b/tienda_ilusion/don_confiao/forms.py index 5d4efbb..5c49274 100644 --- a/tienda_ilusion/don_confiao/forms.py +++ b/tienda_ilusion/don_confiao/forms.py @@ -35,9 +35,9 @@ class PurchaseLineForm(forms.ModelForm): ] class PurchaseSummaryForm(forms.Form): - quantity_lines = forms.IntegerField() - quantity_products = forms.IntegerField() - ammount = forms.DecimalField(max_digits=10, decimal_places=2) + quantity_lines = forms.IntegerField(widget=forms.NumberInput(attrs={'readonly': 'readonly'})) + quantity_products = forms.IntegerField(widget=forms.NumberInput(attrs={'readonly': 'readonly'})) + ammount = forms.DecimalField(max_digits=10, decimal_places=2, widget=forms.NumberInput(attrs={'readonly': 'readonly'})) LineaFormSet = inlineformset_factory( Sale, -- 2.45.2 From 7b74e4d381f3a042d4428d477965ff22365da128 Mon Sep 17 00:00:00 2001 From: Mono Mono Date: Sat, 27 Jul 2024 17:47:04 -0500 Subject: [PATCH 6/8] fix: typo. --- tienda_ilusion/don_confiao/models.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tienda_ilusion/don_confiao/models.py b/tienda_ilusion/don_confiao/models.py index 9de8188..ba69ea1 100644 --- a/tienda_ilusion/don_confiao/models.py +++ b/tienda_ilusion/don_confiao/models.py @@ -54,7 +54,7 @@ class Product(models.Model): return self.name -class PyamentMethods(models.TextChoices): +class PaymentMethods(models.TextChoices): CASH = 'CASH', _('Cash') CONFIAR = 'CONFIAR', _('Confiar') BANCOLOMBIA = 'BANCOLOMBIA', _('Bancolombia') @@ -112,8 +112,8 @@ class Payment(models.Model): date_time = models.DateTimeField() type_payment = models.CharField( max_length=30, - choices=PyamentMethods.choices, - default=PyamentMethods.CASH + choices=PaymentMethods.choices, + default=PaymentMethods.CASH ) amount = models.DecimalField(max_digits=9, decimal_places=2) reconciliation_jar = models.ForeignKey( @@ -129,7 +129,7 @@ class Payment(models.Model): def get_reconciliation_jar_summary(cls): return ReconciliationJarSummary( cls.objects.filter( - type_payment=PyamentMethods.CASH, + type_payment=PaymentMethods.CASH, reconciliation_jar=None ) ) -- 2.45.2 From a636264e4fee2ed2fb98a51decc0d622691bd327 Mon Sep 17 00:00:00 2001 From: Mono Mono Date: Sat, 27 Jul 2024 17:48:09 -0500 Subject: [PATCH 7/8] view: agregando forma de pago en formulario de compra. --- tienda_ilusion/don_confiao/forms.py | 22 +++++++++++++++---- .../templates/don_confiao/purchase.html | 2 +- tienda_ilusion/don_confiao/views.py | 1 + 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/tienda_ilusion/don_confiao/forms.py b/tienda_ilusion/don_confiao/forms.py index 5c49274..809e877 100644 --- a/tienda_ilusion/don_confiao/forms.py +++ b/tienda_ilusion/don_confiao/forms.py @@ -3,8 +3,9 @@ from django.forms.models import inlineformset_factory from django.forms.widgets import DateInput, DateTimeInput -from .models import Sale, SaleLine, ReconciliationJar +from .models import Sale, SaleLine, ReconciliationJar, PaymentMethods +readonly_number_widget = forms.NumberInput(attrs={'readonly': 'readonly'}) class ImportProductsForm(forms.Form): csv_file = forms.FileField() @@ -34,10 +35,23 @@ class PurchaseLineForm(forms.ModelForm): "description", ] + class PurchaseSummaryForm(forms.Form): - quantity_lines = forms.IntegerField(widget=forms.NumberInput(attrs={'readonly': 'readonly'})) - quantity_products = forms.IntegerField(widget=forms.NumberInput(attrs={'readonly': 'readonly'})) - ammount = forms.DecimalField(max_digits=10, decimal_places=2, widget=forms.NumberInput(attrs={'readonly': 'readonly'})) + quantity_lines = forms.IntegerField( + widget=readonly_number_widget + ) + quantity_products = forms.IntegerField( + widget=readonly_number_widget + ) + ammount = forms.DecimalField( + max_digits=10, + decimal_places=2, + widget=readonly_number_widget + ) + payment_method = forms.ChoiceField( + choices=PaymentMethods.choices, + widget=forms.Select(attrs={'disabled': 'disabled'}) + ) LineaFormSet = inlineformset_factory( Sale, diff --git a/tienda_ilusion/don_confiao/templates/don_confiao/purchase.html b/tienda_ilusion/don_confiao/templates/don_confiao/purchase.html index b9caf9d..2095a43 100644 --- a/tienda_ilusion/don_confiao/templates/don_confiao/purchase.html +++ b/tienda_ilusion/don_confiao/templates/don_confiao/purchase.html @@ -13,8 +13,8 @@ {% endfor %} - {{ summary_form }} + {{ summary_form }}
diff --git a/tienda_ilusion/don_confiao/views.py b/tienda_ilusion/don_confiao/views.py index 9b29415..eabd664 100644 --- a/tienda_ilusion/don_confiao/views.py +++ b/tienda_ilusion/don_confiao/views.py @@ -19,6 +19,7 @@ def buy(request): if request.method == "POST": sale_form = PurchaseForm(request.POST) sale_linea_form = LineaFormSet(request.POST) + sale_summary_form = PurchaseSummaryForm(request.POST) if sale_form.is_valid() and sale_linea_form.is_valid(): sale = sale_form.save() lines = sale_linea_form.save(commit=False) -- 2.45.2 From b2ab71e7a40d20a3a061953e13191404e0c84fb9 Mon Sep 17 00:00:00 2001 From: Mono Mono Date: Sat, 3 Aug 2024 09:42:32 -0500 Subject: [PATCH 8/8] payment: remove unused test. --- .../tests/test_purchase_with_payment.py | 52 ++++++++++--------- 1 file changed, 28 insertions(+), 24 deletions(-) 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 d906b97..e9d6d36 100644 --- a/tienda_ilusion/don_confiao/tests/test_purchase_with_payment.py +++ b/tienda_ilusion/don_confiao/tests/test_purchase_with_payment.py @@ -6,27 +6,31 @@ class TestPurchaseWithPayment(TestCase): def setUp(self): self.client = Client() - def test_generate_payment_when_it_has_payment(self): - 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": "2", - "saleline_set-0-unit_price": "22030", - "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)) + # 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) -- 2.45.2