Compare commits

...

2 Commits

Author SHA1 Message Date
Carlos Satorres 6ca8c4ba40 refs 4764 creacion de metodo back y front
gitea/salix/pipeline/head This commit looks good Details
2023-04-27 09:25:48 +02:00
Carlos Satorres 7955d1248d refs #4764 boton
gitea/salix/pipeline/head This commit looks good Details
2023-04-26 09:02:47 +02:00
4 changed files with 238 additions and 1 deletions

View File

@ -0,0 +1,189 @@
module.exports = Self => {
Self.remoteMethod('refund', {
description: 'Create refund tickets with sales and services if provided',
accessType: 'WRITE',
accepts: [
{
arg: 'salesIds',
type: ['number'],
required: true
},
{
arg: 'servicesIds',
type: ['number']
},
{
arg: 'createSingleTicket',
type: 'boolean',
required: false
}
],
returns: {
type: ['number'],
root: true
},
http: {
path: `/refund`,
verb: 'POST'
}
});
Self.refund = async(salesIds, servicesIds, createSingleTicket = false, options) => {
const models = Self.app.models;
const myOptions = {};
let tx;
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const refundAgencyMode = await models.AgencyMode.findOne({
include: {
relation: 'zones',
scope: {
limit: 1,
field: ['id', 'name']
}
},
where: {code: 'refund'}
}, myOptions);
const refoundZoneId = refundAgencyMode.zones()[0].id;
const salesFilter = {
where: {id: {inq: salesIds}},
include: {
relation: 'components',
scope: {
fields: ['saleFk', 'componentFk', 'value']
}
}
};
const sales = await models.Sale.find(salesFilter, myOptions);
const ticketsIds = [...new Set(sales.map(sale => sale.ticketFk))];
const refundTickets = [];
const mappedTickets = new Map();
const now = Date.vnNew();
const [firstTicketId] = ticketsIds;
if (createSingleTicket) {
await createTicketRefund(
firstTicketId,
refundTickets,
mappedTickets,
now,
refundAgencyMode,
refoundZoneId,
myOptions
);
} else {
for (let ticketId of ticketsIds) {
await createTicketRefund(
ticketId,
refundTickets,
mappedTickets,
now,
refundAgencyMode,
refoundZoneId,
myOptions
);
}
}
for (const sale of sales) {
const refundTicketId = await getTicketRefundId(createSingleTicket, sale.ticketFk, refundTickets, mappedTickets);
const createdSale = await models.Sale.create({
ticketFk: refundTicketId,
itemFk: sale.itemFk,
quantity: - sale.quantity,
concept: sale.concept,
price: sale.price,
discount: sale.discount,
}, myOptions);
const components = sale.components();
for (const component of components)
component.saleFk = createdSale.id;
await models.SaleComponent.create(components, myOptions);
}
if (servicesIds && servicesIds.length > 0) {
const servicesFilter = {
where: {id: {inq: servicesIds}}
};
const services = await models.TicketService.find(servicesFilter, myOptions);
for (const service of services) {
const refundTicketId = await getTicketRefundId(createSingleTicket, service.ticketFk, refundTickets, mappedTickets);
await models.TicketService.create({
description: service.description,
quantity: - service.quantity,
price: service.price,
taxClassFk: service.taxClassFk,
ticketFk: refundTicketId,
ticketServiceTypeFk: service.ticketServiceTypeFk,
}, myOptions);
}
}
if (tx) await tx.commit();
return refundTickets;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
async function createTicketRefund(
ticketId,
refundTickets,
mappedTickets,
now,
refundAgencyMode,
refoundZoneId,
myOptions
) {
const models = Self.app.models;
const filter = {include: {relation: 'address'}};
const ticket = await models.Ticket.findById(ticketId, filter, myOptions);
const refundTicket = await models.Ticket.create({
clientFk: ticket.clientFk,
shipped: now,
addressFk: ticket.address().id,
agencyModeFk: refundAgencyMode.id,
nickname: ticket.address().nickname,
warehouseFk: ticket.warehouseFk,
companyFk: ticket.companyFk,
landed: now,
zoneFk: refoundZoneId
}, myOptions);
refundTickets.push(refundTicket);
mappedTickets.set(ticketId, refundTicket.id);
await models.TicketRefund.create({
refundTicketFk: refundTicket.id,
originalTicketFk: ticket.id,
}, myOptions);
}
async function getTicketRefundId(createSingleTicket, ticketId, refundTickets, mappedTickets) {
if (createSingleTicket) {
const [firstRefundTicket] = refundTickets;
return firstRefundTicket.id;
} else return mappedTickets.get(ticketId);
}
};

View File

@ -24,7 +24,15 @@
</vn-watcher> </vn-watcher>
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md"> <form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
<vn-card class="vn-pa-lg"> <vn-card class="vn-pa-lg">
<vn-button
name="refund"
label="Refund"
ng-click="$ctrl.createRefund()"
vn-acl="invoicing, claimManager, salesAssistant"
vn-acl-action="remove">
</vn-button>
<vn-horizontal ng-repeat="service in $ctrl.services track by $index"> <vn-horizontal ng-repeat="service in $ctrl.services track by $index">
<vn-check ng.model="service.checked"></vn-check>
<vn-autocomplete vn-two vn-focus <vn-autocomplete vn-two vn-focus
data="ticketServiceTypes" data="ticketServiceTypes"
label="Description" label="Description"
@ -41,11 +49,13 @@
</vn-icon-button> </vn-icon-button>
</append> </append>
</vn-autocomplete> </vn-autocomplete>
<vn-input-number <vn-input-number
vn-one vn-one
step="1" step="1"
label="Quantity" label="Quantity"
ng-model="service.quantity" ng-model="service.quantity"
info="To create services with negative amounts mark the service on the source ticket and press the pay button."
rule="TicketService"> rule="TicketService">
</vn-input-number> </vn-input-number>
<vn-input-number <vn-input-number

View File

@ -24,6 +24,23 @@ class Controller extends Section {
}); });
} }
selectedServices() {
if (!this.services) return;
return this.services.filter(services => {
return this.services.checked;
});
}
selectedValidServices() {
if (!this.services) return;
const selectedServices = this.selectedServices();
return selectedServices.filter(service => {
return service.id != undefined;
});
}
onNewServiceTypeClick(service, event) { onNewServiceTypeClick(service, event) {
event.preventDefault(); event.preventDefault();
this.$.newServiceType = {}; this.$.newServiceType = {};
@ -42,6 +59,25 @@ class Controller extends Section {
.then(res => service.ticketServiceTypeFk = res.data.id); .then(res => service.ticketServiceTypeFk = res.data.id);
} }
createRefund() {
const services = this.selectedServices();
if (!services) return;
const servicesIds = services.map(service => service.id);
const params = {servicesIds: servicesIds};
const query = 'service/refund';
this.$http.post(query, params).then(res => {
const [refundTicket] = res.data;
this.vnApp.showSuccess(this.$t('The following refund ticket have been created', {
ticketId: refundTicket.id
}));
this.$state.go('ticket.card.sale', {id: refundTicket.id});
this.resetChanges();
});
}
onSubmit() { onSubmit() {
this.$.watcher.check(); this.$.watcher.check();

View File

@ -2,4 +2,6 @@ Service: Servicios
Tax class: Tipo IVA Tax class: Tipo IVA
Add service: Añadir servicio Add service: Añadir servicio
Remove service: Quitar servicio Remove service: Quitar servicio
New service type: Nuevo tipo de servicio New service type: Nuevo tipo de servicio
Pay: Abono
To create services with negative amounts mark the service on the source ticket and press the pay button.: Para crear sevicios con cantidades negativas marcar servicio en el ticket origen y apretar el boton abonar.