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:
		@@ -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]
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user