Compare commits
	
		
			3 Commits
		
	
	
		
			main
			...
			TrytonApiC
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 03d38f0b64 | |||
| a097bf7141 | |||
| eb75a13857 | 
| @@ -2,7 +2,6 @@ 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 | ||||||
| @@ -10,12 +9,6 @@ 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 | ||||||
| @@ -138,9 +131,3 @@ 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 |  | ||||||
|   | |||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,5 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "don-confiao", |   "name": "don-confiao", | ||||||
|  |   "type": "module", | ||||||
|   "version": "0.0.0", |   "version": "0.0.0", | ||||||
|   "scripts": { |   "scripts": { | ||||||
|     "dev": "vite --host 0.0.0.0", |     "dev": "vite --host 0.0.0.0", | ||||||
| @@ -10,6 +11,7 @@ | |||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@mdi/font": "7.4.47", |     "@mdi/font": "7.4.47", | ||||||
|     "core-js": "^3.37.1", |     "core-js": "^3.37.1", | ||||||
|  |     "cors": "^2.8.5", | ||||||
|     "roboto-fontface": "*", |     "roboto-fontface": "*", | ||||||
|     "vee-validate": "^4.14.6", |     "vee-validate": "^4.14.6", | ||||||
|     "vue": "^3.4.31", |     "vue": "^3.4.31", | ||||||
|   | |||||||
| @@ -29,8 +29,7 @@ | |||||||
|          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: { | ||||||
|   | |||||||
| @@ -276,7 +276,14 @@ | |||||||
|      fetchProducts() { |      fetchProducts() { | ||||||
|        this.api.getProducts() |        this.api.getProducts() | ||||||
|            .then(data => { |            .then(data => { | ||||||
|              this.products = data; |                console.log(data) | ||||||
|  |                const transformed_products = data.map(item => ({ | ||||||
|  |                    name: item.name, | ||||||
|  |                    price: item["template."]?.list_price?.decimal, | ||||||
|  |                    measuring_unit: item["default_uom"]?.name, | ||||||
|  |                    categories: [] | ||||||
|  |                })); | ||||||
|  |                this.products = transformed_products; | ||||||
|            }) |            }) | ||||||
|            .catch(error => { |            .catch(error => { | ||||||
|              console.error(error); |              console.error(error); | ||||||
|   | |||||||
| @@ -1,64 +0,0 @@ | |||||||
| <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> |  | ||||||
| @@ -1,140 +0,0 @@ | |||||||
| <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: Number |       id: String | ||||||
|     }, |     }, | ||||||
|     data () { |     data () { | ||||||
|       return { |       return { | ||||||
|   | |||||||
| @@ -1,30 +0,0 @@ | |||||||
| <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> |  | ||||||
| @@ -1,31 +0,0 @@ | |||||||
| <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> |  | ||||||
| @@ -13,12 +13,20 @@ import ApiImplementation from './services/api-implementation'; | |||||||
|  |  | ||||||
| // Composables | // Composables | ||||||
| import { createApp } from 'vue' | import { createApp } from 'vue' | ||||||
|  | import cors from 'cors'; | ||||||
|  |  | ||||||
| process.env.API_IMPLEMENTATION = 'django'; | // const cors = require('cors'); | ||||||
|  |  | ||||||
|  | process.env.API_IMPLEMENTATION = 'tryton'; | ||||||
|  | // process.env.API_IMPLEMENTATION = 'django'; | ||||||
| let apiImplementation = new ApiImplementation(); | let apiImplementation = new ApiImplementation(); | ||||||
| const api = apiImplementation.getApi(); | const api = apiImplementation.getApi(); | ||||||
|  |  | ||||||
| const app = createApp(App); | const app = createApp(App); | ||||||
|  | // app.use(cors({ | ||||||
|  | //   origin: '*', // Permitir todas las solicitudes de origen | ||||||
|  | //   exposedHeaders: ['X-Custom-Header', 'Content-Length'], // Exponer headers específicos | ||||||
|  | // })); | ||||||
| app.provide('api', api); | app.provide('api', api); | ||||||
|  |  | ||||||
| registerPlugins(app) | registerPlugins(app) | ||||||
|   | |||||||
| @@ -1,20 +0,0 @@ | |||||||
| <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> |  | ||||||
| @@ -1,4 +1,5 @@ | |||||||
| import DjangoApi from './django-api'; | import DjangoApi from './django-api'; | ||||||
|  | import TrytonApiClient from './tryton-api'; | ||||||
| import Api from './api'; | import Api from './api'; | ||||||
|  |  | ||||||
| class ApiImplementation { | class ApiImplementation { | ||||||
| @@ -7,6 +8,13 @@ class ApiImplementation { | |||||||
|     let apiImplementation; |     let apiImplementation; | ||||||
|     if (implementation === 'django') { |     if (implementation === 'django') { | ||||||
|       apiImplementation = new DjangoApi(); |       apiImplementation = new DjangoApi(); | ||||||
|  |     } else if (implementation === 'tryton'){ | ||||||
|  |       const url = 'http://192.168.0.114:18030'; | ||||||
|  |       const key = '9a9ffc430146447d81e6698240199a4be2b0e774cb18474999d0f60e33b5b1eb1cfff9d9141346a98844879b5a9e787489c891ddc8fb45cc903b7244cab64fb1'; | ||||||
|  |       const db = 'tryton'; | ||||||
|  |       const applicationName = 'sale_don_confiao'; | ||||||
|  |       apiImplementation = new TrytonApiClient( | ||||||
|  |         url, key, db, applicationName); | ||||||
|     } else { |     } else { | ||||||
|       throw new Error("API implementation don't configured"); |       throw new Error("API implementation don't configured"); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ class Api { | |||||||
|     return this.apiImplementation.getProducts(); |     return this.apiImplementation.getProducts(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|   getPaymentMethods() { |   getPaymentMethods() { | ||||||
|     return this.apiImplementation.getPaymentMethods(); |     return this.apiImplementation.getPaymentMethods(); | ||||||
|   } |   } | ||||||
| @@ -23,14 +24,6 @@ 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,16 +24,6 @@ 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) | ||||||
|   | |||||||
| @@ -0,0 +1,98 @@ | |||||||
|  | class TrytonApiClient { | ||||||
|  |   constructor(url, key, db, applicationName) { | ||||||
|  |     this.baseUrl = `${url}/${db}/${applicationName}`; | ||||||
|  |     this.headers = { | ||||||
|  |       'Authorization': `Bearer ${key}`, | ||||||
|  |       'Content-Type': 'application/json', | ||||||
|  |       mode: 'cors' | ||||||
|  |     }; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   getCustomers() { | ||||||
|  |     const url = this.baseUrl + '/parties'; | ||||||
|  |     const customers = this.getRequest(url); | ||||||
|  |     return customers; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   getProducts() { | ||||||
|  |     const url = this.baseUrl + '/products' | ||||||
|  |     const products = this.getRequest(url); | ||||||
|  |     return products; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   getPaymentMethods() { | ||||||
|  |     const url = '/don_confiao/payment_methods/all/select_format'; | ||||||
|  |     return this.getRequest(url); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   getSummaryPurchase(purchaseId) { | ||||||
|  |     const url = `/don_confiao/resumen_compra_json/${purchaseId}`; | ||||||
|  |     return this.getRequest(url); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   getPurchasesForReconciliation() { | ||||||
|  |     const url = '/don_confiao/purchases/for_reconciliation'; | ||||||
|  |     return this.getRequest(url); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   isValidAdminCode(code) { | ||||||
|  |     const url = `/don_confiao/api/admin_code/validate/${code}` | ||||||
|  |     return this.getRequest(url) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   createPurchase(purchase) { | ||||||
|  |     const url = '/don_confiao/api/sales/'; | ||||||
|  |     return this.postRequest(url, purchase); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   createReconciliationJar(reconciliation) { | ||||||
|  |     const url = '/don_confiao/reconciliate_jar'; | ||||||
|  |     return this.postRequest(url, reconciliation); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   createCustomer(customer) { | ||||||
|  |     const url = '/don_confiao/api/customers/'; | ||||||
|  |     return this.postRequest(url, customer); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   getRequest(url) { | ||||||
|  |     return new Promise ((resolve, reject) => { | ||||||
|  |       fetch(url, { | ||||||
|  |         method: 'GET', | ||||||
|  |         headers: this.headers | ||||||
|  |       }).then(response => response.json()) | ||||||
|  |         .then(data => { | ||||||
|  |           resolve(data); | ||||||
|  |         }) | ||||||
|  |         .catch(error => { | ||||||
|  |           reject(error); | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   postRequest(url, content) { | ||||||
|  |     return new Promise((resolve, reject) => { | ||||||
|  |       fetch(url, { | ||||||
|  |         method: 'POST', | ||||||
|  |         headers: this.headers, | ||||||
|  |         body: JSON.stringify(content) | ||||||
|  |       }) | ||||||
|  |         .then(response => { | ||||||
|  |           if (!response.ok) { | ||||||
|  |             reject(new Error(`Error ${response.status}: ${response.statusText}`)); | ||||||
|  |           } else { | ||||||
|  |             response.json().then(data => { | ||||||
|  |               if (!data) { | ||||||
|  |                 reject(new Error('La respuesta no es un JSON válido')); | ||||||
|  |               } else { | ||||||
|  |                 resolve(data); | ||||||
|  |               } | ||||||
|  |             }); | ||||||
|  |           } | ||||||
|  |         }) | ||||||
|  |         .catch(error => reject(error)); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export default TrytonApiClient; | ||||||
| @@ -11,6 +11,8 @@ import Vuetify, { transformAssetUrls } from 'vite-plugin-vuetify' | |||||||
| import { defineConfig } from 'vite' | import { defineConfig } from 'vite' | ||||||
| import { fileURLToPath, URL } from 'node:url' | import { fileURLToPath, URL } from 'node:url' | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| // https://vitejs.dev/config/ | // https://vitejs.dev/config/ | ||||||
| export default defineConfig({ | export default defineConfig({ | ||||||
|   plugins: [ |   plugins: [ | ||||||
| @@ -63,6 +65,19 @@ export default defineConfig({ | |||||||
|   }, |   }, | ||||||
|   server: { |   server: { | ||||||
|     port: 3000, |     port: 3000, | ||||||
|  |     cors: { | ||||||
|  |       origin: '*', | ||||||
|  |       methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], | ||||||
|  |       allowedHeaders: ['Content-Type', 'Authorization'], | ||||||
|  |     }, | ||||||
|  |     proxy: { | ||||||
|  |       '/sale_don_confiao': { | ||||||
|  |         target: "http://127.0.0.1:8000/tryton/sale_don_confiao", // Cambia esto a la URL de tu API | ||||||
|  |         changeOrigin: true, | ||||||
|  |         rewrite: (path) => path.replace(/^\/sale_don_confiao/, '/tryton/sale_don_confiao'), // Opcional: reescribe la ruta | ||||||
|  |         ws: true | ||||||
|  |       }, | ||||||
|  |     }, | ||||||
|   }, |   }, | ||||||
|   build: { |   build: { | ||||||
|     outDir: '../../static/frontend/',  |     outDir: '../../static/frontend/',  | ||||||
|   | |||||||
| @@ -10,12 +10,9 @@ 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): | ||||||
| @@ -31,8 +28,6 @@ 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 = [ | ||||||
| @@ -42,10 +37,8 @@ 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() | ||||||
| @@ -56,7 +49,6 @@ 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,7 +139,22 @@ 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): | ||||||
|         response = self._create_reconciliation_with_purchase() |         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, | ||||||
|  |             ], | ||||||
|  |         } | ||||||
|  |         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) | ||||||
| @@ -182,59 +197,6 @@ 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" | ||||||
| @@ -244,21 +206,3 @@ 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,8 +10,7 @@ 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"), | ||||||
|   | |||||||
| @@ -28,6 +28,10 @@ DEBUG = True | |||||||
| ALLOWED_HOSTS = [] | ALLOWED_HOSTS = [] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | CORS_ALLOWED_ORIGINS = [ | ||||||
|  |     "http://localhost:8000", | ||||||
|  | ] | ||||||
|  |  | ||||||
| # Application definition | # Application definition | ||||||
|  |  | ||||||
| INSTALLED_APPS = [ | INSTALLED_APPS = [ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user