diff --git a/db/dump/fixtures.before.sql b/db/dump/fixtures.before.sql index 788854b4e..590fe34b6 100644 --- a/db/dump/fixtures.before.sql +++ b/db/dump/fixtures.before.sql @@ -694,22 +694,22 @@ INSERT INTO `vn`.`invoiceOutExpense`(`id`, `invoiceOutFk`, `amount`, `expenseFk` (6, 4, 8.07, 2000000000, util.VN_CURDATE()), (7, 5, 8.07, 2000000000, util.VN_CURDATE()); -INSERT INTO `vn`.`zone` (`id`, `name`, `hour`, `agencyModeFk`, `travelingDays`, `price`, `bonus`, `itemMaxSize`) - VALUES - (1, 'Zone pickup A', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 1, 0, 1, 0, 100), - (2, 'Zone pickup B', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 1, 0, 1, 0, 100), - (3, 'Zone 247 A', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 7, 1, 2, 0, 100), - (4, 'Zone 247 B', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 7, 1, 2, 0, 100), - (5, 'Zone expensive A', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 8, 1, 1000, 0, 100), - (6, 'Zone expensive B', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 8, 1, 1000, 0, 100), - (7, 'Zone refund', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 23, 0, 1, 0, 100), - (8, 'Zone others', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 10, 0, 1, 0, 100), - (9, 'Zone superMan', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 2, 0, 1, 0, 100), - (10, 'Zone teleportation', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 3, 0, 1, 0, 100), - (11, 'Zone pickup C', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 1, 0, 1, 0, 100), - (12, 'Zone entanglement', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 4, 0, 1, 0, 100), - (13, 'Zone quantum break', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 5, 0, 1, 0, 100); - +INSERT INTO `vn`.`zone` + (`id`, `name`, `hour`, `agencyModeFk`, `travelingDays`, `price`, `bonus`, `itemMaxSize`, `priceOptimum`) +VALUES + (1, 'Zone pickup A', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 1, 0, 1, 0, 100, 1), + (2, 'Zone pickup B', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 1, 0, 1, 0, 100, 1), + (3, 'Zone 247 A', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 7, 1, 2, 0, 100, 1), + (4, 'Zone 247 B', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 7, 1, 2, 0, 100, 1), + (5, 'Zone expensive A', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 8, 1, 1000, 0, 100, 500), + (6, 'Zone expensive B', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 8, 1, 1000, 0, 100, 500), + (7, 'Zone refund', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 23, 0, 1, 0, 100, 0.5), + (8, 'Zone others', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 10, 0, 1, 0, 100, 0.5), + (9, 'Zone superMan', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 2, 0, 1, 0, 100, 0.5), + (10, 'Zone teleportation', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 3, 0, 1, 0, 100, 0.5), + (11, 'Zone pickup C', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 1, 0, 1, 0, 100, 0.5), + (12, 'Zone entanglement', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 4, 0, 1, 0, 100, 0.5), + (13, 'Zone quantum break', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 5, 0, 1, 0, 100, 0.5); INSERT INTO `vn`.`zoneWarehouse` (`id`, `zoneFk`, `warehouseFk`) VALUES diff --git a/db/routines/vn/events/client_setPackagesDiscountFactor.sql b/db/routines/vn/events/client_setPackagesDiscountFactor.sql new file mode 100644 index 000000000..a0dc33cac --- /dev/null +++ b/db/routines/vn/events/client_setPackagesDiscountFactor.sql @@ -0,0 +1,8 @@ +DELIMITER $$ +CREATE OR REPLACE DEFINER=`vn`@`localhost` EVENT `vn`.`client_setPackagesDiscountFactor` + ON SCHEDULE EVERY 1 DAY + STARTS '2024-10-18 03:00:00.000' + ON COMPLETION PRESERVE + ENABLE +DO CALL client_setPackagesDiscountFactor()$$ +DELIMITER ; diff --git a/db/routines/vn/procedures/catalog_componentCalculate.sql b/db/routines/vn/procedures/catalog_componentCalculate.sql index e29e13a8c..aaf2db408 100644 --- a/db/routines/vn/procedures/catalog_componentCalculate.sql +++ b/db/routines/vn/procedures/catalog_componentCalculate.sql @@ -231,7 +231,19 @@ BEGIN SELECT tcc.warehouseFK, tcc.itemFk, c2.id, - z.inflation * ROUND(ic.cm3delivery * (IFNULL(zo.price,5000) - IFNULL(zo.bonus,0)) / (1000 * vc.standardFlowerBox) , 4) cost + z.inflation + * ROUND( + ic.cm3delivery + * ( + ( + zo.priceOptimum + (( zo.price - zo.priceOptimum) * 2 * ( 1 - c.packagesDiscountFactor)) + ) + - IFNULL(zo.bonus, 0) + ) + / (1000 * vc.standardFlowerBox), + 4 + ) cost + FROM tmp.ticketComponentCalculate tcc JOIN item i ON i.id = tcc.itemFk JOIN tmp.zoneOption zo ON zo.zoneFk = vZoneFk @@ -239,6 +251,7 @@ BEGIN JOIN agencyMode am ON am.id = z.agencyModeFk JOIN vn.volumeConfig vc JOIN vn.component c2 ON c2.code = 'delivery' + JOIN `client` c on c.id = vClientFk LEFT JOIN itemCost ic ON ic.warehouseFk = tcc.warehouseFk AND ic.itemFk = tcc.itemFk HAVING cost <> 0; diff --git a/db/routines/vn/procedures/client_setPackagesDiscountFactor.sql b/db/routines/vn/procedures/client_setPackagesDiscountFactor.sql new file mode 100644 index 000000000..f6068ca37 --- /dev/null +++ b/db/routines/vn/procedures/client_setPackagesDiscountFactor.sql @@ -0,0 +1,25 @@ +DELIMITER $$ + +CREATE OR REPLACE DEFINER=`vn`@`localhost` +PROCEDURE `vn`.`client_setPackagesDiscountFactor`() +BEGIN + /** + * Set the discount factor for the packages of the clients. + */ + UPDATE client c + JOIN ( + SELECT t.clientFk, + LEAST(( + SUM(t.packages) / COUNT(DISTINCT DATE(t.shipped)) + ) / cc.packagesOptimum, 1) discountFactor + FROM ticket t + JOIN clientConfig cc ON TRUE + WHERE t.shipped > util.VN_CURDATE() - INTERVAL cc.monthsToCalcOptimumPrice MONTH + AND t.packages + GROUP BY t.clientFk + ) ca ON c.id = ca.clientFk + SET c.packagesDiscountFactor = ca.discountFactor; + +END$$ + +DELIMITER ; diff --git a/db/routines/vn/procedures/zone_getAddresses.sql b/db/routines/vn/procedures/zone_getAddresses.sql index 2e5982c82..9946b0b73 100644 --- a/db/routines/vn/procedures/zone_getAddresses.sql +++ b/db/routines/vn/procedures/zone_getAddresses.sql @@ -1,26 +1,27 @@ DELIMITER $$ CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`zone_getAddresses`( vSelf INT, - vShipped DATE, + vLanded DATE, vDepartmentFk INT ) BEGIN /** * Devuelve un listado de todos los clientes activos * con consignatarios a los que se les puede - * vender producto para esa zona. + * entregar producto para esa zona. * * @param vSelf Id de zona - * @param vShipped Fecha de envio - * @param vDepartmentFk Id de departamento + * @param vLanded Fecha de entrega + * @param vDepartmentFk Id de departamento | NULL para mostrar todos * @return Un select */ CALL zone_getPostalCode(vSelf); WITH clientWithTicket AS ( - SELECT clientFk + SELECT DISTINCT clientFk FROM vn.ticket - WHERE shipped BETWEEN vShipped AND util.dayEnd(vShipped) + WHERE landed BETWEEN vLanded AND util.dayEnd(vLanded) + AND NOT isDeleted ) SELECT c.id, c.name, @@ -30,7 +31,7 @@ BEGIN u.name username, aai.invoiced, cnb.lastShipped, - cwt.clientFk + IF(cwt.clientFk, TRUE, FALSE) hasTicket FROM vn.client c JOIN vn.worker w ON w.id = c.salesPersonFk JOIN vn.workerDepartment wd ON wd.workerFk = w.id @@ -50,7 +51,7 @@ BEGIN AND c.isActive AND ct.code = 'normal' AND bt.code <> 'worker' - AND (d.id = vDepartmentFk OR NOT vDepartmentFk) + AND (d.id = vDepartmentFk OR vDepartmentFk IS NULL) GROUP BY c.id; DROP TEMPORARY TABLE tmp.zoneNodes; diff --git a/db/routines/vn/procedures/zone_getOptionsForShipment.sql b/db/routines/vn/procedures/zone_getOptionsForShipment.sql index fa48b0b0f..17d1b3d11 100644 --- a/db/routines/vn/procedures/zone_getOptionsForShipment.sql +++ b/db/routines/vn/procedures/zone_getOptionsForShipment.sql @@ -9,7 +9,7 @@ BEGIN * @return tmp.zoneOption(zoneFk, hour, travelingDays, price, bonus, specificity) The computed options */ DECLARE vHour TIME DEFAULT TIME(util.VN_NOW()); - + DROP TEMPORARY TABLE IF EXISTS tLandings; CREATE TEMPORARY TABLE tLandings (INDEX (eventFk)) @@ -30,6 +30,7 @@ BEGIN TIME(IFNULL(e.`hour`, z.`hour`)) `hour`, l.travelingDays, IFNULL(e.price, z.price) price, + IFNULL(e.priceOptimum, z.priceOptimum) priceOptimum, IFNULL(e.bonus, z.bonus) bonus, l.landed, vShipped shipped diff --git a/db/versions/11398-orangeRose/00-zoneEventPriceOptimum.sql b/db/versions/11398-orangeRose/00-zoneEventPriceOptimum.sql new file mode 100644 index 000000000..0440714e4 --- /dev/null +++ b/db/versions/11398-orangeRose/00-zoneEventPriceOptimum.sql @@ -0,0 +1,5 @@ +ALTER TABLE `vn`.`zoneEvent` + ADD COLUMN `priceOptimum` DECIMAL(10,2) NULL COMMENT 'Precio mínimo que puede pagar un bulto' + AFTER `price`, + ADD CONSTRAINT `ck_zoneEvent_priceOptimum` + CHECK (priceOptimum <= price) diff --git a/db/versions/11398-orangeRose/00-zonePriceOptimum.sql b/db/versions/11398-orangeRose/00-zonePriceOptimum.sql new file mode 100644 index 000000000..82b2001cd --- /dev/null +++ b/db/versions/11398-orangeRose/00-zonePriceOptimum.sql @@ -0,0 +1,5 @@ +ALTER TABLE `vn`.`zone` + ADD COLUMN `priceOptimum` DECIMAL(10,2) NOT NULL COMMENT 'Precio mínimo que puede pagar un bulto' + AFTER `price`, + ADD CONSTRAINT `ck_zone_priceOptimum` + CHECK (priceOptimum <= price) diff --git a/db/versions/11398-orangeRose/01-zoneUpdate.sql b/db/versions/11398-orangeRose/01-zoneUpdate.sql new file mode 100644 index 000000000..042f2a92b --- /dev/null +++ b/db/versions/11398-orangeRose/01-zoneUpdate.sql @@ -0,0 +1,2 @@ +UPDATE `vn`.`zone` + SET `priceOptimum` = `price`; diff --git a/db/versions/11398-orangeRose/02-clientAlter.sql b/db/versions/11398-orangeRose/02-clientAlter.sql new file mode 100644 index 000000000..b5275a301 --- /dev/null +++ b/db/versions/11398-orangeRose/02-clientAlter.sql @@ -0,0 +1,3 @@ +ALTER TABLE `vn`.`client` + ADD COLUMN `packagesDiscountFactor` DECIMAL(4,3) NOT NULL DEFAULT 1.000 + COMMENT 'Porcentaje de ajuste entre el numero de bultos medio del cliente, y el número medio óptimo para las zonas en las que compra'; diff --git a/db/versions/11398-orangeRose/03-clientConfig.sql b/db/versions/11398-orangeRose/03-clientConfig.sql new file mode 100644 index 000000000..2869f26a2 --- /dev/null +++ b/db/versions/11398-orangeRose/03-clientConfig.sql @@ -0,0 +1,3 @@ +ALTER TABLE `vn`.`clientConfig` + ADD COLUMN `packagesOptimum` INT UNSIGNED NOT NULL DEFAULT 20 COMMENT 'Numero de bultos por cliente/dia para conseguir el precio optimo', + ADD COLUMN `monthsToCalcOptimumPrice` TINYINT UNSIGNED NOT NULL DEFAULT 3 COMMENT 'Número de meses a usar para el cálculo de client.packagesDiscountFactor'; diff --git a/db/versions/11415-chocolateTulip/00-firstScript.sql b/db/versions/11415-chocolateTulip/00-firstScript.sql new file mode 100644 index 000000000..2ed7ec9b5 --- /dev/null +++ b/db/versions/11415-chocolateTulip/00-firstScript.sql @@ -0,0 +1 @@ +CREATE INDEX ticket_landed_IDX USING BTREE ON vn.ticket (landed); diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 8d5eab4bc..06428475f 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -211,7 +211,7 @@ "Name should be uppercase": "Name should be uppercase", "You cannot update these fields": "You cannot update these fields", "CountryFK cannot be empty": "Country cannot be empty", - "No tickets to invoice": "There are no tickets to invoice that meet the invoicing requirements", + "No tickets to invoice": "There are no tickets to invoice that meet the invoicing requirements", "You are not allowed to modify the alias": "You are not allowed to modify the alias", "You already have the mailAlias": "You already have the mailAlias", "This machine is already in use.": "This machine is already in use.", @@ -247,9 +247,11 @@ "ticketLostExpedition": "The ticket [{{ticketId}}]({{{ticketUrl}}}) has the following lost expedition:{{ expeditionId }}", "The raid information is not correct": "The raid information is not correct", "Payment method is required": "Payment method is required", - "Sales already moved": "Sales already moved", - "Holidays to past days not available": "Holidays to past days not available", "Price cannot be blank": "Price cannot be blank", "There are tickets to be invoiced": "There are tickets to be invoiced", - "The address of the customer must have information about Incoterms and Customs Agent": "The address of the customer must have information about Incoterms and Customs Agent" -} + "The address of the customer must have information about Incoterms and Customs Agent": "The address of the customer must have information about Incoterms and Customs Agent", + "Sales already moved": "Sales already moved", + "Holidays to past days not available": "Holidays to past days not available", + "Incorrect delivery order alert on route": "Incorrect delivery order alert on route: {{ route }} zone: {{ zone }}", + "Ticket has been delivered out of order": "The ticket {{ticket}} {{{fullUrl}}} has been delivered out of order." +} \ No newline at end of file diff --git a/loopback/locale/es.json b/loopback/locale/es.json index cde81e0cb..abd2f79a0 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -390,13 +390,11 @@ "The web user's email already exists": "El correo del usuario web ya existe", "Sales already moved": "Ya han sido transferidas", "The raid information is not correct": "La información de la redada no es correcta", - "No trips found because input coordinates are not connected": "No se encontraron rutas porque las coordenadas de entrada no están conectadas", - "This request is not supported": "Esta solicitud no es compatible", - "Invalid options or too many coordinates": "Opciones invalidas o demasiadas coordenadas", - "No address has coordinates": "Ninguna dirección tiene coordenadas", "An item type with the same code already exists": "Un tipo con el mismo código ya existe", "Holidays to past days not available": "Las vacaciones a días pasados no están disponibles", "All tickets have a route order": "Todos los tickets tienen orden de ruta", - "Price cannot be blank": "Price cannot be blank", - "There are tickets to be invoiced": "La zona tiene tickets por facturar" -} + "There are tickets to be invoiced": "La zona tiene tickets por facturar", + "Incorrect delivery order alert on route": "Alerta de orden de entrega incorrecta en ruta: {{ route }} zona: {{ zone }}", + "Ticket has been delivered out of order": "El ticket {{ticket}} {{{fullUrl}}} no ha sigo entregado en su orden.", + "Price cannot be blank": "El precio no puede estar en blanco" +} \ No newline at end of file diff --git a/loopback/locale/fr.json b/loopback/locale/fr.json index f49196a8f..d7d5b7710 100644 --- a/loopback/locale/fr.json +++ b/loopback/locale/fr.json @@ -362,9 +362,11 @@ "The invoices have been created but the PDFs could not be generated": "La facture a été émise mais le PDF n'a pas pu être généré", "It has been invoiced but the PDF of refund not be generated": "Il a été facturé mais le PDF de remboursement n'a pas été généré", "Cannot send mail": "Impossible d'envoyer le mail", - "Original invoice not found": "Facture originale introuvable", - "The quantity claimed cannot be greater than the quantity of the line": "Le montant réclamé ne peut pas être supérieur au montant de la ligne", - "You do not have permission to modify the booked field": "Vous n'avez pas la permission de modifier le champ comptabilisé", + "Original invoice not found": "Facture originale introuvable", + "The quantity claimed cannot be greater than the quantity of the line": "Le montant réclamé ne peut pas être supérieur au montant de la ligne", + "You do not have permission to modify the booked field": "Vous n'avez pas la permission de modifier le champ comptabilisé", "ticketLostExpedition": "Le ticket [{{ticketId}}]({{{ticketUrl}}}) a l'expédition perdue suivante : {{expeditionId}}", - "The web user's email already exists": "L'email de l'internaute existe déjà" -} + "The web user's email already exists": "L'email de l'internaute existe déjà", + "Incorrect delivery order alert on route": "Alerte de bon de livraison incorrect sur l'itinéraire: {{ route }} zone : {{ zone }}", + "Ticket has been delivered out of order": "Le ticket {{ticket}} {{{fullUrl}}} a été livré hors ordre." +} \ No newline at end of file diff --git a/loopback/locale/pt.json b/loopback/locale/pt.json index e2374d35f..d1ac2ef23 100644 --- a/loopback/locale/pt.json +++ b/loopback/locale/pt.json @@ -365,5 +365,7 @@ "Cannot send mail": "Não é possível enviar o email", "The quantity claimed cannot be greater than the quantity of the line": "O valor reclamado não pode ser superior ao valor da linha", "ticketLostExpedition": "O ticket [{{ticketId}}]({{{ticketUrl}}}) tem a seguinte expedição perdida: {{expeditionId}}", - "The web user's email already exists": "O e-mail do utilizador da web já existe." -} + "The web user's email already exists": "O e-mail do utilizador da web já existe.", + "Incorrect delivery order alert on route": "Alerta de ordem de entrega incorreta na rota: {{ route }} zona: {{ zone }}", + "Ticket has been delivered out of order": "O ticket {{ticket}} {{{fullUrl}}} foi entregue fora de ordem." +} \ No newline at end of file diff --git a/modules/client/back/methods/defaulter/filter.js b/modules/client/back/methods/defaulter/filter.js index 5359ce4a7..cf8bd855a 100644 --- a/modules/client/back/methods/defaulter/filter.js +++ b/modules/client/back/methods/defaulter/filter.js @@ -94,7 +94,7 @@ module.exports = Self => { AND r1.started = r2.maxStarted ) r ON r.clientFk = c.id LEFT JOIN workerDepartment wd ON wd.workerFk = u.id - JOIN department dp ON dp.id = wd.departmentFk + LEFT JOIN department dp ON dp.id = wd.departmentFk WHERE d.created = ? AND d.amount > 0 diff --git a/modules/client/back/models/client-credit.json b/modules/client/back/models/client-credit.json index b92639b80..b57374dc3 100644 --- a/modules/client/back/models/client-credit.json +++ b/modules/client/back/models/client-credit.json @@ -19,6 +19,9 @@ }, "created": { "type": "date" + }, + "workerFk": { + "type": "number" } }, "relations": { @@ -33,4 +36,4 @@ "foreignKey": "workerFk" } } -} \ No newline at end of file +} diff --git a/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js b/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js index f66221409..78fce348e 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js +++ b/modules/invoiceOut/back/methods/invoiceOut/clientsToInvoice.js @@ -74,7 +74,8 @@ module.exports = Self => { AND t.companyFk = ? AND NOT t.isDeleted GROUP BY IF(c.hasToInvoiceByAddress, a.id, c.id) - HAVING SUM(t.totalWithVat) > 0;`; + HAVING SUM(t.totalWithVat) > 0 + ORDER BY c.id`; const addresses = await Self.rawSql(query, [ minShipped, diff --git a/modules/supplier/back/methods/supplier/newSupplier.js b/modules/supplier/back/methods/supplier/newSupplier.js index 3cca4195f..eb941ed69 100644 --- a/modules/supplier/back/methods/supplier/newSupplier.js +++ b/modules/supplier/back/methods/supplier/newSupplier.js @@ -28,6 +28,7 @@ module.exports = Self => { delete args.ctx; if (!args.name) throw new UserError('The social name cannot be empty'); + if (args.name !== args.name.toUpperCase()) throw new UserError('Social name should be uppercase'); const data = {...args, ...{nickname: args.name}}; const supplier = await models.Supplier.create(data, myOptions); diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js index ac2a7bc66..f99311c39 100644 --- a/modules/ticket/back/methods/ticket/saveSign.js +++ b/modules/ticket/back/methods/ticket/saveSign.js @@ -28,7 +28,6 @@ module.exports = Self => { verb: 'POST' } }); - Self.saveSign = async(ctx, tickets, location, signedTime, options) => { const models = Self.app.models; const myOptions = {userId: ctx.req.accessToken.userId}; @@ -111,6 +110,12 @@ module.exports = Self => { scope: { fields: ['id'] } + }, + { + relation: 'zone', + scope: { + fields: ['id', 'zoneFk,', 'name'] + } }] }, myOptions); @@ -151,6 +156,28 @@ module.exports = Self => { await Self.rawSql(`CALL vn.ticket_setState(?, ?)`, [ticketId, stateCode], myOptions); + if (stateCode == 'DELIVERED' && ticket.priority) { + const orderState = await models.State.findOne({ + where: {code: 'DELIVERED'}, + fields: ['id'] + }, myOptions); + + const ticketIncorrect = await Self.rawSql(` + SELECT t.id + FROM ticket t + JOIN ticketState ts ON ts.ticketFk = t.id + JOIN state s ON s.code = ts.code + WHERE t.routeFk = ? + AND s.\`order\` < ? + AND priority <(SELECT t.priority + FROM ticket t + WHERE t.id = ?)` + , [ticket.routeFk, orderState.id, ticket.id], myOptions); + + if (ticketIncorrect?.length > 0) + await sendMail(ctx, ticket.routeFk, ticket.id, ticket.zone().name); + } + if (ticket?.address()?.province()?.country()?.code != 'ES' && ticket.$cmrFk) { await models.Ticket.saveCmr(ctx, [ticketId], myOptions); externalTickets.push(ticketId); @@ -163,4 +190,25 @@ module.exports = Self => { } await models.Ticket.sendCmrEmail(ctx, externalTickets); }; + + async function sendMail(ctx, route, ticket, zoneName) { + const $t = ctx.req.__; + const url = await Self.app.models.Url.getUrl(); + const sendTo = 'repartos@verdnatura.es'; + const fullUrl = `${url}route/${route}/summary`; + const emailSubject = $t('Incorrect delivery order alert on route', { + route, + zone: zoneName + }); + const emailBody = $t('Ticket has been delivered out of order', { + ticket, + fullUrl + }); + + await Self.app.models.Mail.create({ + receiver: sendTo, + subject: emailSubject, + body: emailBody + }); + } }; diff --git a/modules/ticket/back/methods/ticket/specs/saveSign.spec.js b/modules/ticket/back/methods/ticket/specs/saveSign.spec.js index e93408973..3b426c2cf 100644 --- a/modules/ticket/back/methods/ticket/specs/saveSign.spec.js +++ b/modules/ticket/back/methods/ticket/specs/saveSign.spec.js @@ -1,12 +1,20 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('Ticket saveSign()', () => { let ctx = {req: { getLocale: () => { return 'en'; }, + __: () => {}, accessToken: {userId: 9} - }}; + } + }; + beforeEach(() => { + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: ctx + }); + }); it(`should throw error if the ticket's alert level is lower than 2`, async() => { const tx = await models.TicketDms.beginTransaction({}); @@ -51,4 +59,46 @@ describe('Ticket saveSign()', () => { expect(ticketTrackingAfter.name).toBe('Entregado en parte'); }); + + it('should send an email to notify that the delivery order is not correct', async() => { + const tx = await models.Ticket.beginTransaction({}); + const ticketFk = 8; + const priority = 5; + const stateFk = 10; + const stateTicketFk = 2; + const expeditionFk = 11; + const expeditionStateFK = 2; + + let mailCountBefore; + let mailCountAfter; + spyOn(models.Dms, 'uploadFile').and.returnValue([{id: 1}]); + + const options = {transaction: tx}; + const tickets = [ticketFk]; + + const expedition = await models.Expedition.findById(expeditionFk, null, options); + expedition.updateAttribute('stateTypeFk', expeditionStateFK, options); + + const ticket = await models.Ticket.findById(ticketFk, null, options); + ticket.updateAttribute('priority', priority, options); + + const filter = {where: { + ticketFk: ticketFk, + stateFk: stateTicketFk} + }; + try { + const ticketTracking = await models.TicketTracking.findOne(filter, options); + ticketTracking.updateAttribute('stateFk', stateFk, options); + mailCountBefore = await models.Mail.count(options); + await models.Ticket.saveSign(ctx, tickets, null, null, options); + mailCountAfter = await models.Mail.count(options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + + expect(mailCountAfter).toBeGreaterThan(mailCountBefore); + }); }); diff --git a/modules/travel/back/methods/travel/filter.js b/modules/travel/back/methods/travel/filter.js index 30c1a45fa..837e30b30 100644 --- a/modules/travel/back/methods/travel/filter.js +++ b/modules/travel/back/methods/travel/filter.js @@ -1,4 +1,3 @@ - const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; const buildFilter = require('vn-loopback/util/filter').buildFilter; const mergeFilters = require('vn-loopback/util/filter').mergeFilters; @@ -91,6 +90,11 @@ module.exports = Self => { arg: 'landed', type: 'date', description: 'The landed date' + }, + { + arg: 'awbFk', + type: 'number', + description: 'The awbFk id' } ], returns: { @@ -168,14 +172,17 @@ module.exports = Self => { t.totalEntries, t.isRaid, t.daysInForward, + t.awbFk, am.name agencyModeName, + a.code awbCode, win.name warehouseInName, wout.name warehouseOutName, cnt.code continent - FROM vn.travel t - JOIN vn.agencyMode am ON am.id = t.agencyModeFk - JOIN vn.warehouse win ON win.id = t.warehouseInFk - JOIN vn.warehouse wout ON wout.id = t.warehouseOutFk + FROM travel t + JOIN agencyMode am ON am.id = t.agencyModeFk + JOIN warehouse win ON win.id = t.warehouseInFk + JOIN warehouse wout ON wout.id = t.warehouseOutFk + LEFT JOIN awb a ON a.id = t.awbFk JOIN warehouse wo ON wo.id = t.warehouseOutFk JOIN country c ON c.id = wo.countryFk LEFT JOIN continent cnt ON cnt.id = c.continentFk) AS t` diff --git a/modules/zone/back/models/zone-event.json b/modules/zone/back/models/zone-event.json index 366bdec9d..cf5045a8c 100644 --- a/modules/zone/back/models/zone-event.json +++ b/modules/zone/back/models/zone-event.json @@ -42,6 +42,9 @@ "price": { "type": "number" }, + "priceOptimum": { + "type": "number" + }, "bonus": { "type": "number" }, diff --git a/modules/zone/back/models/zone.json b/modules/zone/back/models/zone.json index 141b28750..4f963568f 100644 --- a/modules/zone/back/models/zone.json +++ b/modules/zone/back/models/zone.json @@ -28,6 +28,9 @@ "price": { "type": "number" }, + "priceOptimum": { + "type": "number" + }, "bonus": { "type": "number" },