Compare commits
15 Commits
TrytonApiC
...
main
Author | SHA1 | Date | |
---|---|---|---|
43756952fb | |||
6a346bdf8a | |||
2a983c8056 | |||
2c6449c727 | |||
77a0c4ac0d | |||
2fcf884cce | |||
75d39c6ca7 | |||
a5d4c1977a | |||
d85ad7cc38 | |||
aa45ea44ac | |||
1b06818583 | |||
baa0677e7a | |||
d9d3239662 | |||
8bc2d02572 | |||
c9cfc7f873 |
@ -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
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,5 @@
|
|||||||
{
|
{
|
||||||
"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",
|
||||||
@ -11,7 +10,6 @@
|
|||||||
"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,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: {
|
||||||
|
@ -276,14 +276,7 @@
|
|||||||
fetchProducts() {
|
fetchProducts() {
|
||||||
this.api.getProducts()
|
this.api.getProducts()
|
||||||
.then(data => {
|
.then(data => {
|
||||||
console.log(data)
|
this.products = 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);
|
||||||
|
@ -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>
|
@ -13,20 +13,12 @@ import ApiImplementation from './services/api-implementation';
|
|||||||
|
|
||||||
// Composables
|
// Composables
|
||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import cors from 'cors';
|
|
||||||
|
|
||||||
// const cors = require('cors');
|
process.env.API_IMPLEMENTATION = 'django';
|
||||||
|
|
||||||
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)
|
||||||
|
@ -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>
|
@ -1,5 +1,4 @@
|
|||||||
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 {
|
||||||
@ -8,13 +7,6 @@ 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,7 +11,6 @@ class Api {
|
|||||||
return this.apiImplementation.getProducts();
|
return this.apiImplementation.getProducts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
getPaymentMethods() {
|
getPaymentMethods() {
|
||||||
return this.apiImplementation.getPaymentMethods();
|
return this.apiImplementation.getPaymentMethods();
|
||||||
}
|
}
|
||||||
@ -24,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)
|
||||||
|
@ -1,98 +0,0 @@
|
|||||||
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,8 +11,6 @@ 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: [
|
||||||
@ -65,19 +63,6 @@ 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,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"),
|
||||||
|
@ -28,10 +28,6 @@ DEBUG = True
|
|||||||
ALLOWED_HOSTS = []
|
ALLOWED_HOSTS = []
|
||||||
|
|
||||||
|
|
||||||
CORS_ALLOWED_ORIGINS = [
|
|
||||||
"http://localhost:8000",
|
|
||||||
]
|
|
||||||
|
|
||||||
# Application definition
|
# Application definition
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
|
Loading…
Reference in New Issue
Block a user