Merge pull request 'Habilitando Resumen de compra' (#63) from enable_summary_purchase_#55 into main
Reviewed-on: OneTeam/don_confiao#63
This commit is contained in:
commit
ac5c962ca7
@ -1,17 +1,103 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-app>
|
|
||||||
<v-navigation-drawer app>
|
|
||||||
</v-navigation-drawer>
|
|
||||||
<v-app-bar>
|
|
||||||
Resumen de la compra
|
|
||||||
</v-app-bar>
|
|
||||||
<v-container>
|
|
||||||
Pon aqui la información de la compra
|
|
||||||
</v-container>
|
|
||||||
</v-app>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
|
|
||||||
|
<v-container>
|
||||||
|
<v-container v-show="!id">
|
||||||
|
<v-toolbar>
|
||||||
|
<v-toolbar-title> No se indicó Id de la compra</v-toolbar-title>
|
||||||
|
</v-toolbar>
|
||||||
|
</v-container>
|
||||||
|
<v-container v-show="id">
|
||||||
|
<v-toolbar>
|
||||||
|
<v-toolbar-title> Resumen de la compra {{ id }}</v-toolbar-title>
|
||||||
|
</v-toolbar>
|
||||||
|
<v-list>
|
||||||
|
<v-list-item>
|
||||||
|
<v-list-item-content>
|
||||||
|
<v-list-item-title>Fecha:</v-list-item-title>
|
||||||
|
<v-list-item-subtitle>{{ purchase.date }}</v-list-item-subtitle>
|
||||||
|
</v-list-item-content>
|
||||||
|
</v-list-item>
|
||||||
|
<v-list-item>
|
||||||
|
<v-list-item-content>
|
||||||
|
<v-list-item-title>Cliente:</v-list-item-title>
|
||||||
|
<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>Total:</v-list-item-title>
|
||||||
|
<v-list-item-subtitle v-if="purchase.set_lines">{{ currencyFormat(calculateTotal(purchase.set_lines)) }}</v-list-item-subtitle>
|
||||||
|
</v-list-item-content>
|
||||||
|
</v-list-item>
|
||||||
|
</v-list>
|
||||||
|
<v-data-table-virtual
|
||||||
|
:headers="headers"
|
||||||
|
:items="purchase.set_lines"
|
||||||
|
>
|
||||||
|
<template v-slot:item.unit_price="{ item }">
|
||||||
|
{{ currencyFormat(item.unit_price) }}
|
||||||
|
</template>
|
||||||
|
<template v-slot:item.subtotal="{ item }">
|
||||||
|
{{ currencyFormat(calculateSubtotal(item.price, item.quantity)) }}
|
||||||
|
</template>
|
||||||
|
</v-data-table-virtual>
|
||||||
|
</v-container>
|
||||||
|
</v-container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'SummaryPurchase',
|
||||||
|
props: {
|
||||||
|
msg: String,
|
||||||
|
id: String
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
purchase: {},
|
||||||
|
headers: [
|
||||||
|
{ title: 'Nombre', value: 'product.name' },
|
||||||
|
{ title: 'Precio', value: 'unit_price' },
|
||||||
|
{ title: 'Cantidad', value: 'quantity' },
|
||||||
|
{ title: 'Subtotal', value: 'subtotal' },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
if (this.id) {
|
||||||
|
this.fetchPurchase(this.id);
|
||||||
|
} else {
|
||||||
|
console.error('No se proporcionó un ID de compra.');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
fetchPurchase(purchaseId) {
|
||||||
|
fetch(`/don_confiao/resumen_compra_json/${purchaseId}`)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
this.purchase = data;
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error(error);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
currencyFormat(value) {
|
||||||
|
return new Intl.NumberFormat('es-CO', { style: 'currency', currency: 'COP' }).format(value);
|
||||||
|
},
|
||||||
|
calculateSubtotal(price, quantity) {
|
||||||
|
price = parseFloat(price || 0);
|
||||||
|
quantity = parseFloat(price || 0);
|
||||||
|
return price * quantity;
|
||||||
|
},
|
||||||
|
calculateTotal(lines) {
|
||||||
|
let total = 0;
|
||||||
|
lines.forEach(line => {
|
||||||
|
total += this.calculateSubtotal(line.price, line.quantity);
|
||||||
|
});
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<SummaryPurchase />
|
<SummaryPurchase :id="$route.query.id"/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
@ -17,16 +17,7 @@ class TestAPI(APITestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_create_sale(self):
|
def test_create_sale(self):
|
||||||
url = '/don_confiao/api/sales/'
|
response = self._create_sale()
|
||||||
data = {
|
|
||||||
'customer': self.customer.id,
|
|
||||||
'date': '2024-09-02',
|
|
||||||
'saleline_set': [
|
|
||||||
{'product': self.product.id, 'quantity': 2, 'unit_price': 3000},
|
|
||||||
{'product': self.product.id, 'quantity': 3, 'unit_price': 5000}
|
|
||||||
],
|
|
||||||
}
|
|
||||||
response = self.client.post(url, data, format='json')
|
|
||||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||||
self.assertEqual(Sale.objects.count(), 1)
|
self.assertEqual(Sale.objects.count(), 1)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
@ -47,3 +38,15 @@ class TestAPI(APITestCase):
|
|||||||
json_response = json.loads(response.content.decode('utf-8'))
|
json_response = json.loads(response.content.decode('utf-8'))
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(self.customer.name, json_response[0]['name'])
|
self.assertEqual(self.customer.name, json_response[0]['name'])
|
||||||
|
|
||||||
|
def _create_sale(self):
|
||||||
|
url = '/don_confiao/api/sales/'
|
||||||
|
data = {
|
||||||
|
'customer': self.customer.id,
|
||||||
|
'date': '2024-09-02',
|
||||||
|
'saleline_set': [
|
||||||
|
{'product': self.product.id, 'quantity': 2, 'unit_price': 3000},
|
||||||
|
{'product': self.product.id, 'quantity': 3, 'unit_price': 5000}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
return self.client.post(url, data, format='json')
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from django.test import TestCase, Client
|
from django.test import TestCase, Client
|
||||||
from ..models import Sale, Product, SaleLine, Customer
|
from ..models import Sale, Product, SaleLine, Customer
|
||||||
|
|
||||||
|
|
||||||
class TestSummaryViewPurchase(TestCase):
|
class TestSummaryViewPurchase(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
customer = Customer()
|
customer = Customer()
|
||||||
@ -22,13 +23,29 @@ class TestSummaryViewPurchase(TestCase):
|
|||||||
line = SaleLine()
|
line = SaleLine()
|
||||||
line.sale = purchase
|
line.sale = purchase
|
||||||
line.product = product
|
line.product = product
|
||||||
line.quantity = "2"
|
line.quantity = "11"
|
||||||
line.unit_price = "72500"
|
line.unit_price = "72500"
|
||||||
line.save()
|
line.save()
|
||||||
self.purchase = purchase
|
self.purchase = purchase
|
||||||
|
|
||||||
def test_summary_has_customer(self):
|
def test_summary_has_customer(self):
|
||||||
response = self.client.get("/don_confiao/resumen_compra/" + str(self.purchase.id))
|
url = "/don_confiao/resumen_compra/" + str(self.purchase.id)
|
||||||
|
response = self.client.get(url)
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(response.context["purchase"].customer, self.purchase.customer)
|
self.assertEqual(
|
||||||
|
response.context["purchase"].customer,
|
||||||
|
self.purchase.customer
|
||||||
|
)
|
||||||
self.assertIn('Alejo Mono', response.content.decode('utf-8'))
|
self.assertIn('Alejo Mono', response.content.decode('utf-8'))
|
||||||
|
|
||||||
|
def test_json_summary(self):
|
||||||
|
url = f"/don_confiao/resumen_compra_json/{self.purchase.id}"
|
||||||
|
response = self.client.get(url)
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertIn('Alejo Mono', response.content.decode('utf-8'))
|
||||||
|
self.assertIn('cafe', response.content.decode('utf-8'))
|
||||||
|
self.assertIn('72500', response.content.decode('utf-8'))
|
||||||
|
self.assertIn('quantity', response.content.decode('utf-8'))
|
||||||
|
self.assertIn('11', response.content.decode('utf-8'))
|
||||||
|
self.assertIn('date', response.content.decode('utf-8'))
|
||||||
|
self.assertIn(self.purchase.date, response.content.decode('utf-8'))
|
||||||
|
@ -26,5 +26,6 @@ urlpatterns = [
|
|||||||
path("cuadrar_tarro", views.reconciliate_jar, name="reconciliate_jar"),
|
path("cuadrar_tarro", views.reconciliate_jar, name="reconciliate_jar"),
|
||||||
path("cuadres", views.reconciliate_jar, name="reconciliations"),
|
path("cuadres", views.reconciliate_jar, name="reconciliations"),
|
||||||
path("resumen_compra/<int:id>", views.purchase_summary, name="purchase_summary"),
|
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('api/', include(router.urls)),
|
path('api/', include(router.urls)),
|
||||||
]
|
]
|
||||||
|
@ -131,6 +131,7 @@ def reconciliate_jar(request):
|
|||||||
def reconciliations(request):
|
def reconciliations(request):
|
||||||
return HttpResponse('<h1>Reconciliaciones</h1>')
|
return HttpResponse('<h1>Reconciliaciones</h1>')
|
||||||
|
|
||||||
|
|
||||||
def purchase_summary(request, id):
|
def purchase_summary(request, id):
|
||||||
purchase = Sale.objects.get(pk=id)
|
purchase = Sale.objects.get(pk=id)
|
||||||
return render(
|
return render(
|
||||||
@ -142,6 +143,37 @@ def purchase_summary(request, id):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def purchase_json_summary(request, id):
|
||||||
|
purchase = Sale.objects.get(pk=id)
|
||||||
|
lines = []
|
||||||
|
for line in purchase.saleline_set.all():
|
||||||
|
lines.append({
|
||||||
|
'product': {
|
||||||
|
'id': line.product.id,
|
||||||
|
'name': line.product.name,
|
||||||
|
},
|
||||||
|
'quantity': line.quantity,
|
||||||
|
'unit_price': line.unit_price,
|
||||||
|
'description': line.description,
|
||||||
|
})
|
||||||
|
to_response = {
|
||||||
|
'id': purchase.id,
|
||||||
|
'date': purchase.date,
|
||||||
|
'customer': {
|
||||||
|
'id': purchase.customer.id,
|
||||||
|
'name': purchase.customer.name,
|
||||||
|
# 'phone': _mask_phone(purchase.customer.phone)
|
||||||
|
},
|
||||||
|
'set_lines': lines,
|
||||||
|
}
|
||||||
|
return JsonResponse(to_response, safe=False)
|
||||||
|
|
||||||
|
|
||||||
|
def _mask_phone(phone):
|
||||||
|
digits = str(phone)[-3:] if phone else " " * 3
|
||||||
|
return "X" * 7 + digits
|
||||||
|
|
||||||
|
|
||||||
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]
|
||||||
|
Loading…
Reference in New Issue
Block a user