Compare commits
7 Commits
dev
...
7793_sortB
Author | SHA1 | Date |
---|---|---|
|
2479019634 | |
|
2aa10d059f | |
|
0bcf244433 | |
|
454593afb6 | |
|
5cce2cf567 | |
|
c2d8d7f03f | |
|
cec5d50f81 |
|
@ -33,52 +33,25 @@ module.exports = Self => {
|
|||
const emailUser =
|
||||
await Self.app.models.EmailUser.findById(userId, {fields: ['email']});
|
||||
|
||||
const tableStyle = 'width:100%; border-collapse: collapse; text-align: left;';
|
||||
const thStyle = 'padding: 8px; border: 1px solid #ddd; background-color: #f4f4f4;';
|
||||
const tdStyle = 'padding: 8px; border: 1px solid #ddd;';
|
||||
const tdBoldStyle = 'padding: 8px; border: 1px solid #ddd; font-weight: bold;';
|
||||
const subTdStyle = 'padding: 6px; border: 1px solid #ddd;';
|
||||
const subTdBoldStyle = 'padding: 6px; border: 1px solid #ddd; font-weight: bold;';
|
||||
|
||||
let html = `
|
||||
<h2>Motivo: ${reason}</h2>
|
||||
<h3>Usuario: ${userId} ${emailUser.email}</h3>
|
||||
<h3>Additional Data:</h3>
|
||||
<table style="${tableStyle}">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="${thStyle}">Clave</th><th style="${thStyle}">Valor</th></tr>
|
||||
</thead>
|
||||
<tbody>`;
|
||||
let html = `<h2>Motivo: ${reason}</h2>`;
|
||||
html += `<h3>Usuario: ${userId} ${emailUser.email}</h3>`;
|
||||
html += `<h3>Additional Data:</h3>`;
|
||||
html += '<ul>';
|
||||
for (const [key, val] of Object.entries(additionalData)) {
|
||||
if (key !== 'config') {
|
||||
html += `<tr>
|
||||
<td style="${tdBoldStyle}">${key}</td>
|
||||
<td style="${tdStyle}">${parse(val)}</td>
|
||||
</tr>`;
|
||||
} else {
|
||||
html += `<tr>
|
||||
<td style="${tdBoldStyle}">${key}</td>
|
||||
<td style="${tdStyle}">
|
||||
<table style="${tableStyle}">
|
||||
<tbody>`;
|
||||
for (const [confKey, confVal] of Object.entries(val)) {
|
||||
html += `<tr>
|
||||
<td style="${subTdBoldStyle}">${confKey}</td>
|
||||
<td style="${subTdStyle}">${parse(confVal)}</td>
|
||||
</tr>`;
|
||||
}
|
||||
html += `</tbody></table></td></tr>`;
|
||||
if (key !== 'config') html += `<li>${key}: ${parse(val)}</li>`;
|
||||
else {
|
||||
html += `<li>${key}:</li><ul style="list-style-type: square;">`;
|
||||
for (const [confKey, confVal] of Object.entries(val))
|
||||
html += `<li>${confKey}: ${parse(confVal)}</li>`;
|
||||
html += '</ul>';
|
||||
}
|
||||
}
|
||||
html += `</tbody></table>`;
|
||||
html += '</ul>';
|
||||
|
||||
const {message, path, name} = additionalData;
|
||||
const err = name && message ? `${name}: ${message}` : name || message || '';
|
||||
|
||||
await smtp.send({
|
||||
to: `${config.app.reportEmail}, ${emailUser.email}`,
|
||||
subject: `[Support-Salix] ${path.split('?')[0]} ${err}`,
|
||||
subject: `[Support-Salix] ${path} ${name}: ${message}`,
|
||||
html
|
||||
});
|
||||
};
|
||||
|
|
|
@ -54,8 +54,7 @@
|
|||
"type": "string"
|
||||
},
|
||||
"hasGrant": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
"type": "boolean"
|
||||
},
|
||||
"passExpired": {
|
||||
"type": "date"
|
||||
|
@ -169,7 +168,7 @@
|
|||
"emailVerified",
|
||||
"twoFactor"
|
||||
]
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2785,11 +2785,11 @@ INSERT INTO `vn`.`roadmapAddress` (`addressFk`)
|
|||
(3),
|
||||
(4);
|
||||
|
||||
INSERT INTO `vn`.`roadmap` (`id`, `name`, `tractorPlate`, `trailerPlate`, `phone`, `supplierFk`, `etd`, `observations`, `editorFk`, `price`, `driverName`)
|
||||
INSERT INTO `vn`.`roadmap` (`id`, `name`, `tractorPlate`, `trailerPlate`, `phone`, `supplierFk`, `etd`, `eta`, `observations`, `editorFk`, `price`, `driverName`)
|
||||
VALUES
|
||||
(1, 'val-algemesi', '1234-BCD', '9876-BCD', '111111111', 1, util.VN_NOW(), 'this is test observation', 1, 15, 'Batman'),
|
||||
(2, 'alg-valencia', '2345-CDF', '8765-BCD', '111111111', 1, util.VN_NOW(), 'test observation', 1, 20, 'Robin'),
|
||||
(3, 'alz-algemesi', '3456-DFG', '7654-BCD', '222222222', 2, DATE_ADD(util.VN_NOW(), INTERVAL 3 DAY), 'observations...', 2, 25, 'Driverman');
|
||||
(1, 'val-algemesi', '1234-BCD', '9876-BCD', '111111111', 1, util.VN_NOW(), DATE_ADD(util.VN_NOW(), INTERVAL 2 DAY), 'this is test observation', 1, 15, 'Batman'),
|
||||
(2, 'alg-valencia', '2345-CDF', '8765-BCD', '111111111', 1, util.VN_NOW(), DATE_ADD(util.VN_NOW(), INTERVAL 5 DAY), 'test observation', 1, 20, 'Robin'),
|
||||
(3, 'alz-algemesi', '3456-DFG', '7654-BCD', '222222222', 2, DATE_ADD(util.VN_NOW(), INTERVAL 3 DAY), DATE_ADD(util.VN_NOW(), INTERVAL 6 DAY), 'observations...', 2, 25, 'Driverman');
|
||||
|
||||
INSERT INTO `vn`.`roadmapStop` (`id`, `roadmapFk`, `roadmapAddressFk`, `eta`, `description`, `editorFk`)
|
||||
VALUES
|
||||
|
|
|
@ -160,11 +160,9 @@ BEGIN
|
|||
OR (NOT s.isPreparable AND NOT s.isPrintable)
|
||||
OR pb.collectionH IS NOT NULL
|
||||
OR pb.collectionV IS NOT NULL
|
||||
OR pb.collectionA IS NOT NULL
|
||||
OR pb.collectionN IS NOT NULL
|
||||
OR (NOT pb.H AND pb.V + pb.A > 0 AND vItemPackingTypeFk = 'H')
|
||||
OR (NOT pb.H AND pb.V > 0 AND vItemPackingTypeFk = 'H')
|
||||
OR (NOT pb.V AND vItemPackingTypeFk = 'V')
|
||||
OR (NOT pb.A AND vItemPackingTypeFk = 'A')
|
||||
OR (pc.isPreviousPreparationRequired AND pb.previousWithoutParking)
|
||||
OR LENGTH(pb.problem)
|
||||
OR pb.lines > vLinesLimit
|
||||
|
|
|
@ -30,7 +30,7 @@ BEGIN
|
|||
WITH entriesIn AS (
|
||||
SELECT 'entry' originType,
|
||||
e.id originId,
|
||||
IFNULL(tr.availabled, tr.landed) shipped,
|
||||
tr.landed shipped,
|
||||
b.quantity `in`,
|
||||
NULL `out`,
|
||||
st.alertLevel ,
|
||||
|
@ -54,7 +54,7 @@ BEGIN
|
|||
OR (util.VN_CURDATE() AND tr.isReceived),
|
||||
'DELIVERED',
|
||||
'FREE')
|
||||
WHERE IFNULL(tr.availabled, tr.landed) >= vDateInventory
|
||||
WHERE tr.landed >= vDateInventory
|
||||
AND tr.warehouseInFk = vWarehouseFk
|
||||
AND (s.id <> vSupplierInventoryFk OR vDated IS NULL)
|
||||
AND b.itemFk = vItemFk
|
||||
|
@ -99,7 +99,7 @@ BEGIN
|
|||
),
|
||||
sales AS (
|
||||
WITH itemSales AS (
|
||||
SELECT DATE(t.shipped) + INTERVAL HOUR(z.`hour`) HOUR shipped,
|
||||
SELECT DATE(t.shipped) shipped,
|
||||
s.quantity,
|
||||
st2.alertLevel,
|
||||
st2.name,
|
||||
|
@ -114,7 +114,6 @@ BEGIN
|
|||
cb.claimFk
|
||||
FROM vn.sale s
|
||||
JOIN vn.ticket t ON t.id = s.ticketFk
|
||||
JOIN vn.`zone` z ON z.id = t.zoneFk
|
||||
LEFT JOIN vn.ticketState ts ON ts.ticketFk = t.id
|
||||
LEFT JOIN vn.state st ON st.code = ts.code
|
||||
JOIN vn.client c ON c.id = t.clientFk
|
||||
|
@ -190,15 +189,14 @@ BEGIN
|
|||
SELECT * FROM sales
|
||||
UNION ALL
|
||||
SELECT * FROM orders
|
||||
ORDER BY DATE(shipped),
|
||||
ORDER BY shipped,
|
||||
(inventorySupplierFk = entityId) DESC,
|
||||
alertLevel DESC,
|
||||
isTicket,
|
||||
`order` DESC,
|
||||
isPicked DESC,
|
||||
`in` DESC,
|
||||
`out` DESC,
|
||||
shipped;
|
||||
`out` DESC;
|
||||
|
||||
IF vDated IS NULL THEN
|
||||
SET @a := 0;
|
||||
|
@ -207,7 +205,7 @@ BEGIN
|
|||
|
||||
SELECT t.originType,
|
||||
t.originId,
|
||||
@shipped:= t.shipped,
|
||||
DATE(@shipped:= t.shipped) shipped,
|
||||
t.alertLevel,
|
||||
t.stateName,
|
||||
t.reference,
|
||||
|
|
|
@ -91,7 +91,6 @@ proc: BEGIN
|
|||
pk.code parking,
|
||||
0 H,
|
||||
0 V,
|
||||
0 A,
|
||||
0 N,
|
||||
st.isOk,
|
||||
ag.isOwn,
|
||||
|
@ -139,7 +138,6 @@ proc: BEGIN
|
|||
CHANGE COLUMN `problem` `problem` VARCHAR(255),
|
||||
ADD COLUMN `collectionH` INT,
|
||||
ADD COLUMN `collectionV` INT,
|
||||
ADD COLUMN `collectionA` INT,
|
||||
ADD COLUMN `collectionN` INT;
|
||||
|
||||
-- Clientes Nuevos o Recuperados
|
||||
|
@ -180,14 +178,12 @@ proc: BEGIN
|
|||
ENGINE = MEMORY
|
||||
SELECT ticketFk,
|
||||
SUM(sub.H) H,
|
||||
SUM(sub.V) V,
|
||||
SUM(sub.A) A,
|
||||
SUM(sub.V) V,
|
||||
SUM(sub.N) N
|
||||
FROM (
|
||||
SELECT t.ticketFk,
|
||||
SUM(i.itemPackingTypeFk = 'H') H,
|
||||
SUM(i.itemPackingTypeFk = 'V') V,
|
||||
SUM(i.itemPackingTypeFk = 'A') A,
|
||||
SUM(i.itemPackingTypeFk IS NULL) N
|
||||
FROM tmp.productionTicket t
|
||||
JOIN sale s ON s.ticketFk = t.ticketFk
|
||||
|
@ -200,7 +196,6 @@ proc: BEGIN
|
|||
JOIN tItemPackingType ti ON ti.ticketFk = pb.ticketFk
|
||||
SET pb.H = ti.H,
|
||||
pb.V = ti.V,
|
||||
pb.A = ti.A,
|
||||
pb.N = ti.N;
|
||||
|
||||
-- Colecciones segun tipo de encajado
|
||||
|
@ -208,7 +203,6 @@ proc: BEGIN
|
|||
JOIN ticketCollection tc ON pb.ticketFk = tc.ticketFk
|
||||
SET pb.collectionH = IF(pb.H, tc.collectionFk, NULL),
|
||||
pb.collectionV = IF(pb.V, tc.collectionFk, NULL),
|
||||
pb.collectionA = IF(pb.A, tc.collectionFk, NULL),
|
||||
pb.collectionN = IF(pb.N, tc.collectionFk, NULL);
|
||||
|
||||
-- Previa pendiente
|
||||
|
|
|
@ -9,12 +9,15 @@ BEGIN
|
|||
*/
|
||||
DECLARE vDone BOOL;
|
||||
DECLARE vClientFk INT;
|
||||
DECLARE vCurTicketFk INT;
|
||||
DECLARE vCurTicketFk INT;
|
||||
DECLARE vIsTaxDataChecked BOOL;
|
||||
DECLARE vCompanyFk INT;
|
||||
DECLARE vShipped DATE;
|
||||
DECLARE vNewInvoiceId INT;
|
||||
DECLARE vHasDailyInvoice BOOL;
|
||||
DECLARE vWithPackage BOOL;
|
||||
DECLARE vHasToInvoice BOOL;
|
||||
DECLARE vStateCode VARCHAR(45);
|
||||
DECLARE vHasToInvoice BOOL;
|
||||
DECLARE vSerial VARCHAR(2);
|
||||
|
||||
DECLARE cur CURSOR FOR
|
||||
SELECT ticketFk FROM tmp.ticket_close;
|
||||
|
@ -35,11 +38,18 @@ BEGIN
|
|||
LEAVE proc;
|
||||
END IF;
|
||||
|
||||
SELECT c.id,
|
||||
SELECT
|
||||
c.id,
|
||||
c.isTaxDataChecked,
|
||||
t.companyFk,
|
||||
t.shipped,
|
||||
c.hasDailyInvoice,
|
||||
w.isManaged,
|
||||
c.hasToInvoice
|
||||
INTO vClientFk,
|
||||
vIsTaxDataChecked,
|
||||
vCompanyFk,
|
||||
vShipped,
|
||||
vHasDailyInvoice,
|
||||
vWithPackage,
|
||||
vHasToInvoice
|
||||
|
@ -49,7 +59,7 @@ BEGIN
|
|||
WHERE t.id = vCurTicketFk;
|
||||
|
||||
INSERT INTO ticketPackaging (ticketFk, packagingFk, quantity)
|
||||
SELECT vCurTicketFk, p.id, COUNT(*)
|
||||
(SELECT vCurTicketFk, p.id, COUNT(*)
|
||||
FROM expedition e
|
||||
JOIN packaging p ON p.id = e.packagingFk
|
||||
JOIN ticket t ON t.id = e.ticketFk
|
||||
|
@ -58,35 +68,39 @@ BEGIN
|
|||
WHERE e.ticketFk = vCurTicketFk AND p.isPackageReturnable
|
||||
AND vWithPackage
|
||||
AND NOT dm.`code`= 'PICKUP'
|
||||
GROUP BY p.itemFk;
|
||||
GROUP BY p.itemFk);
|
||||
|
||||
-- No retornables o no catalogados
|
||||
INSERT INTO sale (
|
||||
itemFk,
|
||||
ticketFk,
|
||||
concept,
|
||||
quantity,
|
||||
price, isPriceFixed
|
||||
)SELECT e.freightItemFk,
|
||||
vCurTicketFk,
|
||||
i.name,
|
||||
COUNT(*) amount,
|
||||
getSpecialPrice(e.freightItemFk, vClientFk),
|
||||
TRUE
|
||||
INSERT INTO sale (itemFk, ticketFk, concept, quantity, price, isPriceFixed)
|
||||
(SELECT e.freightItemFk, vCurTicketFk, i.name, COUNT(*) AS amount, getSpecialPrice(e.freightItemFk, vClientFk), 1
|
||||
FROM expedition e
|
||||
JOIN item i ON i.id = e.freightItemFk
|
||||
LEFT JOIN packaging p ON p.itemFk = i.id
|
||||
WHERE e.ticketFk = vCurTicketFk
|
||||
AND (p.isPackageReturnable = 0 OR p.isPackageReturnable IS NULL)
|
||||
WHERE e.ticketFk = vCurTicketFk AND IFNULL(p.isPackageReturnable, 0) = 0
|
||||
AND getSpecialPrice(e.freightItemFk, vClientFk) > 0
|
||||
GROUP BY e.freightItemFk;
|
||||
GROUP BY e.freightItemFk);
|
||||
|
||||
IF vHasDailyInvoice AND vHasToInvoice THEN
|
||||
SET vStateCode = 'DELIVERED';
|
||||
IF(vHasDailyInvoice) AND vHasToInvoice THEN
|
||||
SELECT invoiceSerial(vClientFk, vCompanyFk, 'quick') INTO vSerial;
|
||||
IF vSerial IS NULL THEN
|
||||
CALL util.throw('Cannot booking without a serial');
|
||||
END IF;
|
||||
|
||||
CALL ticket_setState(vCurTicketFk, 'DELIVERED');
|
||||
|
||||
IF vIsTaxDataChecked THEN
|
||||
CALL invoiceOut_newFromClient(
|
||||
vClientFk,
|
||||
vSerial,
|
||||
vShipped,
|
||||
vCompanyFk,
|
||||
NULL,
|
||||
NULL,
|
||||
vNewInvoiceId);
|
||||
END IF;
|
||||
ELSE
|
||||
SELECT getAlert3State(vCurTicketFk) INTO vStateCode;
|
||||
CALL ticket_setState(vCurTicketFk, (SELECT vn.getAlert3State(vCurTicketFk)));
|
||||
END IF;
|
||||
CALL ticket_setState(vCurTicketFk, vStateCode);
|
||||
END LOOP;
|
||||
|
||||
CLOSE cur;
|
||||
|
|
|
@ -3,25 +3,21 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`ticket_setState`(
|
|||
vSelf INT,
|
||||
vStateCode VARCHAR(255) COLLATE utf8_general_ci
|
||||
)
|
||||
proc:BEGIN
|
||||
BEGIN
|
||||
/**
|
||||
* Modifica el estado de un ticket si se cumplen las condiciones necesarias.
|
||||
*
|
||||
* @param vSelf el id del ticket
|
||||
* @param vStateCode estado a modificar del ticket
|
||||
*/
|
||||
DECLARE vTicketAlertLevel INT;
|
||||
DECLARE vTicketStateCode VARCHAR(255) COLLATE utf8_general_ci;
|
||||
DECLARE vticketAlertLevel INT;
|
||||
DECLARE vTicketStateCode VARCHAR(255);
|
||||
DECLARE vCanChangeState BOOL;
|
||||
DECLARE vPackedAlertLevel INT;
|
||||
DECLARE vZoneFk INT;
|
||||
DECLARE vOldWorkerFk INT;
|
||||
DECLARE vNewWorkerFk INT;
|
||||
|
||||
SET vNewWorkerFk = account.myUser_getId();
|
||||
|
||||
SELECT s.alertLevel, s.`code`, t.zoneFk, tt.userFk
|
||||
INTO vTicketAlertLevel, vTicketStateCode, vZoneFk, vOldWorkerFk
|
||||
SELECT s.alertLevel, s.`code`, t.zoneFk
|
||||
INTO vticketAlertLevel, vTicketStateCode, vZoneFk
|
||||
FROM state s
|
||||
JOIN ticketTracking tt ON tt.stateFk = s.id
|
||||
JOIN ticket t ON t.id = tt.ticketFk
|
||||
|
@ -37,27 +33,24 @@ proc:BEGIN
|
|||
|
||||
SET vCanChangeState = ((
|
||||
vStateCode <> 'ON_CHECKING' AND vStateCode <> 'CHECKED') OR
|
||||
vTicketAlertLevel < vPackedAlertLevel
|
||||
) AND NOT (
|
||||
vticketAlertLevel < vPackedAlertLevel
|
||||
)AND NOT (
|
||||
vTicketStateCode IN ('CHECKED', 'CHECKING')
|
||||
AND vStateCode IN ('PREPARED', 'ON_PREPARATION')
|
||||
);
|
||||
|
||||
IF vCanChangeState THEN
|
||||
INSERT INTO ticketTracking (stateFk, ticketFk, userFk)
|
||||
SELECT id, vSelf, account.myUser_getId()
|
||||
FROM state
|
||||
WHERE `code` = vStateCode COLLATE utf8_unicode_ci;
|
||||
|
||||
IF vStateCode = 'PACKED' THEN
|
||||
CALL ticket_doCmr(vSelf);
|
||||
END IF;
|
||||
|
||||
IF vStateCode = vTicketStateCode AND vOldWorkerFk = vNewWorkerFk THEN
|
||||
LEAVE proc;
|
||||
END IF;
|
||||
|
||||
INSERT INTO ticketTracking (stateFk, ticketFk, userFk)
|
||||
SELECT id, vSelf, vNewWorkerFk
|
||||
FROM state
|
||||
WHERE `code` = vStateCode COLLATE utf8_unicode_ci;
|
||||
ELSE
|
||||
CALL util.throw('INCORRECT_TICKET_STATE');
|
||||
END IF;
|
||||
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`roadmapStop_beforeDelete`
|
||||
BEFORE DELETE ON `roadmapStop`
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
DECLARE vMaxEta DATETIME;
|
||||
DECLARE vRoadmapEta DATETIME;
|
||||
|
||||
IF OLD.roadmapFk IS NOT NULL THEN
|
||||
SELECT MAX(eta) INTO vMaxEta
|
||||
FROM roadmapStop
|
||||
WHERE roadmapFk = OLD.roadmapFk
|
||||
AND id <> OLD.id;
|
||||
|
||||
SELECT eta INTO vRoadmapEta
|
||||
FROM roadmap
|
||||
WHERE id = OLD.roadmapFk;
|
||||
|
||||
IF vMaxEta <> vRoadmapEta OR vMaxEta IS NULL THEN
|
||||
UPDATE roadmap
|
||||
SET eta = vMaxEta
|
||||
WHERE id = OLD.roadmapFk;
|
||||
END IF;
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -3,6 +3,8 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`roadmapStop_beforeInser
|
|||
BEFORE INSERT ON `roadmapStop`
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
DECLARE vRoadmapEta DATETIME;
|
||||
|
||||
SET NEW.editorFk = account.myUser_getId();
|
||||
|
||||
IF NEW.description IS NOT NULL THEN
|
||||
|
@ -14,5 +16,17 @@ BEGIN
|
|||
CALL util.throw('Departure time can not be after arrival time');
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
IF NEW.roadmapFk IS NOT NULL AND NEW.eta IS NOT NULL THEN
|
||||
SELECT eta INTO vRoadmapEta
|
||||
FROM roadmap
|
||||
WHERE id = NEW.roadmapFk;
|
||||
|
||||
IF vRoadmapEta < NEW.eta OR vRoadmapEta IS NULL THEN
|
||||
UPDATE roadmap
|
||||
SET eta = NEW.eta
|
||||
WHERE id = NEW.roadmapFk;
|
||||
END IF;
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -3,17 +3,40 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`roadmapStop_beforeUpdat
|
|||
BEFORE UPDATE ON `roadmapStop`
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
DECLARE vMaxEta DATETIME;
|
||||
DECLARE vCurrentEta DATETIME;
|
||||
|
||||
SET NEW.editorFk = account.myUser_getId();
|
||||
|
||||
IF NOT (NEW.description <=> OLD.description) THEN
|
||||
SET NEW.description = UCASE(NEW.description);
|
||||
END IF;
|
||||
|
||||
IF NOT (NEW.roadmapFk <=> OLD.roadmapFk) OR NOT (NEW.eta <=> OLD.eta) THEN
|
||||
IF (NOT (NEW.roadmapFk <=> OLD.roadmapFk) AND NEW.roadmapFk IS NOT NULL)
|
||||
OR (NOT (NEW.eta <=> OLD.eta)) THEN
|
||||
|
||||
IF NEW.eta < (SELECT etd FROM roadmap WHERE id = NEW.roadmapFk) THEN
|
||||
CALL util.throw('Departure time can not be after arrival time');
|
||||
END IF;
|
||||
|
||||
SELECT MAX(eta) INTO vMaxEta
|
||||
FROM roadmapStop
|
||||
WHERE roadmapFk = NEW.roadmapFk
|
||||
AND id <> OLD.id;
|
||||
|
||||
IF vMaxEta < NEW.eta OR vMaxEta IS NULL THEN
|
||||
SET vMaxEta = NEW.eta;
|
||||
END IF;
|
||||
|
||||
SELECT eta INTO vCurrentEta
|
||||
FROM roadmap
|
||||
WHERE id = NEW.roadmapFk;
|
||||
|
||||
IF (vMaxEta <> vCurrentEta OR vMaxEta IS NULL) OR vMaxEta IS NOT NULL THEN
|
||||
UPDATE roadmap
|
||||
SET eta = vMaxEta
|
||||
WHERE id = NEW.roadmapFk;
|
||||
END IF;
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
DELIMITER ;
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`roadmap_afterUpdate`
|
||||
AFTER UPDATE ON `roadmap`
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
DECLARE vSeconds INT;
|
||||
|
||||
IF NOT (NEW.etd <=> OLD.etd) THEN
|
||||
SET vSeconds = TIME_TO_SEC(TIMEDIFF(NEW.etd, OLD.etd));
|
||||
IF vSeconds IS NOT NULL AND vSeconds <> 0 THEN
|
||||
UPDATE roadmapStop
|
||||
SET eta = eta + INTERVAL vSeconds SECOND
|
||||
WHERE roadmapFk = NEW.id;
|
||||
END IF;
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -3,8 +3,6 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`roadmap_beforeUpdate`
|
|||
BEFORE UPDATE ON `roadmap`
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
DECLARE vSeconds INT;
|
||||
|
||||
SET NEW.editorFk = account.myUser_getId();
|
||||
|
||||
IF NOT (NEW.name <=> OLD.name) THEN
|
||||
|
@ -39,15 +37,5 @@ BEGIN
|
|||
FROM worker w
|
||||
WHERE w.id = NEW.driverChangeFk);
|
||||
END IF;
|
||||
|
||||
IF NOT (NEW.etd <=> OLD.etd) THEN
|
||||
SET vSeconds = TIME_TO_SEC(TIMEDIFF(NEW.etd, OLD.etd));
|
||||
|
||||
IF vSeconds <> 0 THEN
|
||||
UPDATE roadmapStop
|
||||
SET eta = eta + INTERVAL vSeconds SECOND
|
||||
WHERE roadmapFk = NEW.id;
|
||||
END IF;
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -1,8 +0,0 @@
|
|||
CREATE OR REPLACE DEFINER=`vn`@`localhost`
|
||||
SQL SECURITY DEFINER
|
||||
VIEW `vn`.`roadmapEta`
|
||||
AS SELECT `roadmapFk` AS id,
|
||||
MAX(`eta`) AS `eta`
|
||||
FROM `vn`.`roadmapStop`
|
||||
WHERE `roadmapFk` IS NOT NULL
|
||||
GROUP BY `roadmapFk`;
|
|
@ -1,7 +1,6 @@
|
|||
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
|
||||
VALUES ('Entry','getBuyList','READ','ALLOW','ROLE','buyer'),
|
||||
('Entry','getBuyUltimate','READ','ALLOW','ROLE','buyer'),
|
||||
('Entry','search','READ','ALLOW','ROLE','buyer'),
|
||||
('Entry','create','WRITE','ALLOW','ROLE','buyer'),
|
||||
('Entry','cloneEntry','WRITE','ALLOW','ROLE','buyer'),
|
||||
('Entry','deleteEntry','WRITE','ALLOW','ROLE','buyer'),
|
||||
|
@ -12,79 +11,4 @@ INSERT INTO salix.ACL (model,property,accessType,permission,principalType,princi
|
|||
ALTER TABLE vn.ink ADD IF NOT EXISTS hexJson TEXT NOT NULL;
|
||||
|
||||
UPDATE vn.ink
|
||||
SET hexJson = CONCAT('{"value": ["',hex,'"]}');
|
||||
|
||||
UPDATE vn.ink
|
||||
SET hexJson = CASE `name`
|
||||
WHEN 'Blanco/Naranja' THEN '{"value": ["FFFFFF", "FFA500"]}'
|
||||
WHEN 'Sin especificar' THEN '{"value": ["808080"]}'
|
||||
WHEN '2 Colores' THEN '{"value": ["000000", "FFFFFF"]}'
|
||||
WHEN 'Amarillo/Marrón' THEN '{"value": ["FFFF00", "8B4513"]}'
|
||||
WHEN 'Amarillo/Naranja' THEN '{"value": ["FFFF00", "FFA500"]}'
|
||||
WHEN 'Rosa/Blanco/Amarillo' THEN '{"value": ["FFC0CB", "FFFFFF", "FFFF00"]}'
|
||||
WHEN 'Rosa/Amarillo' THEN '{"value": ["FFC0CB", "FFFF00"]}'
|
||||
WHEN 'Antracita' THEN '{"value": ["2F2F2F"]}'
|
||||
WHEN 'Azul/Amarillo' THEN '{"value": ["0000FF", "FFFF00"]}'
|
||||
WHEN 'Azul Claro' THEN '{"value": ["ADD8E6"]}'
|
||||
WHEN 'Azul/Marron' THEN '{"value": ["0000FF", "8B4513"]}'
|
||||
WHEN 'Azul/Verde' THEN '{"value": ["0000FF", "008000"]}'
|
||||
WHEN 'Blanco/Amarillo' THEN '{"value": ["FFFFFF", "FFFF00"]}'
|
||||
WHEN 'Blaugrana' THEN '{"value": ["A50044", "004D98"]}'
|
||||
WHEN 'Blanco/Negro' THEN '{"value": ["FFFFFF", "000000"]}'
|
||||
WHEN 'Blanco/Verde' THEN '{"value": ["FFFFFF", "008000"]}'
|
||||
WHEN 'Blanco/Azul' THEN '{"value": ["FFFFFF", "0000FF"]}'
|
||||
WHEN 'Blanco/Rosa' THEN '{"value": ["FFFFFF", "FFC0CB"]}'
|
||||
WHEN 'Cognac/Verde' THEN '{"value": ["9A463D", "008000"]}'
|
||||
WHEN 'Champagne/Verde' THEN '{"value": ["F7E7CE", "008000"]}'
|
||||
WHEN 'Camuflaje' THEN '{"value": ["6B8E23", "556B2F", "8B4513"]}'
|
||||
WHEN 'Crema/Rosa' THEN '{"value": ["FFFDD0", "FFC0CB"]}'
|
||||
WHEN 'Fucsia/Amarillo' THEN '{"value": ["FF00FF", "FFFF00"]}'
|
||||
WHEN 'Fucsia/Blanco' THEN '{"value": ["FF00FF", "FFFFFF"]}'
|
||||
WHEN 'Fucsia/Crema' THEN '{"value": ["FF00FF", "FFFDD0"]}'
|
||||
WHEN 'Fucsia/Rosa' THEN '{"value": ["FF00FF", "FFC0CB"]}'
|
||||
WHEN 'Fucsia/Verde' THEN '{"value": ["FF00FF", "008000"]}'
|
||||
WHEN 'Granate/Blanco' THEN '{"value": ["800000", "FFFFFF"]}'
|
||||
WHEN 'Gris Lila' THEN '{"value": ["808080", "C8A2C8"]}'
|
||||
WHEN 'Lavanda/Amarillo' THEN '{"value": ["E6E6FA", "FFFF00"]}'
|
||||
WHEN 'Lavanda/Gris' THEN '{"value": ["E6E6FA", "808080"]}'
|
||||
WHEN 'Lividum' THEN '{"value": ["702963"]}'
|
||||
WHEN 'Morado/Amarillo' THEN '{"value": ["800080", "FFFF00"]}'
|
||||
WHEN 'Marrón/Blanco' THEN '{"value": ["8B4513", "FFFFFF"]}'
|
||||
WHEN 'Marron/Gris' THEN '{"value": ["8B4513", "808080"]}'
|
||||
WHEN 'Marron/Negro' THEN '{"value": ["8B4513", "000000"]}'
|
||||
WHEN 'Marrón/Verde' THEN '{"value": ["8B4513", "008000"]}'
|
||||
WHEN 'Matizado' THEN '{"value": ["D3D3D3", "808080", "FFFFFF"]}'
|
||||
WHEN 'Mixto' THEN '{"value": ["FF0000", "0000FF", "008000", "FFFF00"]}'
|
||||
WHEN 'Marrón Oscuro' THEN '{"value": ["654321"]}'
|
||||
WHEN 'Naranja/Marron' THEN '{"value": ["FFA500", "8B4513"]}'
|
||||
WHEN 'Naranja/Rosa' THEN '{"value": ["FFA500", "FFC0CB"]}'
|
||||
WHEN 'Ocre/Burgundi' THEN '{"value": ["CC7722", "800020"]}'
|
||||
WHEN 'Oro/Plata' THEN '{"value": ["FFD700", "C0C0C0"]}'
|
||||
WHEN 'Oro/Negro' THEN '{"value": ["FFD700", "000000"]}'
|
||||
WHEN 'Oro/Verde' THEN '{"value": ["FFD700", "008000"]}'
|
||||
WHEN 'Purpura/Blanco' THEN '{"value": ["800080", "FFFFFF"]}'
|
||||
WHEN 'Purpura/Rosa' THEN '{"value": ["800080", "FFC0CB"]}'
|
||||
WHEN 'Pastel' THEN '{"value": ["FFB6C1", "87CEFA", "98FB98"]}'
|
||||
WHEN 'Plata' THEN '{"value": ["C0C0C0"]}'
|
||||
WHEN 'Plata/Verde' THEN '{"value": ["C0C0C0", "008000"]}'
|
||||
WHEN 'Rojo/Amarillo' THEN '{"value": ["FF0000", "FFFF00"]}'
|
||||
WHEN 'Rojo/Blanco' THEN '{"value": ["FF0000", "FFFFFF"]}'
|
||||
WHEN 'Rojo/Naranja' THEN '{"value": ["FF0000", "FFA500"]}'
|
||||
WHEN 'Rojo/Oro' THEN '{"value": ["FF0000", "FFD700"]}'
|
||||
WHEN 'Rojo/Verde' THEN '{"value": ["FF0000", "008000"]}'
|
||||
WHEN 'Rosa/Lila' THEN '{"value": ["FFC0CB", "C8A2C8"]}'
|
||||
WHEN 'Rosa/Naranja' THEN '{"value": ["FFC0CB", "FFA500"]}'
|
||||
WHEN 'Rojo/Rosa' THEN '{"value": ["FF0000", "FFC0CB"]}'
|
||||
WHEN 'Rosa empolvado' THEN '{"value": ["E6B8AF"]}'
|
||||
WHEN 'Rosa/Verde' THEN '{"value": ["FFC0CB", "008000"]}'
|
||||
WHEN 'Topo/Blanco' THEN '{"value": ["8B8589", "FFFFFF"]}'
|
||||
WHEN 'Topo' THEN '{"value": ["8B8589"]}'
|
||||
WHEN 'Transparente' THEN '{"value": ["00000000"]}'
|
||||
WHEN 'Verde/Amarillo' THEN '{"value": ["008000", "FFFF00"]}'
|
||||
WHEN 'Verde/Negro' THEN '{"value": ["008000", "000000"]}'
|
||||
WHEN 'Variado' THEN '{"value": ["FF0000", "0000FF", "008000", "FFFF00", "FFA500"]}'
|
||||
WHEN 'Verde Claro/Morado' THEN '{"value": ["90EE90", "800080"]}'
|
||||
WHEN 'Verde/Lila' THEN '{"value": ["008000", "C8A2C8"]}'
|
||||
WHEN 'Vaquero Neon' THEN '{"value": ["1560BD", "FFFF00"]}'
|
||||
ELSE hexJson
|
||||
END;
|
||||
SET hexJson = CONCAT('{"value": ["',hex,'"]}')
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
ALTER TABLE vn.roadmap
|
||||
MODIFY COLUMN dollyPlate varchar(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci DEFAULT NULL NULL COMMENT
|
||||
'Vehículo sin motor diseñado para conectarse a una unidad tractora, un camión o un vehículo tractor con fuerte potencia de tracción';
|
|
@ -1,3 +0,0 @@
|
|||
ALTER TABLE vn.volumeConfig ADD COLUMN id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST;
|
||||
|
||||
GRANT UPDATE (palletM3) ON vn.volumeConfig TO deliveryBoss;
|
|
@ -1,3 +0,0 @@
|
|||
ALTER TABLE vn.vehicle
|
||||
MODIFY COLUMN typeFk enum('car','van','truck','trailer','tug','dolly','trailerLink')
|
||||
CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci DEFAULT 'van' NOT NULL;
|
|
@ -1 +0,0 @@
|
|||
ALTER TABLE vn.roadmap DROP COLUMN eta;
|
|
@ -1,8 +0,0 @@
|
|||
UPDATE vn.expedition e
|
||||
JOIN (
|
||||
SELECT id
|
||||
FROM vn.expedition
|
||||
WHERE hostFk COLLATE utf8mb3_unicode_ci NOT IN
|
||||
(SELECT code COLLATE utf8mb3_unicode_ci FROM vn.host WHERE code IS NOT NULL)
|
||||
) s ON e.id = s.id
|
||||
SET e.hostFk = 'pc336';
|
|
@ -1,9 +0,0 @@
|
|||
ALTER TABLE vn.expedition
|
||||
MODIFY COLUMN hostFk VARCHAR(30) COLLATE utf8mb3_general_ci;
|
||||
|
||||
ALTER TABLE vn.expedition
|
||||
ADD CONSTRAINT fk_expedition_host_code
|
||||
FOREIGN KEY (hostFk)
|
||||
REFERENCES host(code)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE;
|
|
@ -2,6 +2,7 @@
|
|||
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||
const UserError = require('vn-loopback/util/user-error');
|
||||
const utils = require('loopback/lib/utils');
|
||||
const {orderBySearch, findLikeKeys} = require('../../util/orderBySearch');
|
||||
|
||||
module.exports = function(Self) {
|
||||
Self.ParameterizedSQL = ParameterizedSQL;
|
||||
|
@ -45,6 +46,16 @@ module.exports = function(Self) {
|
|||
const {result} = ctx;
|
||||
const length = Array.isArray(result) ? result.length : result ? 1 : 0;
|
||||
if (length >= this.app.orm.selectLimit) throw new UserError('Too many records');
|
||||
const likeKeys = findLikeKeys(ctx.args.filter?.where) ?? [];
|
||||
if (!likeKeys.length) return result;
|
||||
let property = likeKeys[0].property;
|
||||
let value = likeKeys[0].value;
|
||||
if (likeKeys.length > 1) {
|
||||
const firstOrderBy = likeKeys.find(({prop}) => ctx.args.order[0] === prop);
|
||||
if (firstOrderBy) property = firstOrderBy.property;
|
||||
}
|
||||
|
||||
return orderBySearch(result, property, value);
|
||||
});
|
||||
|
||||
// Register field ACL validation
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
exports.orderBySearch = function(results, property, searchValue) {
|
||||
return results.sort((a, b) => {
|
||||
const aStartsWithSearch = a[property].startsWith(searchValue);
|
||||
const bStartsWithSearch = b[property].startsWith(searchValue);
|
||||
|
||||
if (aStartsWithSearch && !bStartsWithSearch) return -1;
|
||||
if (!aStartsWithSearch && bStartsWithSearch) return 1;
|
||||
|
||||
return a[property].localeCompare(b[property]);
|
||||
});
|
||||
};
|
||||
exports.findLikeKeys = function(where) {
|
||||
const likeKeys = [];
|
||||
|
||||
function searchLike(obj, parentKey = '') {
|
||||
if (typeof obj !== 'object' || obj === null) return;
|
||||
|
||||
for (const key in obj) {
|
||||
if (key === 'like')
|
||||
likeKeys.push({property: parentKey, value: obj[key].replace(/%/g, '')});
|
||||
else if (typeof obj[key] === 'object')
|
||||
searchLike(obj[key], key);
|
||||
}
|
||||
}
|
||||
|
||||
searchLike(where);
|
||||
return likeKeys;
|
||||
};
|
|
@ -1,5 +1,5 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('getSimilar', {
|
||||
Self.remoteMethod('getSimilar', {
|
||||
description: 'Returns list of items with similar item requested',
|
||||
accessType: 'READ',
|
||||
accepts: [
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('search', {
|
||||
description: 'Returns an array of search results for a specified item',
|
||||
accepts: [{
|
||||
arg: 'filter',
|
||||
type: 'object',
|
||||
description: 'Filter to define conditions and paginate the data.',
|
||||
required: true
|
||||
}],
|
||||
returns: {
|
||||
type: ['object'],
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/search`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.search = async(ctx, filter) => {
|
||||
const conn = Self.dataSource.connector;
|
||||
|
||||
const stmt = new ParameterizedSQL(`
|
||||
SELECT *
|
||||
FROM(
|
||||
SELECT i.id, i.name, i.size, p.name producerName
|
||||
FROM item i
|
||||
LEFT JOIN producer p ON p.id = i.producerFk
|
||||
) sub
|
||||
`);
|
||||
|
||||
stmt.merge(conn.makeSuffix(filter));
|
||||
|
||||
return conn.executeStmt(stmt);
|
||||
};
|
||||
};
|
|
@ -18,7 +18,6 @@ module.exports = Self => {
|
|||
require('../methods/item/buyerWasteEmail')(Self);
|
||||
require('../methods/item/setVisibleDiscard')(Self);
|
||||
require('../methods/item/get')(Self);
|
||||
require('../methods/item/search')(Self);
|
||||
|
||||
Self.validatesPresenceOf('originFk', {message: 'Cannot be blank'});
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
"observations": {
|
||||
"type": "string"
|
||||
},
|
||||
"editorFk": {
|
||||
"userFk": {
|
||||
"type": "number"
|
||||
},
|
||||
"price": {
|
||||
|
|
|
@ -15,13 +15,16 @@
|
|||
"roadmapFk": {
|
||||
"type": "number"
|
||||
},
|
||||
"addressFk": {
|
||||
"type": "number"
|
||||
},
|
||||
"eta": {
|
||||
"type": "date"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"editorFk": {
|
||||
"userFk": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
|
@ -34,7 +37,7 @@
|
|||
"address": {
|
||||
"type": "belongsTo",
|
||||
"model": "RoadmapAddress",
|
||||
"foreignKey": "roadmapAddressFk"
|
||||
"foreignKey": "addressFk"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ module.exports = Self => {
|
|||
ps.monitorId,
|
||||
e.created
|
||||
FROM expedition e
|
||||
JOIN host h ON h.code = e.hostFk
|
||||
JOIN host h ON Convert(h.code USING utf8mb3) COLLATE utf8mb3_unicode_ci = e.hostFk
|
||||
JOIN packingSite ps ON ps.hostFk = h.id
|
||||
WHERE e.id = ?;`;
|
||||
const [expedition] = await models.Expedition.rawSql(query, [id]);
|
||||
|
|
|
@ -44,7 +44,7 @@ module.exports = Self => {
|
|||
ps.monitorId,
|
||||
e.created
|
||||
FROM expedition e
|
||||
JOIN host h ON h.code = e.hostFk
|
||||
JOIN host h ON Convert(h.code USING utf8mb3) COLLATE utf8mb3_unicode_ci = e.hostFk
|
||||
JOIN packingSite ps ON ps.hostFk = h.id
|
||||
WHERE e.id = ?;`;
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
const smtp = require('vn-print/core/smtp');
|
||||
const config = require('vn-print/core/config');
|
||||
const closure = require('./closure');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('closeAll', {
|
||||
|
@ -26,62 +25,122 @@ module.exports = Self => {
|
|||
Self.closeAll = async(ctx, options) => {
|
||||
const userId = ctx.req.accessToken.userId;
|
||||
const myOptions = {userId};
|
||||
let tx;
|
||||
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
if (!myOptions.transaction) {
|
||||
tx = await Self.beginTransaction({});
|
||||
myOptions.transaction = tx;
|
||||
}
|
||||
let tx;
|
||||
// IMPORTANT: Due to its high cost in production, wrapping this process in a transaction may cause timeouts.
|
||||
|
||||
const toDate = Date.vnNew();
|
||||
toDate.setHours(0, 0, 0, 0);
|
||||
toDate.setDate(toDate.getDate() - 1);
|
||||
const [{dateFrom, dateTo}] = await Self.rawSql(`
|
||||
SELECT ? - INTERVAL closureDaysAgo DAY dateFrom,
|
||||
util.dayEnd(?) dateTo
|
||||
FROM ticketConfig
|
||||
LIMIT 1`, [toDate, toDate], myOptions);
|
||||
|
||||
await Self.rawSql(`
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.ticket_close;
|
||||
CREATE TEMPORARY TABLE tmp.ticket_close
|
||||
ENGINE = MEMORY
|
||||
WITH wTickets AS(
|
||||
SELECT t.id ticketFk
|
||||
FROM ticket t
|
||||
JOIN warehouse wh ON wh.id = t.warehouseFk AND wh.hasComission
|
||||
WHERE t.shipped BETWEEN ? AND ?
|
||||
AND t.refFk IS NULL
|
||||
), wTicketsTracking AS(
|
||||
SELECT wt.ticketFk, MAX(tt.id) maxTracking
|
||||
FROM wTickets wt
|
||||
JOIN ticketTracking tt ON tt.ticketFk = wt.ticketFk
|
||||
GROUP BY tt.ticketFk
|
||||
), wTicketsLastState AS(
|
||||
SELECT wt.ticketFk, tt.stateFk
|
||||
FROM wTicketsTracking wt
|
||||
JOIN ticketTracking tt ON tt.id = wt.maxTracking
|
||||
) SELECT tls.ticketFk,
|
||||
const tickets = await Self.rawSql(`
|
||||
SELECT t.id,
|
||||
t.clientFk,
|
||||
t.companyFk,
|
||||
c.id clientFk,
|
||||
c.name clientName,
|
||||
c.email recipient,
|
||||
eu.email salesPersonEmail,
|
||||
t.addressFk,
|
||||
c.salesPersonFk,
|
||||
c.isToBeMailed,
|
||||
c.hasToInvoice,
|
||||
c.hasDailyInvoice,
|
||||
c.hasToInvoiceByAddress,
|
||||
t.totalWithVat,
|
||||
t.companyFk
|
||||
FROM wTicketsLastState tls
|
||||
JOIN ticket t ON t.id = tls.ticketFk
|
||||
JOIN state s ON s.id =tls.stateFk
|
||||
JOIN alertLevel al ON al.id = s.alertLevel
|
||||
eu.email salesPersonEmail,
|
||||
t.addressFk
|
||||
FROM ticket t
|
||||
JOIN agencyMode am ON am.id = t.agencyModeFk
|
||||
JOIN warehouse wh ON wh.id = t.warehouseFk AND wh.hasComission
|
||||
JOIN ticketState ts ON ts.ticketFk = t.id
|
||||
JOIN alertLevel al ON al.id = ts.alertLevel
|
||||
JOIN client c ON c.id = t.clientFk
|
||||
JOIN province p ON p.id = c.provinceFk
|
||||
JOIN country co ON co.id = p.countryFk
|
||||
LEFT JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk
|
||||
WHERE (al.code = 'PACKED' OR (am.code = 'refund' AND al.code <> 'delivered'));
|
||||
CALL ticket_close();
|
||||
`, [dateFrom, dateTo], myOptions);
|
||||
JOIN ticketConfig tc ON TRUE
|
||||
WHERE (al.code = 'PACKED' OR (am.code = 'refund' AND al.code <> 'delivered'))
|
||||
AND t.shipped BETWEEN ? - INTERVAL tc.closureDaysAgo DAY AND util.dayEnd(?)
|
||||
AND t.refFk IS NULL
|
||||
GROUP BY t.id
|
||||
`, [toDate, toDate], myOptions);
|
||||
const ticketIds = tickets.map(ticket => ticket.id);
|
||||
await Self.rawSql(`
|
||||
INSERT INTO util.debug (variable, value)
|
||||
VALUES ('nightInvoicing', ?)
|
||||
`, [ticketIds.join(',')], myOptions);
|
||||
|
||||
await Self.rawSql(`
|
||||
WITH ticketNotInvoiceable AS(
|
||||
SELECT JSON_OBJECT(
|
||||
'tickets',
|
||||
JSON_ARRAYAGG(
|
||||
JSON_OBJECT(
|
||||
'ticketId', ticketFk,
|
||||
'reason', reason,
|
||||
'clientId', clientFk
|
||||
)
|
||||
)
|
||||
)errors
|
||||
FROM (
|
||||
SELECT ticketFk,
|
||||
CONCAT_WS(', ',
|
||||
IF(hasErrorToInvoice, 'Facturar', NULL),
|
||||
IF(hasErrorTaxDataChecked, 'Datos comprobados', NULL),
|
||||
IF(hasErrorDeleted, 'Eliminado', NULL),
|
||||
IF(hasErrorItemTaxCountry, 'Impuesto no informado', NULL),
|
||||
IF(hasErrorAddress, 'Sin dirección', NULL),
|
||||
IF(hasErrorInfoTaxAreaWorld, 'Datos exportaciones', NULL)) reason,
|
||||
clientFk
|
||||
FROM (
|
||||
SELECT t.id ticketFk,
|
||||
SUM(NOT c.hasToInvoice) hasErrorToInvoice,
|
||||
SUM(NOT c.isTaxDataChecked) hasErrorTaxDataChecked,
|
||||
SUM(t.isDeleted) hasErrorDeleted,
|
||||
SUM(itc.id IS NULL) hasErrorItemTaxCountry,
|
||||
SUM(a.id IS NULL) hasErrorAddress,
|
||||
SUM(ios.code IS NOT NULL
|
||||
AND(ad.customsAgentFk IS NULL
|
||||
OR ad.incotermsFk IS NULL)) hasErrorInfoTaxAreaWorld,
|
||||
t.clientFk clientFk
|
||||
FROM ticket t
|
||||
LEFT JOIN address ad ON ad.id = t.addressFk
|
||||
JOIN sale s ON s.ticketFk = t.id
|
||||
JOIN item i ON i.id = s.itemFk
|
||||
JOIN supplier su ON su.id = t.companyFk
|
||||
JOIN agencyMode am ON am.id = t.agencyModeFk
|
||||
JOIN warehouse wh ON wh.id = t.warehouseFk AND wh.hasComission
|
||||
JOIN ticketState ts ON ts.ticketFk = t.id
|
||||
JOIN alertLevel al ON al.id = ts.alertLevel
|
||||
JOIN client c ON c.id = t.clientFk
|
||||
JOIN province p ON p.id = c.provinceFk
|
||||
JOIN ticketConfig tc ON TRUE
|
||||
LEFT JOIN autonomy a ON a.id = p.autonomyFk
|
||||
JOIN country co ON co.id = p.countryFk
|
||||
LEFT JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk
|
||||
LEFT JOIN itemTaxCountry itc ON itc.itemFk = i.id
|
||||
AND itc.countryFk = su.countryFk
|
||||
LEFT JOIN vn.invoiceOutSerial ios ON ios.taxAreaFk = 'WORLD'
|
||||
AND ios.code = invoiceSerial(t.clientFk, t.companyFk, 'multiple')
|
||||
WHERE (al.code = 'PACKED' OR (am.code = 'refund' AND al.code <> 'delivered'))
|
||||
AND t.shipped BETWEEN ? - INTERVAL tc.closureDaysAgo DAY AND util.dayEnd(?)
|
||||
AND t.refFk IS NULL
|
||||
AND c.hasDailyInvoice
|
||||
GROUP BY ticketFk
|
||||
HAVING hasErrorToInvoice
|
||||
OR hasErrorTaxDataChecked
|
||||
OR hasErrorDeleted
|
||||
OR hasErrorItemTaxCountry
|
||||
OR hasErrorAddress
|
||||
OR hasErrorInfoTaxAreaWorld
|
||||
)sub
|
||||
)sub2
|
||||
) SELECT IF(errors = '{"tickets": null}',
|
||||
'No errors',
|
||||
util.notification_send('invoice-ticket-closure', errors, NULL))
|
||||
FROM ticketNotInvoiceable`, [toDate, toDate], myOptions);
|
||||
|
||||
await closure(ctx, Self, tickets, myOptions);
|
||||
|
||||
await Self.rawSql(`
|
||||
UPDATE ticket t
|
||||
|
@ -92,100 +151,17 @@ module.exports = Self => {
|
|||
JOIN ticketConfig tc ON TRUE
|
||||
LEFT JOIN ticketObservation tob ON tob.ticketFk = t.id
|
||||
SET t.routeFk = NULL
|
||||
WHERE t.shipped BETWEEN ? AND ?
|
||||
WHERE t.shipped BETWEEN ? - INTERVAL tc.closureDaysAgo DAY AND util.dayEnd(?)
|
||||
AND al.code NOT IN ('DELIVERED', 'PACKED')
|
||||
AND NOT t.packages
|
||||
AND tob.id IS NULL
|
||||
AND t.routeFk`, [dateFrom, dateTo], myOptions);
|
||||
|
||||
const [clients] = await Self.rawSql(`
|
||||
SELECT clientFk clientId,
|
||||
clientName,
|
||||
recipient,
|
||||
salesPersonEmail,
|
||||
addressFk addressId,
|
||||
companyFk,
|
||||
SUM(totalWithVat) total,
|
||||
'quick' serialType
|
||||
FROM tmp.ticket_close
|
||||
WHERE hasDailyInvoice
|
||||
GROUP BY IF (hasToInvoiceByAddress, addressFk, clientFk), companyFk
|
||||
HAVING total > 0;
|
||||
DROP TEMPORARY TABLE tmp.ticket_close;
|
||||
`, [], myOptions);
|
||||
AND t.routeFk`, [toDate, toDate], myOptions);
|
||||
|
||||
if (tx)
|
||||
await tx.commit();
|
||||
|
||||
const failedClients = [];
|
||||
const nestedTransaction = options?.transaction ? myOptions : {};
|
||||
for (const client of clients) {
|
||||
ctx.args = {
|
||||
...client,
|
||||
invoiceDate: Date.vnNew(),
|
||||
maxShipped: toDate
|
||||
};
|
||||
try {
|
||||
const id = await Self.app.models.InvoiceOut.invoiceClient(ctx, nestedTransaction);
|
||||
if (id)
|
||||
await Self.app.models.InvoiceOut.makePdfAndNotify(ctx, id, null, nestedTransaction);
|
||||
} catch (error) {
|
||||
await Self.rawSql(`
|
||||
INSERT INTO util.debug (variable, value)
|
||||
VALUES ('invoicingTicketError', ?)
|
||||
`, [client.clientId + ' - ' + error]);
|
||||
|
||||
if (error.responseCode == 450) {
|
||||
await invalidEmail(client);
|
||||
continue;
|
||||
}
|
||||
|
||||
failedClients.push({
|
||||
id: client.clientId,
|
||||
address: client.addressId,
|
||||
error
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (failedClients.length > 0) {
|
||||
let body = 'This following tickets have failed:<br/><br/>';
|
||||
|
||||
for (const client of failedClients) {
|
||||
body += `Client: <strong>${client.id}</strong>
|
||||
Address: <strong>${client.address}</strong>
|
||||
<br/> <strong>${client.error}</strong><br/><br/>`;
|
||||
}
|
||||
|
||||
smtp.send({
|
||||
to: config.app.reportEmail,
|
||||
subject: '[API] Nightly ticket closure report',
|
||||
html: body,
|
||||
}).catch(err => console.error(err));
|
||||
}
|
||||
|
||||
return {
|
||||
message: 'Success'
|
||||
};
|
||||
};
|
||||
|
||||
async function invalidEmail(client) {
|
||||
await Self.rawSql(
|
||||
`UPDATE client SET email = NULL WHERE id = ?`,
|
||||
[client.clientId],
|
||||
myOptions
|
||||
);
|
||||
|
||||
const body = `No se ha podido facturar al cliente <strong>${client.clientId} - ${client.clientName}</strong>
|
||||
porque la dirección de email <strong>"${client.recipient}"</strong> no es correcta
|
||||
o no está disponible.<br/><br/>
|
||||
Para evitar que se repita este error, se ha eliminado la dirección de email de la ficha del cliente.
|
||||
Actualiza la dirección de email con una correcta.`;
|
||||
|
||||
smtp.send({
|
||||
to: client.salesPersonEmail,
|
||||
subject: 'No se ha podido enviar el albarán',
|
||||
html: body,
|
||||
}).catch(err => console.error(err));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -284,6 +284,39 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"relation": "business",
|
||||
"scope": {
|
||||
"fields": [
|
||||
"id",
|
||||
"started",
|
||||
"ended",
|
||||
"reasonEndFk",
|
||||
"departmentFk",
|
||||
"workerBusinessProfessionalCategoryFk"
|
||||
],
|
||||
"include":[
|
||||
{
|
||||
"relation": "department",
|
||||
"scope": {
|
||||
"fields": ["id", "name"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"relation": "reasonEnd",
|
||||
"scope": {
|
||||
"fields": ["id", "reason"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"relation": "workerBusinessProfessionalCategory",
|
||||
"scope": {
|
||||
"fields": ["id", "description"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"relation": "boss",
|
||||
"scope": {
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
<td width="5%">{{sale.itemFk}}</td>
|
||||
<td class="number">{{sale.quantity}}</td>
|
||||
<td width="50%">{{sale.concept}}</td>
|
||||
<td width="5%" class="font light-gray">{{sale.subName}}</td>
|
||||
<td width="5%" class="font light-gray" v-if="sale.subName">{{sale.subName}}</td>
|
||||
<td class="number" v-if="showPrices">{{sale.price | currency('EUR', $i18n.locale)}}</td>
|
||||
<td class="centered" width="5%" v-if="showPrices">{{(sale.discount / 100) | percentage}}</td>
|
||||
<td class="centered" v-if="showPrices">{{sale.vatType}}</td>
|
||||
|
|
Loading…
Reference in New Issue