feat: implementing form to reconciliation jar.
This commit is contained in:
		| @@ -1,7 +1,7 @@ | ||||
| from django import forms | ||||
| from django.forms.widgets import DateInput | ||||
| from django.forms.widgets import DateInput, DateTimeInput | ||||
|  | ||||
| from .models import Sale, SaleLine | ||||
| from .models import Sale, SaleLine, ReconciliationJar | ||||
|  | ||||
|  | ||||
| class ImportProductsForm(forms.Form): | ||||
| @@ -37,3 +37,17 @@ LineaFormSet = forms.models.inlineformset_factory( | ||||
|     extra=2, | ||||
|     fields='__all__' | ||||
| ) | ||||
|  | ||||
| class ReconciliationJarForm(forms.ModelForm): | ||||
|     class Meta: | ||||
|         model = ReconciliationJar | ||||
|         fields = [ | ||||
|             'date_time', | ||||
|             'description', | ||||
|             'reconciler', | ||||
|             'cash_taken', | ||||
|             'cash_discrepancy', | ||||
|         ] | ||||
|         # widgets = { | ||||
|         #     'date_time': DateTimeInput(attrs={'type': 'datetime-local'}) | ||||
|         # } | ||||
|   | ||||
| @@ -0,0 +1,37 @@ | ||||
| # Generated by Django 5.0.6 on 2024-07-13 18:10 | ||||
|  | ||||
| from django.db import migrations, models | ||||
|  | ||||
|  | ||||
| class Migration(migrations.Migration): | ||||
|  | ||||
|     dependencies = [ | ||||
|         ('don_confiao', '0015_alter_payment_reconciliation_jar'), | ||||
|     ] | ||||
|  | ||||
|     operations = [ | ||||
|         migrations.AddField( | ||||
|             model_name='reconciliationjar', | ||||
|             name='cash_discrepancy', | ||||
|             field=models.DecimalField(decimal_places=2, default=0, max_digits=9), | ||||
|             preserve_default=False, | ||||
|         ), | ||||
|         migrations.AddField( | ||||
|             model_name='reconciliationjar', | ||||
|             name='cash_float', | ||||
|             field=models.DecimalField(decimal_places=2, default=0, max_digits=9), | ||||
|             preserve_default=False, | ||||
|         ), | ||||
|         migrations.AddField( | ||||
|             model_name='reconciliationjar', | ||||
|             name='cash_taken', | ||||
|             field=models.DecimalField(decimal_places=2, default=0, max_digits=9), | ||||
|             preserve_default=False, | ||||
|         ), | ||||
|         migrations.AddField( | ||||
|             model_name='reconciliationjar', | ||||
|             name='reconciler', | ||||
|             field=models.CharField(default='Jorge', max_length=255), | ||||
|             preserve_default=False, | ||||
|         ), | ||||
|     ] | ||||
| @@ -0,0 +1,18 @@ | ||||
| # Generated by Django 5.0.6 on 2024-07-13 18:15 | ||||
|  | ||||
| from django.db import migrations, models | ||||
|  | ||||
|  | ||||
| class Migration(migrations.Migration): | ||||
|  | ||||
|     dependencies = [ | ||||
|         ('don_confiao', '0016_reconciliationjar_cash_discrepancy_and_more'), | ||||
|     ] | ||||
|  | ||||
|     operations = [ | ||||
|         migrations.AddField( | ||||
|             model_name='reconciliationjar', | ||||
|             name='draft', | ||||
|             field=models.BooleanField(default=False), | ||||
|         ), | ||||
|     ] | ||||
| @@ -0,0 +1,18 @@ | ||||
| # Generated by Django 5.0.6 on 2024-07-13 18:19 | ||||
|  | ||||
| from django.db import migrations | ||||
|  | ||||
|  | ||||
| class Migration(migrations.Migration): | ||||
|  | ||||
|     dependencies = [ | ||||
|         ('don_confiao', '0017_reconciliationjar_draft'), | ||||
|     ] | ||||
|  | ||||
|     operations = [ | ||||
|         migrations.RenameField( | ||||
|             model_name='reconciliationjar', | ||||
|             old_name='draft', | ||||
|             new_name='valid', | ||||
|         ), | ||||
|     ] | ||||
| @@ -0,0 +1,18 @@ | ||||
| # Generated by Django 5.0.6 on 2024-07-13 19:56 | ||||
|  | ||||
| from django.db import migrations | ||||
|  | ||||
|  | ||||
| class Migration(migrations.Migration): | ||||
|  | ||||
|     dependencies = [ | ||||
|         ('don_confiao', '0018_rename_draft_reconciliationjar_valid'), | ||||
|     ] | ||||
|  | ||||
|     operations = [ | ||||
|         migrations.RenameField( | ||||
|             model_name='reconciliationjar', | ||||
|             old_name='valid', | ||||
|             new_name='is_valid', | ||||
|         ), | ||||
|     ] | ||||
| @@ -0,0 +1,17 @@ | ||||
| # Generated by Django 5.0.6 on 2024-07-13 20:13 | ||||
|  | ||||
| from django.db import migrations | ||||
|  | ||||
|  | ||||
| class Migration(migrations.Migration): | ||||
|  | ||||
|     dependencies = [ | ||||
|         ('don_confiao', '0019_rename_valid_reconciliationjar_is_valid'), | ||||
|     ] | ||||
|  | ||||
|     operations = [ | ||||
|         migrations.RemoveField( | ||||
|             model_name='reconciliationjar', | ||||
|             name='cash_float', | ||||
|         ), | ||||
|     ] | ||||
| @@ -1,5 +1,7 @@ | ||||
| from django.db import models | ||||
| from django.utils.translation import gettext_lazy as _ | ||||
| from django.core.exceptions import ValidationError | ||||
|  | ||||
|  | ||||
| class Sale(models.Model): | ||||
|  | ||||
| @@ -23,15 +25,18 @@ class SaleLine(models.Model): | ||||
|     def __str__(self): | ||||
|         return f"{self.sale} - {self.product}" | ||||
|  | ||||
|  | ||||
| class MeasuringUnits(models.TextChoices): | ||||
|     UNIT = 'UNIT', _('Unit') | ||||
|  | ||||
|  | ||||
| class ProductCategory(models.Model): | ||||
|     name = models.CharField(max_length=100, unique=True) | ||||
|  | ||||
|     def __str__(self): | ||||
|         return self.name | ||||
|  | ||||
|  | ||||
| class Product(models.Model): | ||||
|     name = models.CharField(max_length=100, unique=True) | ||||
|     price = models.DecimalField(max_digits=9, decimal_places=2) | ||||
| @@ -45,11 +50,13 @@ class Product(models.Model): | ||||
|     def __str__(self): | ||||
|         return self.name | ||||
|  | ||||
|  | ||||
| class PyamentMethods(models.TextChoices): | ||||
|     CASH = 'CASH', _('Cash') | ||||
|     CONFIAR = 'CONFIAR', _('Confiar') | ||||
|     BANCOLOMBIA = 'BANCOLOMBIA', _('Bancolombia') | ||||
|  | ||||
|  | ||||
| class ReconciliationJarSummary(): | ||||
|     def __init__(self, payments): | ||||
|         self._validate_payments(payments) | ||||
| @@ -68,9 +75,24 @@ class ReconciliationJarSummary(): | ||||
|  | ||||
|  | ||||
| class ReconciliationJar(models.Model): | ||||
|     is_valid = models.BooleanField(default=False) | ||||
|     date_time = models.DateTimeField() | ||||
|     description = models.CharField(max_length=255, null=True, blank=True) | ||||
|     reconciler = 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): | ||||
|         payments_amount = sum([p.amount for p in self.payment_set.all()]) | ||||
|         reconciliation_ammount = sum([ | ||||
|             self.cash_taken, | ||||
|             self.cash_discrepancy, | ||||
|         ]) | ||||
|         if reconciliation_ammount != payments_amount: | ||||
|             raise ValidationError( | ||||
|                 {"cash_take": _("The taken ammount has discrepancy.")} | ||||
|             ) | ||||
|         self.is_valid = True | ||||
|  | ||||
| class Payment(models.Model): | ||||
|     date_time = models.DateTimeField() | ||||
|   | ||||
| @@ -0,0 +1,2 @@ | ||||
| <!doctype html> | ||||
| {{ summary.total }} | ||||
| @@ -1,22 +1,21 @@ | ||||
| from django.test import Client, TestCase | ||||
| from .models import Payment | ||||
| from django.core.exceptions import ValidationError | ||||
| from .models import Payment, ReconciliationJar | ||||
|  | ||||
|  | ||||
| class TestBilling(TestCase): | ||||
|  | ||||
|     def test_reconciliation_jar_summary(self): | ||||
|         cash_payment1 = Payment() | ||||
|         cash_payment1.date_time = '2024-07-07 12:00:00' | ||||
|         cash_payment1.type_payment = 'CASH' | ||||
|         cash_payment1.amount = 132000 | ||||
|         cash_payment1.description = 'Saldo en compra' | ||||
|         cash_payment1.save() | ||||
|         cash_payment1, cash_payment2 = self._create_two_cash_payments() | ||||
|         jar_summary = Payment.get_reconciliation_jar_summary() | ||||
|         self.assertEqual(164000, jar_summary.total) | ||||
|         self.assertSetEqual( | ||||
|             {cash_payment1, cash_payment2}, | ||||
|             set(jar_summary.payments) | ||||
|         ) | ||||
|  | ||||
|         cash_payment2 = Payment() | ||||
|         cash_payment2.date_time = '2024-07-07 13:05:00' | ||||
|         cash_payment2.type_payment = 'CASH' | ||||
|         cash_payment2.amount = 32000 | ||||
|         cash_payment2.save() | ||||
|     def test_reconciliation_jar_summary_use_only_cash(self): | ||||
|         cash_payment1, cash_payment2 = self._create_two_cash_payments() | ||||
|  | ||||
|         confiar_payment = Payment() | ||||
|         confiar_payment.date_time = '2024-07-07 16:00:00' | ||||
| @@ -36,3 +35,57 @@ class TestBilling(TestCase): | ||||
|             {cash_payment1, cash_payment2}, | ||||
|             set(jar_summary.payments) | ||||
|         ) | ||||
|  | ||||
|     def test_fail_validate_reconciliation_jar_with_discrepancy_values(self): | ||||
|         cash_payment1, cash_payment2 = self._create_two_cash_payments() | ||||
|  | ||||
|         jar_summary = Payment.get_reconciliation_jar_summary() | ||||
|  | ||||
|         reconciliation_jar = ReconciliationJar() | ||||
|         reconciliation_jar.date_time = '2024-07-13 13:02:00' | ||||
|         reconciliation_jar.description = "test reconcialiation jar" | ||||
|         reconciliation_jar.reconcilier = 'Jorge' | ||||
|         reconciliation_jar.cash_float = 0 | ||||
|         reconciliation_jar.cash_taken = 0 | ||||
|         reconciliation_jar.cash_discrepancy = 0 | ||||
|         reconciliation_jar.save() | ||||
|  | ||||
|         for payment in jar_summary.payments: | ||||
|             reconciliation_jar.payment_set.add(payment) | ||||
|         with self.assertRaises(ValidationError): | ||||
|             reconciliation_jar.clean() | ||||
|  | ||||
|     def test_validate_reconciliation_jar_with_cash_float(self): | ||||
|         cash_payment1, cash_payment2 = self._create_two_cash_payments() | ||||
|         jar_summary = Payment.get_reconciliation_jar_summary() | ||||
|  | ||||
|         reconciliation_jar = ReconciliationJar() | ||||
|         reconciliation_jar.date_time = '2024-07-13 13:02:00' | ||||
|         reconciliation_jar.description = "test reconcialiation jar" | ||||
|         reconciliation_jar.reconcilier = 'Jorge' | ||||
|         reconciliation_jar.cash_float = 10000 | ||||
|         reconciliation_jar.cash_taken = jar_summary.total | ||||
|         reconciliation_jar.cash_discrepancy = 0 | ||||
|         reconciliation_jar.save() | ||||
|  | ||||
|         for payment in jar_summary.payments: | ||||
|             reconciliation_jar.payment_set.add(payment) | ||||
|         reconciliation_jar.clean() | ||||
|         reconciliation_jar.save() | ||||
|         self.assertTrue(reconciliation_jar.is_valid) | ||||
|  | ||||
|     def _create_two_cash_payments(self): | ||||
|         cash_payment1 = Payment() | ||||
|         cash_payment1.date_time = '2024-07-07 12:00:00' | ||||
|         cash_payment1.type_payment = 'CASH' | ||||
|         cash_payment1.amount = 132000 | ||||
|         cash_payment1.description = 'Saldo en compra' | ||||
|         cash_payment1.save() | ||||
|  | ||||
|         cash_payment2 = Payment() | ||||
|         cash_payment2.date_time = '2024-07-07 13:05:00' | ||||
|         cash_payment2.type_payment = 'CASH' | ||||
|         cash_payment2.amount = 32000 | ||||
|         cash_payment2.save() | ||||
|  | ||||
|         return [cash_payment1, cash_payment2] | ||||
|   | ||||
							
								
								
									
										34
									
								
								tienda_ilusion/don_confiao/test_reconciliation_jar_client.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								tienda_ilusion/don_confiao/test_reconciliation_jar_client.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| 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 | ||||
