Creada vista para listar los cuadres de tarro #90 #91
| @@ -2,6 +2,7 @@ from rest_framework import viewsets | |||||||
| from rest_framework.response import Response | from rest_framework.response import Response | ||||||
| from rest_framework.status import HTTP_400_BAD_REQUEST | from rest_framework.status import HTTP_400_BAD_REQUEST | ||||||
| from rest_framework.views import APIView | from rest_framework.views import APIView | ||||||
|  | from rest_framework.pagination import PageNumberPagination | ||||||
|  |  | ||||||
| from .models import Sale, SaleLine, Customer, Product, ReconciliationJar, PaymentMethods, AdminCode | from .models import Sale, SaleLine, Customer, Product, ReconciliationJar, PaymentMethods, AdminCode | ||||||
| from .serializers import SaleSerializer, ProductSerializer, CustomerSerializer, ReconciliationJarSerializer, PaymentMethodSerializer, SaleForRenconciliationSerializer, SaleSummarySerializer | from .serializers import SaleSerializer, ProductSerializer, CustomerSerializer, ReconciliationJarSerializer, PaymentMethodSerializer, SaleForRenconciliationSerializer, SaleSummarySerializer | ||||||
| @@ -9,6 +10,12 @@ from .serializers import SaleSerializer, ProductSerializer, CustomerSerializer, | |||||||
| from decimal import Decimal | from decimal import Decimal | ||||||
| import json | import json | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Pagination(PageNumberPagination): | ||||||
|  |     page_size = 10 | ||||||
|  |     page_size_query_param = 'page_size' | ||||||
|  |  | ||||||
|  |  | ||||||
| class SaleView(viewsets.ModelViewSet): | class SaleView(viewsets.ModelViewSet): | ||||||
|     queryset = Sale.objects.all() |     queryset = Sale.objects.all() | ||||||
|     serializer_class = SaleSerializer |     serializer_class = SaleSerializer | ||||||
| @@ -131,3 +138,9 @@ class AdminCodeValidateView(APIView): | |||||||
|     def get(self, request, code): |     def get(self, request, code): | ||||||
|         codes = AdminCode.objects.filter(value=code) |         codes = AdminCode.objects.filter(value=code) | ||||||
|         return Response({'validCode': bool(codes)}) |         return Response({'validCode': bool(codes)}) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class ReconciliateJarModelView(viewsets.ModelViewSet): | ||||||
|  |     queryset = ReconciliationJar.objects.all().order_by('-date_time') | ||||||
|  |     pagination_class = Pagination | ||||||
|  |     serializer_class = ReconciliationJarSerializer | ||||||
|   | |||||||
| @@ -29,7 +29,8 @@ | |||||||
|          menuItems: [ |          menuItems: [ | ||||||
|              { title: 'Inicio', route: '/'}, |              { title: 'Inicio', route: '/'}, | ||||||
|              { title: 'Comprar', route:'/comprar'}, |              { title: 'Comprar', route:'/comprar'}, | ||||||
|              { title: 'Cuadrar tarro', route: '/cuadrar_tarro'} |              { title: 'Cuadrar tarro', route: '/cuadrar_tarro'}, | ||||||
|  |              { title: 'Cuadres de tarro', route: '/cuadres_de_tarro'}, | ||||||
|          ], |          ], | ||||||
|      }), |      }), | ||||||
|      watch: { |      watch: { | ||||||
|   | |||||||
| @@ -0,0 +1,64 @@ | |||||||
|  | <template> | ||||||
|  |   <v-container> | ||||||
|  |     <v-toolbar> | ||||||
|  |       <v-toolbar-title> Cuadres del Tarro </v-toolbar-title> | ||||||
|  |     </v-toolbar> | ||||||
|  |     <v-card> | ||||||
|  |       <v-card-text> | ||||||
|  |         <v-data-table-server | ||||||
|  |           v-model:items-per-page="itemsPerPage" | ||||||
|  |           :headers="headers" | ||||||
|  |           :items="serverItems" | ||||||
|  |           :items-length="totalItems" | ||||||
|  |           :loading="loading" | ||||||
|  |           :search="search" | ||||||
|  |           @update:options="loadItems" | ||||||
|  |         > | ||||||
|  |           <template v-slot:item.id="{ item }"> | ||||||
|  |             <v-btn @click="openSummaryModal(item.id)">{{ item.id }}</v-btn> | ||||||
|  |           </template> | ||||||
|  |         </v-data-table-server> | ||||||
|  |         <SummaryReconciliationModal :id="selectedReconciliationId" ref="summaryModal" /> | ||||||
|  |       </v-card-text> | ||||||
|  |     </v-card> | ||||||
|  |   </v-container> | ||||||
|  | </template> | ||||||
|  | <script> | ||||||
|  |   export default { | ||||||
|  |     data() { | ||||||
|  |       return { | ||||||
|  |         api: inject('api'), | ||||||
|  |         selectedReconciliationId: null, | ||||||
|  |         itemsPerPage: 10, | ||||||
|  |         headers: [ | ||||||
|  |           { title: 'Acciones', key: 'id'}, | ||||||
|  |           { title: 'Fecha', key: 'date_time'}, | ||||||
|  |           { title: 'Reconciliador', key: 'reconcilier'}, | ||||||
|  |           { title: 'Total Compras Efectivo', key: 'total_cash_purchases'}, | ||||||
|  |           { title: 'Recogido', key: 'cash_taken'}, | ||||||
|  |           { title: 'Descuadre', key: 'cash_discrepancy'}, | ||||||
|  |         ], | ||||||
|  |         search: '', | ||||||
|  |         serverItems: [], | ||||||
|  |         loading: true, | ||||||
|  |         totalItems: 0, | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     methods: { | ||||||
|  |       loadItems ({page, itemsPerPage}) { | ||||||
|  |         this.loading = true; | ||||||
|  |         this.api.getListReconcliations(page, itemsPerPage) | ||||||
|  |             .then(data => { | ||||||
|  |               this.serverItems = data['results']; | ||||||
|  |               this.totalItems = data['count']; | ||||||
|  |               this.loading = false; | ||||||
|  |             }) | ||||||
|  |             .catch(error => console.log('Error:', error)); | ||||||
|  |       }, | ||||||
|  |       openSummaryModal(id) { | ||||||
|  |         this.selectedReconciliationId = id.toString(); | ||||||
|  |         this.$refs.summaryModal.dialog = true; | ||||||
|  |       }, | ||||||
|  |     }, | ||||||
|  |   } | ||||||
|  | </script> | ||||||
| @@ -0,0 +1,140 @@ | |||||||
|  | <template> | ||||||
|  |   <v-container> | ||||||
|  |     <v-toolbar> | ||||||
|  |       <v-toolbar-title> Cuadre de Tarro: {{ id }}</v-toolbar-title> | ||||||
|  |     </v-toolbar> | ||||||
|  |     <v-card> | ||||||
|  |       <v-card-text> | ||||||
|  |         <v-text-field | ||||||
|  |           v-model="reconciliation.date_time" | ||||||
|  |           label="Fecha" | ||||||
|  |           required | ||||||
|  |           readonly | ||||||
|  |         ></v-text-field> | ||||||
|  |         <v-text-field | ||||||
|  |           v-model="reconciliation.reconcilier" | ||||||
|  |           label="Cajero" | ||||||
|  |           required | ||||||
|  |           readonly | ||||||
|  |         ></v-text-field> | ||||||
|  |         <v-text-field | ||||||
|  |           v-model="reconciliation.total_cash_purchases" | ||||||
|  |           label="Total Ventas en efectivo" | ||||||
|  |           prefix="$" | ||||||
|  |           type="number" | ||||||
|  |           readonly | ||||||
|  |         ></v-text-field> | ||||||
|  |         <v-text-field | ||||||
|  |           v-model="reconciliation.cash_taken" | ||||||
|  |           label="Dinero Recogido" | ||||||
|  |           prefix="$" | ||||||
|  |           type="number" | ||||||
|  |         ></v-text-field> | ||||||
|  |         <v-text-field | ||||||
|  |           v-model="reconciliation.cash_discrepancy" | ||||||
|  |           label="Descuadre" | ||||||
|  |           prefix="$" | ||||||
|  |           type="number" | ||||||
|  |         ></v-text-field> | ||||||
|  |         <v-tabs v-model="tab"> | ||||||
|  |           <v-tab | ||||||
|  |             v-for="(elements, paymentMethod) in purchases" | ||||||
|  |             :key="paymentMethod" | ||||||
|  |           > | ||||||
|  |             {{ paymentMethod }}  <CurrencyText :value="elements.total"</CurrencyText> | ||||||
|  |           </v-tab> | ||||||
|  |         </v-tabs> | ||||||
|  |         <v-tabs-window v-model="tab"> | ||||||
|  |           <v-tabs-window-item | ||||||
|  |             v-for="(elements, paymentMethod) in purchases" | ||||||
|  |             :key="paymentMethod" | ||||||
|  |           > | ||||||
|  |             <v-table> | ||||||
|  |               <thead> | ||||||
|  |                 <tr> | ||||||
|  |                   <th>Id</th> | ||||||
|  |                   <th>Fecha</th> | ||||||
|  |                   <th>Cliente</th> | ||||||
|  |                   <th>Total</th> | ||||||
|  |                 </tr> | ||||||
|  |               </thead> | ||||||
|  |               <tbody> | ||||||
|  |                 <tr v-for="purchase in elements.purchases" :key="purchase.id"> | ||||||
|  |                   <td><v-btn @click="openSummaryModal(purchase.id)">{{ purchase.id }}</v-btn></td> | ||||||
|  |                   <td>{{ purchase.date }}</td> | ||||||
|  |                   <td>{{ purchase.customer }}</td> | ||||||
|  |                   <td><CurrencyText :value="purchase.total"</CurrencyText></td> | ||||||
|  |  | ||||||
|  |                 </tr> | ||||||
|  |               </tbody> | ||||||
|  |             </v-table> | ||||||
|  |  | ||||||
|  |           </v-tabs-window-item> | ||||||
|  |         </v-tabs-window> | ||||||
|  |         <SummaryPurchaseModal :id="selectedPurchaseId" ref="summaryModal" /> | ||||||
|  |       </v-card-text> | ||||||
|  |     </v-card> | ||||||
|  |   </v-container> | ||||||
|  | </template> | ||||||
|  | <script> | ||||||
|  |   import { inject } from 'vue'; | ||||||
|  |  | ||||||
|  |   export default { | ||||||
|  |     name: 'ReconciliationJar View', | ||||||
|  |     props: { | ||||||
|  |       msg: String, | ||||||
|  |       id: { | ||||||
|  |         type: String, | ||||||
|  |         required: true | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     data () { | ||||||
|  |       return { | ||||||
|  |         tab: '0', | ||||||
|  |         selectedPurchaseId: null, | ||||||
|  |         api: inject('api'), | ||||||
|  |         valid: null, | ||||||
|  |         reconciliation: { | ||||||
|  |         }, | ||||||
|  |         purchases: {}, | ||||||
|  |       }; | ||||||
|  |     }, | ||||||
|  |     created() { | ||||||
|  |       if (this.id) { | ||||||
|  |         this.fetchReconciliation(this.id); | ||||||
|  |       } else { | ||||||
|  |         console.error('No se proporcionó ID'); | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     methods: { | ||||||
|  |       fetchReconciliation(reconciliationId) { | ||||||
|  |         this.api.getReconciliation(reconciliationId) | ||||||
|  |             .then(data => { | ||||||
|  |               this.reconciliation = data; | ||||||
|  |               this.groupPurchases(); | ||||||
|  |             }) | ||||||
|  |             .catch(error => console.error(error)); | ||||||
|  |       }, | ||||||
|  |       groupPurchases() { | ||||||
|  |         if (this.reconciliation.Sales) { | ||||||
|  |           this.purchases = this.reconciliation.Sales.reduce((grouped, sale) => { | ||||||
|  |             const paymentMethod = sale.payment_method; | ||||||
|  |             if (!grouped[paymentMethod]) { | ||||||
|  |               grouped[paymentMethod] = { | ||||||
|  |                 purchases: [], | ||||||
|  |                 total: 0, | ||||||
|  |               }; | ||||||
|  |             } | ||||||
|  |             grouped[paymentMethod].purchases.push(sale); | ||||||
|  |             grouped[paymentMethod].total += sale.total; | ||||||
|  |             return grouped; | ||||||
|  |           }, {}); | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |       openSummaryModal(id) { | ||||||
|  |         this.selectedPurchaseId = id; | ||||||
|  |         this.$refs.summaryModal.dialog = true; | ||||||
|  |       }, | ||||||
|  |     }, | ||||||
|  |   } | ||||||
|  | </script> | ||||||
| @@ -53,7 +53,7 @@ | |||||||
|     name: 'SummaryPurchase', |     name: 'SummaryPurchase', | ||||||
|     props: { |     props: { | ||||||
|       msg: String, |       msg: String, | ||||||
|       id: String |       id: Number | ||||||
|     }, |     }, | ||||||
|     data () { |     data () { | ||||||
|       return { |       return { | ||||||
|   | |||||||
| @@ -0,0 +1,30 @@ | |||||||
|  | <template> | ||||||
|  |   <v-dialog v-model="dialog" max-width="400"> | ||||||
|  |     <v-card> | ||||||
|  |       <v-card-text> | ||||||
|  |         <SummaryPurchase :id="id"/> | ||||||
|  |       </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 { | ||||||
|  |     name: 'SummaryPurchase Modal', | ||||||
|  |     props: { | ||||||
|  |       id: { | ||||||
|  |         type: Number, | ||||||
|  |         required: true, | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     data() { | ||||||
|  |       return { | ||||||
|  |         dialog: false, | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |   } | ||||||
|  | </script> | ||||||
| @@ -0,0 +1,31 @@ | |||||||
|  | <template> | ||||||
|  |   <v-dialog v-model="dialog" max-width="400"> | ||||||
|  |     resumen | ||||||
|  |     <v-card> | ||||||
|  |       <v-card-text> | ||||||
|  |         <ReconciliationJarView :id="id"/> | ||||||
|  |       </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 { | ||||||
|  |     name: 'Summary Reconciliation Modal', | ||||||
|  |     props: { | ||||||
|  |       id: { | ||||||
|  |         type: String, | ||||||
|  |         required: true, | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     data() { | ||||||
|  |       return { | ||||||
|  |         dialog: false, | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |   } | ||||||
|  | </script> | ||||||
| @@ -0,0 +1,20 @@ | |||||||
|  | <template> | ||||||
|  |   <div> | ||||||
|  |     <CodeDialog @code-verified="(verified) => showComponent = verified" /> | ||||||
|  |   </div> | ||||||
|  |   <ReconciliationJarIndex v-if="showComponent" /> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script> | ||||||
|  |   import CodeDialog from '../components/CodeDialog.vue' | ||||||
|  |  | ||||||
|  |   export default { | ||||||
|  |     data() { | ||||||
|  |       return { | ||||||
|  |         showComponent: false, | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     components: { CodeDialog }, | ||||||
|  |     methods: {}, | ||||||
|  |   } | ||||||
|  | </script> | ||||||
| @@ -23,6 +23,14 @@ class Api { | |||||||
|     return this.apiImplementation.getPurchasesForReconciliation(); |     return this.apiImplementation.getPurchasesForReconciliation(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   getListReconcliations(page=1, itemsPerPage=10) { | ||||||
|  |     return this.apiImplementation.getListReconcliations(page, itemsPerPage); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   getReconciliation(reconciliationId) { | ||||||
|  |     return this.apiImplementation.getReconciliation(reconciliationId); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   isValidAdminCode(code) { |   isValidAdminCode(code) { | ||||||
|     return this.apiImplementation.isValidAdminCode(code); |     return this.apiImplementation.isValidAdminCode(code); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -24,6 +24,16 @@ class DjangoApi { | |||||||
|     return this.getRequest(url); |     return this.getRequest(url); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   getListReconcliations(page, itemsPerPage) { | ||||||
|  |     const url = `/don_confiao/api/reconciliate_jar/?page=${page}&page_size=${itemsPerPage}`; | ||||||
|  |     return this.getRequest(url); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   getReconciliation(reconciliationId) { | ||||||
|  |     const url = `/don_confiao/api/reconciliate_jar/${reconciliationId}/`; | ||||||
|  |     return this.getRequest(url); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   isValidAdminCode(code) { |   isValidAdminCode(code) { | ||||||
|     const url = `/don_confiao/api/admin_code/validate/${code}` |     const url = `/don_confiao/api/admin_code/validate/${code}` | ||||||
|     return this.getRequest(url) |     return this.getRequest(url) | ||||||
|   | |||||||
| @@ -10,9 +10,12 @@ class SaleLineSerializer(serializers.ModelSerializer): | |||||||
|  |  | ||||||
|  |  | ||||||
| class SaleSerializer(serializers.ModelSerializer): | class SaleSerializer(serializers.ModelSerializer): | ||||||
|  |     total = serializers.ReadOnlyField(source='get_total') | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|         model = Sale |         model = Sale | ||||||
|         fields = ['id', 'customer', 'date', 'saleline_set'] |         fields = ['id', 'customer', 'date', 'saleline_set', | ||||||
|  |                   'total', 'payment_method'] | ||||||
|  |  | ||||||
|  |  | ||||||
| class ProductSerializer(serializers.ModelSerializer): | class ProductSerializer(serializers.ModelSerializer): | ||||||
| @@ -28,6 +31,8 @@ class CustomerSerializer(serializers.ModelSerializer): | |||||||
|  |  | ||||||
|  |  | ||||||
| class ReconciliationJarSerializer(serializers.ModelSerializer): | class ReconciliationJarSerializer(serializers.ModelSerializer): | ||||||
|  |     Sales = SaleSerializer(many=True, read_only=True) | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|         model = ReconciliationJar |         model = ReconciliationJar | ||||||
|         fields = [ |         fields = [ | ||||||
| @@ -37,8 +42,10 @@ class ReconciliationJarSerializer(serializers.ModelSerializer): | |||||||
|             'cash_taken', |             'cash_taken', | ||||||
|             'cash_discrepancy', |             'cash_discrepancy', | ||||||
|             'total_cash_purchases', |             'total_cash_purchases', | ||||||
|  |             'Sales', | ||||||
|         ] |         ] | ||||||
|  |  | ||||||
|  |  | ||||||
| class PaymentMethodSerializer(serializers.Serializer): | class PaymentMethodSerializer(serializers.Serializer): | ||||||
|     text = serializers.CharField() |     text = serializers.CharField() | ||||||
|     value = serializers.CharField() |     value = serializers.CharField() | ||||||
| @@ -49,6 +56,7 @@ class PaymentMethodSerializer(serializers.Serializer): | |||||||
|             'value': instance[0], |             'value': instance[0], | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |  | ||||||
| class SaleForRenconciliationSerializer(serializers.Serializer): | class SaleForRenconciliationSerializer(serializers.Serializer): | ||||||
|     id = serializers.IntegerField() |     id = serializers.IntegerField() | ||||||
|     date = serializers.DateTimeField() |     date = serializers.DateTimeField() | ||||||
|   | |||||||
| @@ -139,22 +139,7 @@ class TestJarReconcliation(TestCase): | |||||||
|         self.assertIn('total_cash_purchases', content['error']) |         self.assertIn('total_cash_purchases', content['error']) | ||||||
|  |  | ||||||
|     def test_create_reconciliation_with_purchases(self): |     def test_create_reconciliation_with_purchases(self): | ||||||
|         url = '/don_confiao/reconciliate_jar' |         response = self._create_reconciliation_with_purchase() | ||||||
|         total_purchases = (11 * 72500) + (27 * 72500) |  | ||||||
|         data = { |  | ||||||
|             'date_time': '2024-12-02T21:07', |  | ||||||
|             'reconcilier': 'carlos', |  | ||||||
|             'total_cash_purchases': total_purchases, |  | ||||||
|             'cash_taken': total_purchases, |  | ||||||
|             'cash_discrepancy': 0, |  | ||||||
|             'cash_purchases': [ |  | ||||||
|                 self.purchase.id, |  | ||||||
|                 self.purchase2.id, |  | ||||||
|                 self.purchase.id, |  | ||||||
|             ], |  | ||||||
|         } |  | ||||||
|         response = self.client.post(url, data=json.dumps(data).encode('utf-8'), |  | ||||||
|                                     content_type='application/json') |  | ||||||
|  |  | ||||||
|         rawContent = response.content.decode('utf-8') |         rawContent = response.content.decode('utf-8') | ||||||
|         content = json.loads(rawContent) |         content = json.loads(rawContent) | ||||||
| @@ -197,6 +182,59 @@ class TestJarReconcliation(TestCase): | |||||||
|         purchases = Sale.objects.filter(reconciliation_id=content['id']) |         purchases = Sale.objects.filter(reconciliation_id=content['id']) | ||||||
|         self.assertEqual(len(purchases), 3) |         self.assertEqual(len(purchases), 3) | ||||||
|  |  | ||||||
|  |     def test_list_reconciliations(self): | ||||||
|  |         self._create_simple_reconciliation() | ||||||
|  |         self._create_simple_reconciliation() | ||||||
|  |  | ||||||
|  |         url = '/don_confiao/api/reconciliate_jar/' | ||||||
|  |  | ||||||
|  |         response = self.client.get(url) | ||||||
|  |         self.assertEqual(response.status_code, 200) | ||||||
|  |  | ||||||
|  |         content = json.loads(response.content.decode('utf-8')) | ||||||
|  |         self.assertEqual(2, content['count']) | ||||||
|  |         self.assertEqual(2, len(content['results'])) | ||||||
|  |         self.assertEqual('2024-07-30T00:00:00Z', | ||||||
|  |                          content['results'][0]['date_time']) | ||||||
|  |  | ||||||
|  |     def test_list_reconciliations_pagination(self): | ||||||
|  |         self._create_simple_reconciliation() | ||||||
|  |         self._create_simple_reconciliation() | ||||||
|  |  | ||||||
|  |         url = '/don_confiao/api/reconciliate_jar/?page=2&page_size=1' | ||||||
|  |  | ||||||
|  |         response = self.client.get(url) | ||||||
|  |         self.assertEqual(response.status_code, 200) | ||||||
|  |  | ||||||
|  |         content = json.loads(response.content.decode('utf-8')) | ||||||
|  |         self.assertEqual(1, len(content['results'])) | ||||||
|  |         self.assertEqual('2024-07-30T00:00:00Z', | ||||||
|  |                          content['results'][0]['date_time']) | ||||||
|  |  | ||||||
|  |     def test_get_single_reconciliation(self): | ||||||
|  |         createResponse = self._create_reconciliation_with_purchase() | ||||||
|  |         reconciliationId = json.loads( | ||||||
|  |             createResponse.content.decode('utf-8') | ||||||
|  |         )['id'] | ||||||
|  |         self.assertGreater(reconciliationId, 0) | ||||||
|  |  | ||||||
|  |         url = f'/don_confiao/api/reconciliate_jar/{reconciliationId}/' | ||||||
|  |         response = self.client.get(url, content_type='application/json') | ||||||
|  |         content = json.loads( | ||||||
|  |             response.content.decode('utf-8') | ||||||
|  |         ) | ||||||
|  |         self.assertEqual(reconciliationId, content['id']) | ||||||
|  |         self.assertGreater(len(content['Sales']), 0) | ||||||
|  |         self.assertIn( | ||||||
|  |             self.purchase.id, | ||||||
|  |             [sale['id'] for sale in content['Sales']] | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         self.assertIn( | ||||||
|  |             'CASH', | ||||||
|  |             [sale['payment_method'] for sale in content['Sales']] | ||||||
|  |         ) | ||||||
|  |  | ||||||
|     def _create_simple_reconciliation(self): |     def _create_simple_reconciliation(self): | ||||||
|         reconciliation = ReconciliationJar() |         reconciliation = ReconciliationJar() | ||||||
|         reconciliation.date_time = "2024-07-30" |         reconciliation.date_time = "2024-07-30" | ||||||
| @@ -206,3 +244,21 @@ class TestJarReconcliation(TestCase): | |||||||
|         reconciliation.clean() |         reconciliation.clean() | ||||||
|         reconciliation.save() |         reconciliation.save() | ||||||
|         return reconciliation |         return reconciliation | ||||||
|  |  | ||||||
|  |     def _create_reconciliation_with_purchase(self): | ||||||
|  |         url = '/don_confiao/reconciliate_jar' | ||||||
|  |         total_purchases = (11 * 72500) + (27 * 72500) | ||||||
|  |         data = { | ||||||
|  |             'date_time': '2024-12-02T21:07', | ||||||
|  |             'reconcilier': 'carlos', | ||||||
|  |             'total_cash_purchases': total_purchases, | ||||||
|  |             'cash_taken': total_purchases, | ||||||
|  |             'cash_discrepancy': 0, | ||||||
|  |             'cash_purchases': [ | ||||||
|  |                 self.purchase.id, | ||||||
|  |                 self.purchase2.id, | ||||||
|  |                 self.purchase.id, | ||||||
|  |             ], | ||||||
|  |         } | ||||||
|  |         return self.client.post(url, data=json.dumps(data).encode('utf-8'), | ||||||
|  |                                 content_type='application/json') | ||||||
|   | |||||||
| @@ -10,7 +10,8 @@ router = DefaultRouter() | |||||||
| router.register(r'sales', api_views.SaleView, basename='sale') | router.register(r'sales', api_views.SaleView, basename='sale') | ||||||
| router.register(r'customers', api_views.CustomerView, basename='customer') | router.register(r'customers', api_views.CustomerView, basename='customer') | ||||||
| router.register(r'products', api_views.ProductView, basename='product') | router.register(r'products', api_views.ProductView, basename='product') | ||||||
|  | router.register(r'reconciliate_jar', api_views.ReconciliateJarModelView, | ||||||
|  |                 basename='reconciliate_jar') | ||||||
|  |  | ||||||
| urlpatterns = [ | urlpatterns = [ | ||||||
|     path("", views.index, name="wellcome"), |     path("", views.index, name="wellcome"), | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user