#6335 -ticketAdvance_splitOrCreate #1817
|
@ -8,8 +8,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
## [2346.01] - 2023-11-16
|
||||
|
||||
### Added
|
||||
- (Ticket -> Adelantar) Permite mover lineas sin generar negativos
|
||||
- (Ticket -> Adelantar) Permite modificar la fecha de los tickets
|
||||
|
||||
### Changed
|
||||
### Fixed
|
||||
- (Ticket -> RocketChat) Arreglada detección de cambios
|
||||
|
||||
|
||||
## [2342.01] - 2023-11-02
|
||||
|
||||
|
|
|
@ -224,7 +224,9 @@
|
|||
"date in the future": "Fecha en el futuro",
|
||||
"reference duplicated": "Referencia duplicada",
|
||||
"This ticket is already a refund": "Este ticket ya es un abono",
|
||||
"isWithoutNegatives": "isWithoutNegatives",
|
||||
"isWithoutNegatives": "Sin negativos",
|
||||
"newTicket": "Nuevo ticket",
|
||||
"keepPrice": "Mantener precios",
|
||||
"routeFk": "routeFk",
|
||||
"Can't change the password of another worker": "No se puede cambiar la contraseña de otro trabajador",
|
||||
"No hay un contrato en vigor": "No hay un contrato en vigor",
|
||||
|
@ -321,9 +323,13 @@
|
|||
"Select a different client": "Seleccione un cliente distinto",
|
||||
"Fill all the fields": "Rellene todos los campos",
|
||||
"The response is not a PDF": "La respuesta no es un PDF",
|
||||
"Ticket without Route": "Ticket sin ruta",
|
||||
"Booking completed": "Reserva completada",
|
||||
"The ticket is in preparation": "El ticket [{{ticketId}}]({{{ticketUrl}}}) del comercial {{salesPersonId}} está en preparación",
|
||||
"The amount cannot be less than the minimum": "La cantidad no puede ser menor que la cantidad mímina",
|
||||
"quantityLessThanMin": "La cantidad no puede ser menor que la cantidad mímina"
|
||||
"quantityLessThanMin": "La cantidad no puede ser menor que la cantidad mímina",
|
||||
"__cachedRelations": "__cachedRelations",
|
||||
"__data": "__data",
|
||||
"__strict": "__strict",
|
||||
"__persisted": "__persisted",
|
||||
"client": "client"
|
||||
}
|
|
@ -163,7 +163,7 @@ module.exports = Self => {
|
|||
}
|
||||
}
|
||||
|
||||
const originalTicket = await models.Ticket.findOne({
|
||||
const ticketToChange = await models.Ticket.findOne({
|
||||
where: {id: args.id},
|
||||
fields: [
|
||||
'id',
|
||||
|
@ -196,13 +196,7 @@ module.exports = Self => {
|
|||
},
|
||||
]
|
||||
}, myOptions);
|
||||
|
||||
args.routeFk = null;
|
||||
if (args.isWithoutNegatives === false) delete args.isWithoutNegatives;
|
||||
const updatedTicket = Object.assign({}, args);
|
||||
delete updatedTicket.ctx;
|
||||
delete updatedTicket.option;
|
||||
|
||||
const originalTicket = JSON.parse(JSON.stringify(ticketToChange));
|
||||
|
||||
const ticketChages = {
|
||||
clientFk: args.clientFk,
|
||||
nickname: args.nickname,
|
||||
|
@ -219,18 +213,21 @@ module.exports = Self => {
|
|||
let response;
|
||||
if (args.keepPrice) {
|
||||
ticketChages.routeFk = null;
|
||||
response = await originalTicket.updateAttributes(ticketChages, myOptions);
|
||||
response = await ticketToChange.updateAttributes(ticketChages, myOptions);
|
||||
} else {
|
||||
const hasToBeUnrouted = true;
|
||||
const query = 'CALL vn.ticket_componentMakeUpdate(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
response = await Self.rawSql(
|
||||
query,
|
||||
'CALL vn.ticket_componentMakeUpdate(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
|
||||
[args.id].concat(Object.values(ticketChages), [hasToBeUnrouted, args.option]),
|
||||
myOptions
|
||||
);
|
||||
}
|
||||
if (args.isWithoutNegatives === false) delete args.isWithoutNegatives;
|
||||
const updatedTicket = Object.assign({}, args, JSON.parse(JSON.stringify(ticketToChange)));
|
||||
delete updatedTicket.ctx;
|
||||
delete updatedTicket.option;
|
||||
|
||||
if (originalTicket.addressFk != updatedTicket.addressFk && args.id) {
|
||||
if (ticketToChange.addressFk != updatedTicket.addressFk && args.id) {
|
||||
await models.TicketObservation.destroyAll({
|
||||
ticketFk: args.id
|
||||
}, myOptions);
|
||||
|
@ -252,15 +249,20 @@ module.exports = Self => {
|
|||
await models.TicketObservation.create(clonedObservations, myOptions);
|
||||
}
|
||||
}
|
||||
|
||||
const changes = loggable.getChanges(originalTicket, updatedTicket);
|
||||
|
||||
const hasChanges = Object.keys(changes.old).length > 0 || Object.keys(changes.new).length > 0;
|
||||
|
||||
if (hasChanges) {
|
||||
delete changes.old.client;
|
||||
delete changes.old.address;
|
||||
delete changes.new.client;
|
||||
delete changes.new.address;
|
||||
|
||||
const oldProperties = await loggable.translateValues(Self, changes.old);
|
||||
const newProperties = await loggable.translateValues(Self, changes.new);
|
||||
|
||||
const salesPersonId = originalTicket.client().salesPersonFk;
|
||||
const salesPersonId = ticketToChange.client().salesPersonFk;
|
||||
if (salesPersonId) {
|
||||
const url = await Self.app.models.Url.getUrl();
|
||||
|
||||
|
@ -283,7 +285,7 @@ module.exports = Self => {
|
|||
|
||||
response.id = args.id;
|
||||
console.log(originalTicketId, args.newTicket ? ` TRANSFER TO → ` : ` CREATE NEW TICKET → `, args.id);
|
||||
if (tx) await tx.rollback();
|
||||
if (tx) await tx.commit();
|
||||
|
||||
return response;
|
||||
} catch (e) {
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
</vn-button>
|
||||
<vn-button
|
||||
disabled="$ctrl.checked.length === 0"
|
||||
icon="swap_horiz"
|
||||
icon="alt_route"
|
||||
ng-click="splitTickets.show($event)"
|
||||
vn-tooltip="Advance tickets without negatives">
|
||||
</vn-button>
|
||||
|
@ -121,7 +121,7 @@
|
|||
<span
|
||||
ng-click="ticketDescriptor.show($event, ticket.id)"
|
||||
class="link">
|
||||
{{::ticket.id | dashIfEmpty}}
|
||||
{{::ticket.id}}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{::ticket.ipt | dashIfEmpty}}</td>
|
||||
|
@ -137,7 +137,7 @@
|
|||
<span
|
||||
class="chip {{$ctrl.totalPriceColor(ticket.totalWithVat)}}"
|
||||
title="{{$ctrl.totalPriceTitle(ticket.totalWithVat) | translate}}">
|
||||
{{::(ticket.totalWithVat ? ticket.totalWithVat : 0) | currency: 'EUR': 2}}
|
||||
{{::ticket.totalWithVat | currency: 'EUR': 2}}
|
||||
</span>
|
||||
</td>
|
||||
<td separator>
|
||||
|
@ -193,22 +193,24 @@
|
|||
<!-- Split progress -->
|
||||
<vn-dialog
|
||||
vn-id="splitProgress"
|
||||
message="Split progress">
|
||||
message="Progress">
|
||||
<tpl-body>
|
||||
<vn-vertical>
|
||||
<vn-spinner
|
||||
enable="splitProgress.enable">
|
||||
</vn-spinner>
|
||||
<vn-label-value
|
||||
label="Progres"
|
||||
value="[{{$ctrl.progress.length}}/{{$ctrl.checked.length}}]">
|
||||
label="Total progress"
|
||||
value="[{{$ctrl.progress.length}}/{{::$ctrl.checked.length}}]">
|
||||
</vn-label-value>
|
||||
<span class="vn-mt-md" ng-if="$ctrl.splitErrors.length" translate>Error list</span>
|
||||
<vn-vertical ng-repeat="error in $ctrl.splitErrors">
|
||||
<vn-label-value
|
||||
ng-if="$ctrl.splitErrors.length"
|
||||
label="Errors list"
|
||||
value="{{$ctrl.splitErrors}}">
|
||||
label="{{error.id}}"
|
||||
value="{{error.reason}}">
|
||||
</vn-label-value>
|
||||
</vn-vertical>
|
||||
</vn-vertical>
|
||||
</tpl-body>
|
||||
<tpl-buttons>
|
||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}" ng-click="splitProgress.cancel = true"/>
|
||||
|
|
|
@ -120,10 +120,16 @@ export default class Controller extends Section {
|
|||
'\n' + this.$t(`Destination agency`, {agency: agency});
|
||||
}
|
||||
|
||||
moveTicketsAdvance() {
|
||||
async moveTicketsAdvance() {
|
||||
let ticketsToMove = [];
|
||||
// falta ver que hacer con los nulls
|
||||
for (ticket of this.checked) {
|
||||
for (const ticket of this.checked) {
|
||||
if (!ticket.id) {
|
||||
try {
|
||||
const {query, params} = await this.requestComponentUpdate(ticket, false);
|
||||
this.$http.post(query, params);
|
||||
} catch (e) {}
|
||||
continue;
|
||||
}
|
||||
ticketsToMove.push({
|
||||
originId: ticket.futureId,
|
||||
destinationId: ticket.id,
|
||||
|
@ -136,10 +142,12 @@ export default class Controller extends Section {
|
|||
const params = {tickets: ticketsToMove};
|
||||
return this.$http.post('Tickets/merge', params)
|
||||
.then(() => {
|
||||
this.$.model.refresh();
|
||||
this.vnApp.showSuccess(this.$t('Success'));
|
||||
this.refresh();
|
||||
if (ticketsToMove.length)
|
||||
this.vnApp.showSuccess(this.$t('Success', {tickets: ticketsToMove.length}));
|
||||
});
|
||||
}
|
||||
|
||||
async getLanded(params) {
|
||||
const query = `Agencies/getLanded`;
|
||||
return this.$http.get(query, {params}).then(res => {
|
||||
|
@ -160,20 +168,52 @@ export default class Controller extends Section {
|
|||
this.$.splitProgress.enable = true;
|
||||
this.$.splitProgress.cancel = false;
|
||||
this.$.splitProgress.show();
|
||||
|
||||
for (const ticket of this.checked) {
|
||||
if (this.$.splitProgress.cancel) break;
|
||||
try {
|
||||
const {query, params} = await this.requestComponentUpdate(ticket, true);
|
||||
this.$http.post(query, params)
|
||||
.catch(e => {
|
||||
this.splitErrors.push({id: ticket.futureId, reason: e.message});
|
||||
})
|
||||
.finally(() => this.progressAdd(ticket.futureId));
|
||||
} catch (e) {
|
||||
this.splitErrors.push({id: ticket.futureId, reason: e.message});
|
||||
this.progressAdd(ticket.futureId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
progressAdd(ticketId) {
|
||||
this.progress.push(ticketId);
|
||||
if (this.progress.length == this.checked.length) {
|
||||
this.$.splitProgress.enable = false;
|
||||
this.refresh();
|
||||
if ((this.progress.length - this.splitErrors.length) > 0) {
|
||||
this.vnApp.showSuccess(this.$t('Success', {
|
||||
tickets: this.progress.length - this.splitErrors.length
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async requestComponentUpdate(ticket, isWithoutNegatives) {
|
||||
const query = `tickets/${ticket.futureId}/componentUpdate`;
|
||||
if (!ticket.landed) {
|
||||
console.log(ticket);
|
||||
const newLanded = await this.getLanded({
|
||||
shipped: this.$.model.userParams.dateToAdvance,
|
||||
addressFk: ticket.addressFk,
|
||||
agencyModeFk: ticket.agencyModeFk,
|
||||
warehouseFk: ticket.warehouseFk
|
||||
});
|
||||
ticket.landed = newLanded?.landed;
|
||||
ticket.zoneFk = newLanded?.zoneFk;
|
||||
if (!newLanded)
|
||||
throw new Error(this.$t(`No delivery zone available for this landing date`));
|
||||
|
||||
ticket.landed = newLanded.landed;
|
||||
ticket.zoneFk = newLanded.zoneFk;
|
||||
}
|
||||
const query = `tickets/${ticket.futureId}/componentUpdate`;
|
||||
const params = {
|
||||
clientFk: ticket.clientFk,
|
||||
alexm
commented
dest OR origin dest OR origin
|
||||
nickname: ticket.nickname,
|
||||
|
@ -185,28 +225,18 @@ export default class Controller extends Section {
|
|||
shipped: this.$.model.userParams.dateToAdvance,
|
||||
landed: ticket.landed,
|
||||
isDeleted: false,
|
||||
isWithoutNegatives: true,
|
||||
withWarningAccept: false,
|
||||
isWithoutNegatives,
|
||||
newTicket: ticket.id ?? undefined,
|
||||
keepPrice: true
|
||||
};
|
||||
console.log(params);
|
||||
return {query, params};
|
||||
}
|
||||
|
||||
this.$http.post(query, params)
|
||||
.catch(e => {
|
||||
this.splitErrors.push({id: ticket.futureId, reason: e.message});
|
||||
})
|
||||
.finally(() => {
|
||||
this.progress.push(ticket.futureId);
|
||||
if (this.progress.length == this.checked.length) {
|
||||
this.$.splitProgress.enable = false;
|
||||
refresh() {
|
||||
this.$.model.refresh();
|
||||
this.vnApp.showSuccess(this.$t('Success'));
|
||||
this.$checkAll = null;
|
||||
}
|
||||
});
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
exprBuilder(param, value) {
|
||||
switch (param) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
Advance tickets: Adelantar tickets
|
||||
Search advance tickets by date: Busca tickets para adelantar por fecha
|
||||
Advance confirmation: ¿Desea adelantar {{checked}} tickets?
|
||||
Success: Tickets movidos correctamente
|
||||
Success: "{{tickets}} Tickets movidos correctamente"
|
||||
Lines: Líneas
|
||||
Liters: Litros
|
||||
Item Packing Type: Encajado
|
||||
|
@ -9,3 +9,7 @@ Origin agency: "Agencia origen: {{agency}}"
|
|||
Destination agency: "Agencia destino: {{agency}}"
|
||||
Less than 50€: Menor a 50€
|
||||
Not Movable: No movibles
|
||||
Error list: Lista de errores
|
||||
Progress: Progreso
|
||||
Total progress: Progreso total
|
||||
Advance tickets (without negatives): Adelantar tickets (sin negativos)
|
||||
|
|
Loading…
Reference in New Issue
changes