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