Reviewed-on: OneTeam/don_confiao#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