Merge pull request 'Habilitando la selección de método de pago en la compra' (#72) from chose_pay_method_on_purchase_#47 into main

Reviewed-on: OneTeam/don_confiao#72
This commit is contained in:
mono 2024-11-11 16:27:21 -05:00
commit 2d86aba3e5
12 changed files with 186 additions and 12 deletions

View File

@ -14,7 +14,12 @@ class SaleView(viewsets.ModelViewSet):
customer = Customer.objects.get(pk=data['customer'])
date = data['date']
lines = data['saleline_set']
sale = Sale.objects.create(customer=customer, date=date)
payment_method = data['payment_method']
sale = Sale.objects.create(
customer=customer,
date=date,
payment_method=payment_method
)
for line in lines:
product = Product.objects.get(pk=line['product'])

View File

@ -0,0 +1,58 @@
<template>
<v-dialog v-model="dialog" max-width="400">
<v-card>
<v-card-title>Calcular Devuelta</v-card-title>
<v-card-text>
<v-text-field
v-model.number="purchase"
label="Total de la compra"
type="number"
prefix="$"
readonly
></v-text-field>
<v-text-field
v-model.number="money"
label="Dinero"
type="number"
prefix="$"
></v-text-field>
<v-text-field
v-model.number="change_cash"
label="Devuelta"
type="number"
prefix="$"
readonly
></v-text-field>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn text @click="dialog = false">Cerrar</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
export default {
props: {
total_purchase: {
type: Number,
required: true
}
},
data() {
return {
dialog: false,
money: null,
}
},
computed: {
purchase() {
return this.total_purchase
},
change_cash() {
return (this.money || 0) - this.total_purchase
},
},
}
</script>

View File

@ -116,18 +116,31 @@
readonly
persistent-placeholder="true"
></v-text-field>
<v-container v-if="calculateTotal > 0">
<v-select
:items="payment_methods"
v-model="purchase.payment_method"
item-title="text"
item-value="value"
label="Pago en"
></v-select>
<v-btn @click="openCasherModal" v-if="purchase.payment_method === 'CASH'">Calcular Devuelta</v-btn>
<CasherModal :total_purchase="calculateTotal" ref="casherModal"</CasherModal>
</v-container>
<v-btn @click="submit" color="green">Comprar</v-btn>
</v-form>
</v-container>
</v-form>
</v-container>
</template>
<script>
import CustomerForm from './CreateCustomerModal.vue';
import CustomerForm from './CreateCustomerModal.vue';
import CasherModal from './CasherModal.vue';
export default {
name: 'DonConfiao',
components: {
CustomerForm
CustomerForm,
CasherModal,
},
props: {
msg: String
@ -137,10 +150,12 @@
valid: false,
client_search: '',
product_search: '',
payment_methods: null,
purchase: {
date: this.getCurrentDate(),
customer: null,
notes: '',
payment_method: null,
saleline_set: [{product:'', unit_price: 0, quantity: 0, unit: ''}],
},
rules: {
@ -157,6 +172,7 @@
created() {
this.fetchClients();
this.fetchProducts();
this.fetchPaymentMethods();
},
watch: {
group () {
@ -192,6 +208,9 @@
openModal() {
this.$refs.customerModal.openModal();
},
openCasherModal() {
this.$refs.casherModal.dialog = true
},
getCurrentDate() {
const today = new Date();
const yyyy = today.getFullYear();
@ -225,13 +244,22 @@
fetch('/don_confiao/api/products/')
.then(response => response.json())
.then(data => {
console.log(data);
this.products = data;
})
.catch(error => {
console.error(error);
});
},
fetchPaymentMethods() {
fetch('/don_confiao/payment_methods/all/select_format')
.then(response => response.json())
.then(data => {
this.payment_methods = data;
})
.catch(error => {
console.error(error);
});
},
addLine() {
this.purchase.saleline_set.push({ product: '', unit_price: 0, quantity:0, measuring_unit: ''});
},

View File

@ -23,6 +23,12 @@
<v-list-item-subtitle v-if="purchase.customer">{{ purchase.customer.name }}</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
<v-list-item>
<v-list-item-content>
<v-list-item-title>Pagado en:</v-list-item-title>
<v-list-item-subtitle v-if="purchase.payment_method">{{ purchase.payment_method }}</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
<v-list-item>
<v-list-item-content>
<v-list-item-title>Total:</v-list-item-title>

View File

@ -0,0 +1,18 @@
# Generated by Django 5.0.6 on 2024-11-09 17:55
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('don_confiao', '0032_customer_address'),
]
operations = [
migrations.AddField(
model_name='sale',
name='payment_method',
field=models.CharField(choices=[('CASH', 'Cash'), ('CONFIAR', 'Confiar'), ('BANCOLOMBIA', 'Bancolombia')], default='CASH', max_length=30),
),
]

View File

@ -6,6 +6,12 @@ from decimal import Decimal
from datetime import datetime
class PaymentMethods(models.TextChoices):
CASH = 'CASH', _('Efectivo')
CONFIAR = 'CONFIAR', _('Confiar')
BANCOLOMBIA = 'BANCOLOMBIA', _('Bancolombia')
class Customer(models.Model):
name = models.CharField(max_length=100, default=None, null=False, blank=False)
address = models.CharField(max_length=100, null=True, blank=True)
@ -61,6 +67,13 @@ class Sale(models.Model):
date = models.DateField("Date")
phone = models.CharField(max_length=13, null=True, blank=True)
description = models.CharField(max_length=255, null=True, blank=True)
payment_method = models.CharField(
max_length=30,
choices=PaymentMethods.choices,
default=PaymentMethods.CASH,
blank=False,
null=False
)
def __str__(self):
return f"{self.date} {self.customer}"
@ -69,6 +82,10 @@ class Sale(models.Model):
lines = self.saleline_set.all()
return sum([l.quantity * l.unit_price for l in lines])
def clean(self):
if self.payment_method not in PaymentMethods.values:
raise ValidationError({'payment_method': "Invalid payment method"})
@classmethod
def sale_header_csv(cls):
sale_header_csv = [field.name for field in cls._meta.fields]
@ -88,12 +105,6 @@ class SaleLine(models.Model):
return f"{self.sale} - {self.product}"
class PaymentMethods(models.TextChoices):
CASH = 'CASH', _('Cash')
CONFIAR = 'CONFIAR', _('Confiar')
BANCOLOMBIA = 'BANCOLOMBIA', _('Bancolombia')
class ReconciliationJarSummary():
def __init__(self, payments):
self._validate_payments(payments)

View File

@ -50,6 +50,7 @@ class TestAPI(APITestCase):
data = {
'customer': self.customer.id,
'date': '2024-09-02',
'payment_method': 'CASH',
'saleline_set': [
{'product': self.product.id, 'quantity': 2, 'unit_price': 3000},
{'product': self.product.id, 'quantity': 3, 'unit_price': 5000}

View File

@ -0,0 +1,23 @@
from django.test import Client, TestCase
# from ..models import PaymentMethods
class TestPaymentMethods(TestCase):
def setUp(self):
self.client = Client()
def test_keys_in_payment_methods_to_select(self):
response = self.client.get(
'/don_confiao/payment_methods/all/select_format'
)
methods = response.json()
for method in methods:
self.assertEqual(set(method.keys()), {'text', 'value'})
def test_basic_payment_methods_to_select(self):
methods = self.client.get(
'/don_confiao/payment_methods/all/select_format'
).json()
self.assertIn('CASH', [method.get('value') for method in methods])
self.assertIn('CONFIAR', [method.get('value') for method in methods])
self.assertIn('BANCOLOMBIA', [method.get('value') for method in methods])

View File

@ -1,4 +1,6 @@
from django.test import TestCase
from django.core.exceptions import ValidationError
from ..models import Customer, Product, Sale, SaleLine
@ -24,6 +26,17 @@ class ConfiaoTest(TestCase):
self.assertIsInstance(sale, Sale)
def test_can_create_sale_without_payment_method(self):
sale = Sale()
sale.customer = self.customer
sale.date = "2024-06-22"
sale.phone = '666666666'
sale.description = "Description"
sale.payment_method = ''
with self.assertRaises(ValidationError):
sale.full_clean()
def test_create_sale_line(self):
sale = Sale()
sale.customer = self.customer

View File

@ -19,6 +19,7 @@ class PurchaseFormTest(TestCase):
"csrfmiddlewaretoken": _csrf_token,
"customer": self.customer.id,
"date": "2024-08-03",
"payment_method": "CASH",
"phone": "sfasfd",
"description": "dasdadad",
"saleline_set-TOTAL_FORMS": "1",

View File

@ -27,5 +27,6 @@ urlpatterns = [
path("cuadres", views.reconciliate_jar, name="reconciliations"),
path("resumen_compra/<int:id>", views.purchase_summary, name="purchase_summary"),
path("resumen_compra_json/<int:id>", views.purchase_json_summary, name="purchase_json_summary"),
path("payment_methods/all/select_format", views.payment_methods_to_select, name="payment_methods_to_select"),
path('api/', include(router.urls)),
]

View File

@ -164,11 +164,20 @@ def purchase_json_summary(request, id):
'name': purchase.customer.name,
# 'phone': _mask_phone(purchase.customer.phone)
},
'payment_method': purchase.payment_method,
'set_lines': lines,
}
return JsonResponse(to_response, safe=False)
def payment_methods_to_select(request):
methods = [
{'text': choice[1], 'value': choice[0]}
for choice in PaymentMethods.choices
]
return JsonResponse(methods, safe=False)
def _mask_phone(phone):
digits = str(phone)[-3:] if phone else " " * 3
return "X" * 7 + digits