|  | ||||
|  | ||||
| class TestReconciliationJarClient(TestCase): | ||||
|     def setUp(self): | ||||
|         self.client = Client() | ||||
|  | ||||
|     def test_get_summary_info_on_view(self): | ||||
|         self._generate_two_cash_payments() | ||||
|         response = self.client.get("/don_confiao/cuadrar_tarro") | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|         # raise Exception(response.content.decode('utf-8')) | ||||
|         self.assertEqual(response.context["summary"].total, 160000) | ||||
|         self.assertIn('160000', response.content.decode('utf-8')) | ||||
|  | ||||
|     def _generate_two_cash_payments(self): | ||||
|         cash_payment1 = Payment() | ||||
|         cash_payment1.date_time = '2024-07-07 12:00:00' | ||||
|         cash_payment1.type_payment = 'CASH' | ||||
|         cash_payment1.amount = 130000 | ||||
|         cash_payment1.description = 'Saldo en compra' | ||||
|         cash_payment1.save() | ||||
|         # raise Exception (cash_payment1.id) | ||||
|  | ||||
|         cash_payment2 = Payment() | ||||
|         cash_payment2.date_time = '2024-07-07 13:05:00' | ||||
|         cash_payment2.type_payment = 'CASH' | ||||
|         cash_payment2.amount = 30000 | ||||
|         cash_payment2.save() | ||||
| @@ -8,5 +8,6 @@ urlpatterns = [ | ||||
|     path("comprar", views.buy, name="buy"), | ||||
|     path("compras", views.purchases, name="purchases"), | ||||
|     path("productos", views.products, name="products"), | ||||
|     path("importar_productos", views.import_products, name="import_products") | ||||
|     path("importar_productos", views.import_products, name="import_products"), | ||||
|     path("cuadrar_tarro", views.reconciliate_jar, name="reconciliate_jar"), | ||||
| ] | ||||
|   | ||||
| @@ -2,8 +2,8 @@ from django.shortcuts import render | ||||
| from django.http import HttpResponse, HttpResponseRedirect, JsonResponse | ||||
| from django.template import loader | ||||
|  | ||||
| from .models import Sale, Product, ProductCategory | ||||
| from .forms import ImportProductsForm, PurchaseForm, LineaFormSet | ||||
| from .models import Sale, Product, ProductCategory, Payment | ||||
| from .forms import ImportProductsForm, PurchaseForm, LineaFormSet, ReconciliationJarForm | ||||
|  | ||||
| import csv | ||||
| import io | ||||
| @@ -69,6 +69,21 @@ def import_products(request): | ||||
|         {'form': form} | ||||
|     ) | ||||
|  | ||||
|  | ||||
| def reconciliate_jar(request): | ||||
|     if request.method == 'POST': | ||||
|         return HttpResponseRedirect("cuadres") | ||||
|  | ||||
|     form = ReconciliationJarForm() | ||||
|     summary = Payment.get_reconciliation_jar_summary() | ||||
|     # raise Exception(Payment.get_reconciliation_jar_summary().payments) | ||||
|     return render( | ||||
|         request, | ||||
|         "don_confiao/reconciliate_jar.html", | ||||
|         {'summary': summary, 'form': form} | ||||
|     ) | ||||
|  | ||||
|  | ||||
| def _categories_from_csv_string(categories_string, separator="&"): | ||||
|     categories = categories_string.split(separator) | ||||
|     clean_categories = [c.strip() for c in categories] | ||||
|   | ||||
		Reference in New Issue
	
	Block a user