Reviewed-on: #12
This commit is contained in:
		| @@ -1,7 +1,9 @@ | |||||||
| from django.contrib import admin | from django.contrib import admin | ||||||
| from .models import Sale, SaleLine, Product, ProductCategory | from .models import Sale, SaleLine, Product, ProductCategory, Payment, ReconciliationJar | ||||||
|  |  | ||||||
| admin.site.register(Sale) | admin.site.register(Sale) | ||||||
| admin.site.register(SaleLine) | admin.site.register(SaleLine) | ||||||
| admin.site.register(Product) | admin.site.register(Product) | ||||||
| admin.site.register(ProductCategory) | admin.site.register(ProductCategory) | ||||||
|  | admin.site.register(Payment) | ||||||
|  | admin.site.register(ReconciliationJar) | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| from django import forms | 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): | class ImportProductsForm(forms.Form): | ||||||
| @@ -39,3 +39,17 @@ LineaFormSet = forms.models.inlineformset_factory( | |||||||
|     extra=1, |     extra=1, | ||||||
|     fields='__all__' |     fields='__all__' | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | class ReconciliationJarForm(forms.ModelForm): | ||||||
|  |     class Meta: | ||||||
|  |         model = ReconciliationJar | ||||||
|  |         fields = [ | ||||||
|  |             'date_time', | ||||||
|  |             'description', | ||||||
|  |             'reconcilier', | ||||||
|  |             'cash_taken', | ||||||
|  |             'cash_discrepancy', | ||||||
|  |         ] | ||||||
|  |         widgets = { | ||||||
|  |             'date_time': DateTimeInput(attrs={'type': 'datetime-local'}) | ||||||
|  |         } | ||||||
|   | |||||||
							
								
								
									
										23
									
								
								tienda_ilusion/don_confiao/migrations/0012_payment.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								tienda_ilusion/don_confiao/migrations/0012_payment.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | # Generated by Django 5.0.6 on 2024-07-13 14:50 | ||||||
|  |  | ||||||
|  | from django.db import migrations, models | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Migration(migrations.Migration): | ||||||
|  |  | ||||||
|  |     dependencies = [ | ||||||
|  |         ('don_confiao', '0011_alter_product_name'), | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     operations = [ | ||||||
|  |         migrations.CreateModel( | ||||||
|  |             name='Payment', | ||||||
|  |             fields=[ | ||||||
|  |                 ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||||||
|  |                 ('date_time', models.DateTimeField()), | ||||||
|  |                 ('type_payment', models.CharField(choices=[('CASH', 'Cash'), ('CONFIAR', 'Confiar'), ('BANCOLOMBIA', 'Bancolombia')], default='CASH', max_length=30)), | ||||||
|  |                 ('mount', models.DecimalField(decimal_places=2, max_digits=9)), | ||||||
|  |                 ('description', models.CharField(blank=True, max_length=255, null=True)), | ||||||
|  |             ], | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
| @@ -0,0 +1,18 @@ | |||||||
|  | # Generated by Django 5.0.6 on 2024-07-13 15:56 | ||||||
|  |  | ||||||
|  | from django.db import migrations | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Migration(migrations.Migration): | ||||||
|  |  | ||||||
|  |     dependencies = [ | ||||||
|  |         ('don_confiao', '0012_payment'), | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     operations = [ | ||||||
|  |         migrations.RenameField( | ||||||
|  |             model_name='payment', | ||||||
|  |             old_name='mount', | ||||||
|  |             new_name='amount', | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
| @@ -0,0 +1,27 @@ | |||||||
|  | # Generated by Django 5.0.6 on 2024-07-13 16:35 | ||||||
|  |  | ||||||
|  | import django.db.models.deletion | ||||||
|  | from django.db import migrations, models | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Migration(migrations.Migration): | ||||||
|  |  | ||||||
|  |     dependencies = [ | ||||||
|  |         ('don_confiao', '0013_rename_mount_payment_amount'), | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     operations = [ | ||||||
|  |         migrations.CreateModel( | ||||||
|  |             name='ReconciliationJar', | ||||||
|  |             fields=[ | ||||||
|  |                 ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||||||
|  |                 ('date_time', models.DateTimeField()), | ||||||
|  |                 ('description', models.CharField(blank=True, max_length=255, null=True)), | ||||||
|  |             ], | ||||||
|  |         ), | ||||||
|  |         migrations.AddField( | ||||||
|  |             model_name='payment', | ||||||
|  |             name='reconciliation_jar', | ||||||
|  |             field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.RESTRICT, to='don_confiao.reconciliationjar'), | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
| @@ -0,0 +1,19 @@ | |||||||
|  | # Generated by Django 5.0.6 on 2024-07-13 16:36 | ||||||
|  |  | ||||||
|  | import django.db.models.deletion | ||||||
|  | from django.db import migrations, models | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Migration(migrations.Migration): | ||||||
|  |  | ||||||
|  |     dependencies = [ | ||||||
|  |         ('don_confiao', '0014_reconciliationjar_payment_reconciliation_jar'), | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     operations = [ | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='payment', | ||||||
|  |             name='reconciliation_jar', | ||||||
|  |             field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.RESTRICT, to='don_confiao.reconciliationjar'), | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
| @@ -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', | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
| @@ -0,0 +1,18 @@ | |||||||
|  | # Generated by Django 5.0.6 on 2024-07-13 22:16 | ||||||
|  |  | ||||||
|  | from django.db import migrations | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Migration(migrations.Migration): | ||||||
|  |  | ||||||
|  |     dependencies = [ | ||||||
|  |         ('don_confiao', '0020_remove_reconciliationjar_cash_float'), | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     operations = [ | ||||||
|  |         migrations.RenameField( | ||||||
|  |             model_name='reconciliationjar', | ||||||
|  |             old_name='reconciler', | ||||||
|  |             new_name='reconcilier', | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
| @@ -0,0 +1,19 @@ | |||||||
|  | # Generated by Django 5.0.6 on 2024-07-13 22:39 | ||||||
|  |  | ||||||
|  | import django.db.models.deletion | ||||||
|  | from django.db import migrations, models | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Migration(migrations.Migration): | ||||||
|  |  | ||||||
|  |     dependencies = [ | ||||||
|  |         ('don_confiao', '0021_rename_reconciler_reconciliationjar_reconcilier'), | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     operations = [ | ||||||
|  |         migrations.AlterField( | ||||||
|  |             model_name='payment', | ||||||
|  |             name='reconciliation_jar', | ||||||
|  |             field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.RESTRICT, to='don_confiao.reconciliationjar'), | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
| @@ -1,5 +1,9 @@ | |||||||
| from django.db import models | from django.db import models | ||||||
| from django.utils.translation import gettext_lazy as _ | from django.utils.translation import gettext_lazy as _ | ||||||
|  | from django.core.exceptions import ValidationError | ||||||
|  |  | ||||||
|  | from decimal import Decimal | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class Sale(models.Model): | class Sale(models.Model): | ||||||
| @@ -48,3 +52,84 @@ class Product(models.Model): | |||||||
|  |  | ||||||
|     def __str__(self): |     def __str__(self): | ||||||
|         return self.name |         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) | ||||||
|  |         self._payments = payments | ||||||
|  |  | ||||||
|  |     def _validate_payments(self, payments): | ||||||
|  |         pass | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def total(self): | ||||||
|  |         return sum([p.amount for p in self.payments]) | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def payments(self): | ||||||
|  |         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( | ||||||
|  |         max_length=30, | ||||||
|  |         choices=PyamentMethods.choices, | ||||||
|  |         default=PyamentMethods.CASH | ||||||
|  |     ) | ||||||
|  |     amount = models.DecimalField(max_digits=9, decimal_places=2) | ||||||
|  |     reconciliation_jar = models.ForeignKey( | ||||||
|  |         ReconciliationJar, | ||||||
|  |         null=True, | ||||||
|  |         default=None, | ||||||
|  |         blank=True, | ||||||
|  |         on_delete=models.RESTRICT | ||||||
|  |     ) | ||||||
|  |     description = models.CharField(max_length=255, null=True, blank=True) | ||||||
|  |  | ||||||
|  |     @classmethod | ||||||
|  |     def get_reconciliation_jar_summary(cls): | ||||||
|  |         return ReconciliationJarSummary( | ||||||
|  |             cls.objects.filter( | ||||||
|  |                 type_payment=PyamentMethods.CASH, | ||||||
|  |                 reconciliation_jar=None | ||||||
|  |             ) | ||||||
|  |         ) | ||||||
|   | |||||||
| @@ -0,0 +1,30 @@ | |||||||
|  | <!doctype html> | ||||||
|  | {% if summary.total %} | ||||||
|  | <div class="reconciliate_jar summary" style="border: solid 1px brown; margin: 10px"> | ||||||
|  |     <h2>Pagos No reconciliados</h2> | ||||||
|  |     <table style="border: solid 1px blue; margin: 10px"> | ||||||
|  |         <thead> | ||||||
|  |             <tr><th>Fecha</th><th>Monto</th></tr> | ||||||
|  |         </thead> | ||||||
|  |         <tbody> | ||||||
|  |             {% for payment in summary.payments %} | ||||||
|  |             <tr><td>{{ payment.date_time }}</td><td>{{ payment.amount }}</td></tr> | ||||||
|  |             {% endfor %} | ||||||
|  |         </tbody> | ||||||
|  |         <tfoot> | ||||||
|  |             <tr><th>Total</th><td>{{ summary.total }}</td></tr> | ||||||
|  |         </tfoot> | ||||||
|  |     </table> | ||||||
|  | </div> | ||||||
|  | <form method="POST"> | ||||||
|  |     <table style="border: solid 1px blue; margin: 10px"> | ||||||
|  |         {% csrf_token %} | ||||||
|  |         {{ form.as_table }} | ||||||
|  |     </table> | ||||||
|  |     <br/><button name="form" type="submit" >Recoger dinero</button> | ||||||
|  | </form> | ||||||
|  | {% else %} | ||||||
|  | <div class="reconciliate_jar information noform"> | ||||||
|  |     <h2>No hay pagos registrados.</h2> | ||||||
|  | </div> | ||||||
|  | {% endif %} | ||||||
							
								
								
									
										88
									
								
								tienda_ilusion/don_confiao/test_billing.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								tienda_ilusion/don_confiao/test_billing.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,88 @@ | |||||||
|  | from django.test import TestCase | ||||||
|  | from django.core.exceptions import ValidationError | ||||||
|  | from .models import Payment, ReconciliationJar | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestBilling(TestCase): | ||||||
|  |  | ||||||
|  |     def test_reconciliation_jar_summary(self): | ||||||
|  |         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) | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     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' | ||||||
|  |         confiar_payment.type_payment = 'CONFIAR' | ||||||
|  |         confiar_payment.amount = 85000 | ||||||
|  |         confiar_payment.save() | ||||||
|  |  | ||||||
|  |         bancolombia_payment = Payment() | ||||||
|  |         bancolombia_payment.date_time = '2024-07-07 12:30:00' | ||||||
|  |         bancolombia_payment.type_payment = 'BANCOLOMBIA' | ||||||
|  |         bancolombia_payment.amount = 12000 | ||||||
|  |         bancolombia_payment.save() | ||||||
|  |  | ||||||
|  |         jar_summary = Payment.get_reconciliation_jar_summary() | ||||||
|  |         self.assertEqual(164000, jar_summary.total) | ||||||
|  |         self.assertSetEqual( | ||||||
|  |             {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() | ||||||
|  |  | ||||||
|  |         reconciliation_jar.add_payments(jar_summary.payments) | ||||||
|  |         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_taken = jar_summary.total | ||||||
|  |         reconciliation_jar.cash_discrepancy = 0 | ||||||
|  |         reconciliation_jar.save() | ||||||
|  |  | ||||||
|  |         reconciliation_jar.add_payments(jar_summary.payments) | ||||||
|  |         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] | ||||||
							
								
								
									
										47
									
								
								tienda_ilusion/don_confiao/test_reconciliation_jar_client.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								tienda_ilusion/don_confiao/test_reconciliation_jar_client.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | |||||||
|  | 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) | ||||||
|  |         self.assertEqual(response.context["summary"].total, 160000) | ||||||
|  |         self.assertIn('160000', response.content.decode('utf-8')) | ||||||
|  |  | ||||||
|  |     def test_create_reconciliation_jar(self): | ||||||
|  |         self._generate_two_cash_payments() | ||||||
|  |         response = self.client.post( | ||||||
|  |             "/don_confiao/cuadrar_tarro", | ||||||
|  |             { | ||||||
|  |                 "date_time": "2024-07-20T00:00", | ||||||
|  |                 "description": "Cuadre de prueba", | ||||||
|  |                 "reconcilier": "Jorge", | ||||||
|  |                 "cash_taken": "100000", | ||||||
|  |                 "cash_discrepancy": "60000", | ||||||
|  |             } | ||||||
|  |         ) | ||||||
|  |         self.assertRedirects(response, '/don_confiao/cuadres') | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     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() | ||||||
|  |  | ||||||
|  |         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,7 @@ urlpatterns = [ | |||||||
|     path("comprar", views.buy, name="buy"), |     path("comprar", views.buy, name="buy"), | ||||||
|     path("compras", views.purchases, name="purchases"), |     path("compras", views.purchases, name="purchases"), | ||||||
|     path("productos", views.products, name="products"), |     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"), | ||||||
|  |     path("cuadres", views.reconciliate_jar, name="reconciliations"), | ||||||
| ] | ] | ||||||
|   | |||||||
| @@ -1,9 +1,10 @@ | |||||||
| from django.shortcuts import render | from django.shortcuts import render | ||||||
| from django.http import HttpResponseRedirect, JsonResponse | from django.http import HttpResponse, HttpResponseRedirect, JsonResponse | ||||||
| # from django.template import loader | from django.template import loader | ||||||
|  | from django.core.exceptions import ValidationError | ||||||
|  |  | ||||||
| from .models import Sale, Product, ProductCategory | from .models import Sale, Product, ProductCategory, Payment | ||||||
| from .forms import ImportProductsForm, PurchaseForm, LineaFormSet | from .forms import ImportProductsForm, PurchaseForm, LineaFormSet, ReconciliationJarForm | ||||||
|  |  | ||||||
| import csv | import csv | ||||||
| import io | import io | ||||||
| @@ -75,6 +76,29 @@ def import_products(request): | |||||||
|     ) |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def reconciliate_jar(request): | ||||||
|  |     summary = Payment.get_reconciliation_jar_summary() | ||||||
|  |     if request.method == 'POST': | ||||||
|  |         form = ReconciliationJarForm(request.POST) | ||||||
|  |         if form.is_valid(): | ||||||
|  |             reconciliation = form.save() | ||||||
|  |             reconciliation.add_payments(summary.payments) | ||||||
|  |             reconciliation.clean() | ||||||
|  |             reconciliation.save() | ||||||
|  |             return HttpResponseRedirect('cuadres') | ||||||
|  |     else: | ||||||
|  |         form = ReconciliationJarForm() | ||||||
|  |     return render( | ||||||
|  |         request, | ||||||
|  |         "don_confiao/reconciliate_jar.html", | ||||||
|  |         {'summary': summary, 'form': form} | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def reconciliations(request): | ||||||
|  |     return HttpResponse('<h1>Reconciliaciones</h1>') | ||||||
|  |  | ||||||
|  |  | ||||||
| def _categories_from_csv_string(categories_string, separator="&"): | def _categories_from_csv_string(categories_string, separator="&"): | ||||||
|     categories = categories_string.split(separator) |     categories = categories_string.split(separator) | ||||||
|     clean_categories = [c.strip() for c in categories] |     clean_categories = [c.strip() for c in categories] | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user