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:
commit
2d86aba3e5
@ -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'])
|
||||
|
@ -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>
|
@ -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: ''});
|
||||
},
|
||||
|
@ -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>
|
||||
|
@ -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),
|
||||
),
|
||||
]
|
@ -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)
|
||||
|
@ -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}
|
||||
|
23
tienda_ilusion/don_confiao/tests/test_payment_methods.py
Normal file
23
tienda_ilusion/don_confiao/tests/test_payment_methods.py
Normal 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])
|
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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)),
|
||||
]
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user