Merge pull request 'Adicionar resumen de compra en el formulario de compra' (#14) from pagar_una_compra_en_efectivo_#13 into main
Reviewed-on: OneTeam/don_confiao#14
This commit is contained in:
		@@ -1,8 +1,11 @@
 | 
				
			|||||||
from django import forms
 | 
					from django import forms
 | 
				
			||||||
 | 
					from django.forms.models import inlineformset_factory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.forms.widgets import DateInput, DateTimeInput
 | 
					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):
 | 
					class ImportProductsForm(forms.Form):
 | 
				
			||||||
    csv_file = forms.FileField()
 | 
					    csv_file = forms.FileField()
 | 
				
			||||||
@@ -33,7 +36,24 @@ class PurchaseLineForm(forms.ModelForm):
 | 
				
			|||||||
        ]
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LineaFormSet = forms.models.inlineformset_factory(
 | 
					class PurchaseSummaryForm(forms.Form):
 | 
				
			||||||
 | 
					    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,
 | 
					    Sale,
 | 
				
			||||||
    SaleLine,
 | 
					    SaleLine,
 | 
				
			||||||
    extra=1,
 | 
					    extra=1,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -54,7 +54,7 @@ class Product(models.Model):
 | 
				
			|||||||
        return self.name
 | 
					        return self.name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PyamentMethods(models.TextChoices):
 | 
					class PaymentMethods(models.TextChoices):
 | 
				
			||||||
    CASH = 'CASH', _('Cash')
 | 
					    CASH = 'CASH', _('Cash')
 | 
				
			||||||
    CONFIAR = 'CONFIAR', _('Confiar')
 | 
					    CONFIAR = 'CONFIAR', _('Confiar')
 | 
				
			||||||
    BANCOLOMBIA = 'BANCOLOMBIA', _('Bancolombia')
 | 
					    BANCOLOMBIA = 'BANCOLOMBIA', _('Bancolombia')
 | 
				
			||||||
@@ -112,8 +112,8 @@ class Payment(models.Model):
 | 
				
			|||||||
    date_time = models.DateTimeField()
 | 
					    date_time = models.DateTimeField()
 | 
				
			||||||
    type_payment = models.CharField(
 | 
					    type_payment = models.CharField(
 | 
				
			||||||
        max_length=30,
 | 
					        max_length=30,
 | 
				
			||||||
        choices=PyamentMethods.choices,
 | 
					        choices=PaymentMethods.choices,
 | 
				
			||||||
        default=PyamentMethods.CASH
 | 
					        default=PaymentMethods.CASH
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    amount = models.DecimalField(max_digits=9, decimal_places=2)
 | 
					    amount = models.DecimalField(max_digits=9, decimal_places=2)
 | 
				
			||||||
    reconciliation_jar = models.ForeignKey(
 | 
					    reconciliation_jar = models.ForeignKey(
 | 
				
			||||||
@@ -129,7 +129,7 @@ class Payment(models.Model):
 | 
				
			|||||||
    def get_reconciliation_jar_summary(cls):
 | 
					    def get_reconciliation_jar_summary(cls):
 | 
				
			||||||
        return ReconciliationJarSummary(
 | 
					        return ReconciliationJarSummary(
 | 
				
			||||||
            cls.objects.filter(
 | 
					            cls.objects.filter(
 | 
				
			||||||
                type_payment=PyamentMethods.CASH,
 | 
					                type_payment=PaymentMethods.CASH,
 | 
				
			||||||
                reconciliation_jar=None
 | 
					                reconciliation_jar=None
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										37
									
								
								tienda_ilusion/don_confiao/static/js/sale_summary.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								tienda_ilusion/don_confiao/static/js/sale_summary.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					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-';
 | 
				
			||||||
 | 
					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(quantityRegexSelector)) {
 | 
				
			||||||
 | 
					        calculateSummary();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (event.target.matches(priceRegexSelector)) {
 | 
				
			||||||
 | 
					        calculateSummary();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function calculateSummary() {
 | 
				
			||||||
 | 
					    let quantity = 0;
 | 
				
			||||||
 | 
					    let ammount = 0;
 | 
				
			||||||
 | 
					    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(`${idPrefix}${id}${quantitySuffix}`)
 | 
				
			||||||
 | 
					        let linePrice = document.getElementById(`${idPrefix}${id}${priceSuffix}`)
 | 
				
			||||||
 | 
					        quantity += parseFloat(lineQuantity.value);
 | 
				
			||||||
 | 
					        ammount += parseFloat(linePrice.value) * parseFloat(lineQuantity.value);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    quantityProducts.value = quantity;
 | 
				
			||||||
 | 
					    quantityLines.value = quantityInputs.length;
 | 
				
			||||||
 | 
					    ammountInput.value = ammount;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,8 +1,8 @@
 | 
				
			|||||||
<!doctype html>
 | 
					<!doctype html>
 | 
				
			||||||
{% load static %}
 | 
					{% load static %}
 | 
				
			||||||
<form method="POST">
 | 
					<form id="complete_form_purchase" method="POST">
 | 
				
			||||||
  {% csrf_token %}
 | 
					  {% csrf_token %}
 | 
				
			||||||
  {{ sale_form}}
 | 
					  {{ sale_form }}
 | 
				
			||||||
  {{ linea_formset.management_form }}
 | 
					  {{ linea_formset.management_form }}
 | 
				
			||||||
  <div id="formset-container">
 | 
					  <div id="formset-container">
 | 
				
			||||||
    {% for form in linea_formset %}
 | 
					    {% for form in linea_formset %}
 | 
				
			||||||
@@ -14,6 +14,8 @@
 | 
				
			|||||||
    {% endfor %}
 | 
					    {% endfor %}
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
  <button id="add_line" type="button" onclick="add_line">Añadir Linea</button>
 | 
					  <button id="add_line" type="button" onclick="add_line">Añadir Linea</button>
 | 
				
			||||||
 | 
					  {{ summary_form }}
 | 
				
			||||||
  <br/><button name="form" type="submit" >Comprar</button>
 | 
					  <br/><button name="form" type="submit" >Comprar</button>
 | 
				
			||||||
  <script src="{% static 'js/add_line.js' %}"></script>
 | 
					  <script src="{% static 'js/add_line.js' %}"></script>
 | 
				
			||||||
 | 
					  <script src="{% static 'js/sale_summary.js' %}"></script>
 | 
				
			||||||
</form>
 | 
					</form>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
from django.test import TestCase
 | 
					from django.test import TestCase
 | 
				
			||||||
from django.core.exceptions import ValidationError
 | 
					from django.core.exceptions import ValidationError
 | 
				
			||||||
from .models import Payment, ReconciliationJar
 | 
					from ..models import Payment, ReconciliationJar
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestBilling(TestCase):
 | 
					class TestBilling(TestCase):
 | 
				
			||||||
@@ -0,0 +1,36 @@
 | 
				
			|||||||
 | 
					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):
 | 
				
			||||||
 | 
					    #     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)
 | 
				
			||||||
@@ -1,9 +1,7 @@
 | 
				
			|||||||
from django.test import Client, TestCase
 | 
					from django.test import Client, TestCase
 | 
				
			||||||
from django.contrib.auth.models import AnonymousUser, User
 | 
					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):
 | 
					class TestReconciliationJarClient(TestCase):
 | 
				
			||||||
@@ -5,7 +5,7 @@ from django.core.exceptions import ValidationError
 | 
				
			|||||||
from django.views.generic import ListView
 | 
					from django.views.generic import ListView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .models import Sale, Product, ProductCategory, Payment
 | 
					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 csv
 | 
				
			||||||
import io
 | 
					import io
 | 
				
			||||||
@@ -19,6 +19,7 @@ def buy(request):
 | 
				
			|||||||
    if request.method == "POST":
 | 
					    if request.method == "POST":
 | 
				
			||||||
        sale_form = PurchaseForm(request.POST)
 | 
					        sale_form = PurchaseForm(request.POST)
 | 
				
			||||||
        sale_linea_form = LineaFormSet(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():
 | 
					        if sale_form.is_valid() and sale_linea_form.is_valid():
 | 
				
			||||||
            sale = sale_form.save()
 | 
					            sale = sale_form.save()
 | 
				
			||||||
            lines = sale_linea_form.save(commit=False)
 | 
					            lines = sale_linea_form.save(commit=False)
 | 
				
			||||||
@@ -29,12 +30,14 @@ def buy(request):
 | 
				
			|||||||
    else:
 | 
					    else:
 | 
				
			||||||
        sale_form = PurchaseForm()
 | 
					        sale_form = PurchaseForm()
 | 
				
			||||||
        sale_linea_form = LineaFormSet()
 | 
					        sale_linea_form = LineaFormSet()
 | 
				
			||||||
 | 
					        sale_summary_form = PurchaseSummaryForm()
 | 
				
			||||||
    return render(
 | 
					    return render(
 | 
				
			||||||
        request,
 | 
					        request,
 | 
				
			||||||
        'don_confiao/purchase.html',
 | 
					        'don_confiao/purchase.html',
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            'sale_form': sale_form,
 | 
					            'sale_form': sale_form,
 | 
				
			||||||
            'linea_formset': sale_linea_form
 | 
					            'linea_formset': sale_linea_form,
 | 
				
			||||||
 | 
					            'summary_form': sale_summary_form,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user