#69 feat(ReconciliationJar): send reconciliation jar from frontend
This commit is contained in:
		| @@ -1,9 +1,13 @@ | ||||
| from rest_framework import viewsets | ||||
| from rest_framework.response import Response | ||||
| from rest_framework.status import HTTP_400_BAD_REQUEST | ||||
| from rest_framework.views import APIView | ||||
|  | ||||
| from .models import Sale, SaleLine, Customer, Product | ||||
| from .serializers import SaleSerializer, ProductSerializer, CustomerSerializer | ||||
| from .models import Sale, SaleLine, Customer, Product, ReconciliationJar | ||||
| from .serializers import SaleSerializer, ProductSerializer, CustomerSerializer, ReconciliationJarSerializer | ||||
|  | ||||
| from decimal import Decimal | ||||
| import json | ||||
|  | ||||
| class SaleView(viewsets.ModelViewSet): | ||||
|     queryset = Sale.objects.all() | ||||
| @@ -46,3 +50,30 @@ class ProductView(viewsets.ModelViewSet): | ||||
| class CustomerView(viewsets.ModelViewSet): | ||||
|     queryset = Customer.objects.all() | ||||
|     serializer_class = CustomerSerializer | ||||
|  | ||||
| class ReconciliateJarView(APIView): | ||||
|     def post(self, request): | ||||
|         data = request.data | ||||
|         cash_purchases_id = json.loads(data.get('cash_purchases')) | ||||
|         serializer = ReconciliationJarSerializer(data=data) | ||||
|         if serializer.is_valid(): | ||||
|             purchases = Sale.objects.filter(pk__in=cash_purchases_id) | ||||
|  | ||||
|             total_cash_purchases = sum(p.get_total() for p in purchases) | ||||
|             if total_cash_purchases != Decimal(data.get('total_cash_purchases')): | ||||
|                 return Response( | ||||
|                     {'error': 'total_cash_purchases not equal to sum of all purchases.'}, | ||||
|                     status=HTTP_400_BAD_REQUEST | ||||
|                 ) | ||||
|             reconciliation = serializer.save() | ||||
|             for purchase in purchases: | ||||
|                 purchase.reconciliation = reconciliation | ||||
|                 purchase.clean() | ||||
|                 purchase.save() | ||||
|             return Response({'id': reconciliation.id}) | ||||
|         return Response(serializer.errors, status=HTTP_400_BAD_REQUEST) | ||||
|  | ||||
|     def get(self, request): | ||||
|         reconciliations = ReconciliationJar.objects.all() | ||||
|         serializer = ReconciliationJarSerializer(reconciliations, many=True) | ||||
|         return Response(serializer.data) | ||||
|   | ||||
| @@ -5,16 +5,17 @@ | ||||
|     </v-toolbar> | ||||
|     <v-card> | ||||
|       <v-card-text> | ||||
|         <v-form ref="taker" v-model="valid"> | ||||
|           <v-text-field | ||||
|             v-model="reconciliation.date_time" | ||||
|             label="Fecha" | ||||
|             type="datetime-local" | ||||
|             :rules="[rules.required]" | ||||
|             required | ||||
|             readonly | ||||
|           ></v-text-field> | ||||
|         <v-text-field | ||||
|           v-model="reconciliation.datetime" | ||||
|           label="Fecha" | ||||
|           type="datetime-local" | ||||
|           :rules="[rules.required]" | ||||
|           required | ||||
|           readonly | ||||
|         ></v-text-field> | ||||
|         <v-text-field | ||||
|           v-model="reconciliation.cashman" | ||||
|           v-model="reconciliation.reconcilier" | ||||
|           label="Cajero" | ||||
|           :rules="[rules.required]" | ||||
|           required | ||||
| @@ -41,6 +42,8 @@ | ||||
|           prefix="$" | ||||
|           type="number" | ||||
|         ></v-text-field> | ||||
|         <v-btn @click="submit" color="green">Recoger Dinero</v-btn> | ||||
|         </v-form> | ||||
|       </v-card-text> | ||||
|     </v-card> | ||||
|     <v-tabs v-model="selectedTab"> | ||||
| @@ -93,10 +96,12 @@ | ||||
|     }, | ||||
|     data () { | ||||
|       return { | ||||
|         valid: null, | ||||
|         selectedPurchaseId: null, | ||||
|         selectedTab: 'CASH', | ||||
|         reconciliation: { | ||||
|           datetime: '', | ||||
|           csrfmiddlewaretoken: null, | ||||
|           date_time: '', | ||||
|           total_cash_purchases: 0, | ||||
|           cash_taken: 0, | ||||
|           cash_discrepancy: 0, | ||||
| @@ -104,6 +109,7 @@ | ||||
|             confiar: 0, | ||||
|             bancolombia: 0 | ||||
|           }, | ||||
|           cash_purchases: [], | ||||
|         }, | ||||
|         summary: { | ||||
|           headers: [ | ||||
| @@ -122,7 +128,7 @@ | ||||
|     }, | ||||
|     mounted() { | ||||
|       this.fetchPurchases(); | ||||
|       this.reconciliation.datetime = this.getCurrentDate(); | ||||
|       this.reconciliation.date_time = this.getCurrentDate(); | ||||
|     }, | ||||
|     watch: { | ||||
|       'reconciliation.cash_taken'() { | ||||
| @@ -151,18 +157,51 @@ | ||||
|         this.selectedPurchaseId = id; | ||||
|         this.$refs.summaryModal.dialog = true; | ||||
|       }, | ||||
|       getCsrfToken() { | ||||
|         const cookies = document.cookie.split(';'); | ||||
|         const csrfToken = cookies.find(cookie => cookie.startsWith('csrftoken=')); | ||||
|         if (csrfToken) { | ||||
|           this.reconciliation.csrfmiddlewaretoken = csrfToken.split('=')[1]; | ||||
|         } | ||||
|       }, | ||||
|       fetchPurchases() { | ||||
|         const endpoint = '/don_confiao/purchases/for_reconciliation'; | ||||
|         fetch(endpoint) | ||||
|           .then(response => response.json()) | ||||
|           .then(data => { | ||||
|             this.summary.purchases = data; | ||||
|             this.reconciliation.cash_purchases = this.summary.purchases['CASH'].map(purchase => purchase.id); | ||||
|             this.reconciliation.total_cash_purchases = this.totalByMethod('CASH'); | ||||
|             this.getCsrfToken(); | ||||
|           }) | ||||
|           .catch(error => { | ||||
|             console.error(error); | ||||
|           }); | ||||
|       }, | ||||
|       async submit() { | ||||
|         this.$refs.taker.validate(); | ||||
|         if (this.valid) { | ||||
|           try { | ||||
|             const response = await fetch('/don_confiao/reconciliate_jar', { | ||||
|               method: 'POST', | ||||
|               headers: { | ||||
|               'Content-Type': 'application/json' | ||||
|               }, | ||||
|               body: JSON.stringify(this.reconciliation), | ||||
|             }); | ||||
|             if (response.ok) { | ||||
|               const data = await response.json(); | ||||
|               console.log('Cuadre enviado:', data); | ||||
|               this.$router.push({path: "/"}); | ||||
|             } else { | ||||
|               console.error('Error al enviar el cuadre', response.statusText); | ||||
|  | ||||
|             } | ||||
|           } catch (error) { | ||||
|             console.error('Error de red:', error); | ||||
|       } | ||||
|         } | ||||
|       }, | ||||
|     }, | ||||
|   } | ||||
| </script> | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| from rest_framework import serializers | ||||
|  | ||||
| from .models import Sale, SaleLine, Product, Customer | ||||
| from .models import Sale, SaleLine, Product, Customer, ReconciliationJar | ||||
|  | ||||
|  | ||||
| class SaleLineSerializer(serializers.ModelSerializer): | ||||
| @@ -20,7 +20,21 @@ class ProductSerializer(serializers.ModelSerializer): | ||||
|         model = Product | ||||
|         fields = ['id', 'name', 'price', 'measuring_unit', 'categories'] | ||||
|  | ||||
|  | ||||
| class CustomerSerializer(serializers.ModelSerializer): | ||||
|     class Meta: | ||||
|         model = Customer | ||||
|         fields = ['id', 'name', 'address', 'email', 'phone'] | ||||
|  | ||||
|  | ||||
| class ReconciliationJarSerializer(serializers.ModelSerializer): | ||||
|     class Meta: | ||||
|         model = ReconciliationJar | ||||
|         fields = [ | ||||
|             'id', | ||||
|             'date_time', | ||||
|             'reconcilier', | ||||
|             'cash_taken', | ||||
|             'cash_discrepancy', | ||||
|             'total_cash_purchases', | ||||
|         ] | ||||
|   | ||||
| @@ -138,15 +138,15 @@ class TestJarReconcliation(TestCase): | ||||
|         self.assertIn('total_cash_purchases', content['error']) | ||||
|  | ||||
|     def test_create_reconciliation_with_purchases(self): | ||||
|         url = '/don_confiao/reconciliation_jar/create' | ||||
|         url = '/don_confiao/reconciliate_jar' | ||||
|         total_purchases = (11 * 72500) + (27 * 72500) | ||||
|         data = { | ||||
|             'date_time': '2024-12-02T21:07', | ||||
|             'cashman': 'carlos', | ||||
|             'reconcilier': 'carlos', | ||||
|             'total_cash_purchases': total_purchases, | ||||
|             'cash_taken': total_purchases, | ||||
|             'cash_discrepancy': 0, | ||||
|             'purchases': json.dumps([#machete por error al codificar el json en el request | ||||
|             'cash_purchases': json.dumps([#machete por error al codificar el json en el request | ||||
|                 self.purchase.id, | ||||
|                 self.purchase2.id, | ||||
|                 self.purchase.id, | ||||
|   | ||||
| @@ -28,5 +28,6 @@ urlpatterns = [ | ||||
|     path("payment_methods/all/select_format", views.payment_methods_to_select, name="payment_methods_to_select"), | ||||
|     path('purchases/for_reconciliation', views.sales_for_reconciliation, name='sales_for_reconciliation'), | ||||
|     path('reconciliation_jar/create', views.reconciliate_jar, name='reconciliate_jar'), | ||||
|     path('reconciliate_jar', api_views.ReconciliateJarView.as_view()), | ||||
|     path('api/', include(router.urls)), | ||||
| ] | ||||
|   | ||||
| @@ -2,6 +2,7 @@ from django.shortcuts import render | ||||
| from django.http import HttpResponse, HttpResponseRedirect, JsonResponse | ||||
| from django.views.generic import ListView | ||||
| from django.db import transaction | ||||
| from django.middleware.csrf import get_token | ||||
|  | ||||
| from .models import ( | ||||
|     Sale, SaleLine, Product, Customer, ProductCategory, Payment, PaymentMethods, ReconciliationJar) | ||||
| @@ -204,7 +205,12 @@ def sales_for_reconciliation(request): | ||||
|             }, | ||||
|             'total': sale.get_total(), | ||||
|         }) | ||||
|     return JsonResponse(grouped_sales, safe=False) | ||||
|     response = JsonResponse(grouped_sales, safe=False) | ||||
|     csrf_token = get_token(request) | ||||
|     response['X-CSRFToken'] = csrf_token | ||||
|     response['Access-Control-Allow-Headers'] = 'X-CSRFToken' | ||||
|     response.set_cookie('csrftoken', csrf_token) | ||||
|     return response | ||||
|  | ||||
| def _mask_phone(phone): | ||||
|     digits = str(phone)[-3:] if phone else " " * 3 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user