Merge branch 'dev' into 8244-floricode
gitea/salix/pipeline/pr-dev There was a failure building this commit
Details
gitea/salix/pipeline/pr-dev There was a failure building this commit
Details
This commit is contained in:
commit
f4842827a6
|
@ -13,6 +13,11 @@ module.exports = Self => {
|
|||
type: 'string',
|
||||
description: 'Origin model from insert'
|
||||
},
|
||||
{
|
||||
arg: 'description',
|
||||
type: 'string',
|
||||
description: 'Action description'
|
||||
},
|
||||
|
||||
],
|
||||
http: {
|
||||
|
@ -21,7 +26,7 @@ module.exports = Self => {
|
|||
}
|
||||
});
|
||||
|
||||
Self.add = async(ctx, code, model, options) => {
|
||||
Self.add = async(ctx, code, model, description, options) => {
|
||||
const userId = ctx.req.accessToken.userId;
|
||||
const myOptions = {};
|
||||
|
||||
|
@ -29,8 +34,8 @@ module.exports = Self => {
|
|||
Object.assign(myOptions, options);
|
||||
|
||||
return await Self.rawSql(`
|
||||
INSERT INTO workerActivity (workerFk, workerActivityTypeFk, model)
|
||||
SELECT ?, ?, ?
|
||||
INSERT INTO workerActivity (workerFk, workerActivityTypeFk, model, description)
|
||||
SELECT ?, ?, ?, ?
|
||||
FROM workerTimeControlConfig wtcc
|
||||
LEFT JOIN (
|
||||
SELECT wa.workerFk,
|
||||
|
@ -45,6 +50,6 @@ module.exports = Self => {
|
|||
WHERE sub.workerFk IS NULL
|
||||
OR sub.code <> ?
|
||||
OR TIMESTAMPDIFF(SECOND, sub.created, util.VN_NOW()) > wtcc.dayBreak;`
|
||||
, [userId, code, model, userId, code], myOptions);
|
||||
, [userId, code, model, description, userId, code], myOptions);
|
||||
};
|
||||
};
|
||||
|
|
|
@ -13,7 +13,7 @@ describe('workerActivity insert()', () => {
|
|||
{'code': 'TEST', 'description': 'TEST'}, options
|
||||
);
|
||||
|
||||
await models.WorkerActivity.add(ctx, 'TEST', 'APP', options);
|
||||
await models.WorkerActivity.add(ctx, 'TEST', 'APP', 'description', options);
|
||||
|
||||
count = await models.WorkerActivity.count(
|
||||
{'workerFK': 1106}, options
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"relations": {
|
||||
"agency": {
|
||||
"type": "belongsTo",
|
||||
"model": "WorkCenter",
|
||||
"model": "Agency",
|
||||
"foreignKey": "agencyFk"
|
||||
},
|
||||
"workCenter": {
|
||||
|
|
|
@ -195,7 +195,7 @@ INSERT INTO `vn`.`sectorType` (`id`, `code`)
|
|||
INSERT INTO `vn`.`sector`(`id`, `description`, `warehouseFk`, `code`, `typeFk`)
|
||||
VALUES
|
||||
(1, 'First sector', 1, 'FIRST', 1),
|
||||
(2, 'Second sector', 2, 'SECOND',1);
|
||||
(2, 'Second sector', 6, 'SECOND',1);
|
||||
|
||||
INSERT INTO `vn`.`printer` (`id`, `name`, `path`, `isLabeler`, `sectorFk`, `ipAddress`)
|
||||
VALUES
|
||||
|
@ -730,7 +730,8 @@ INSERT INTO `vn`.`zoneWarehouse` (`id`, `zoneFk`, `warehouseFk`)
|
|||
(10, 10, 3),
|
||||
(11, 11, 5),
|
||||
(12, 12, 4),
|
||||
(13, 13, 5);
|
||||
(13, 13, 5),
|
||||
(14, 7, 4);
|
||||
|
||||
INSERT INTO `vn`.`zoneClosure` (`zoneFk`, `dated`, `hour`)
|
||||
VALUES
|
||||
|
@ -853,7 +854,8 @@ INSERT INTO `vn`.`ticketTracking`(`ticketFk`, `stateFk`, `userFk`, `created`)
|
|||
|
||||
INSERT INTO `vn`.`deliveryPoint` (`id`, `name`, `ubication`)
|
||||
VALUES
|
||||
(1, 'Gotham','1007 Mountain Drive, Gotham');
|
||||
(1, 'Gotham','1007 Mountain Drive, Gotham'),
|
||||
(6, 'Stark Tower','200 Park Avenue, Nueva York');
|
||||
|
||||
INSERT INTO `vn`.`vehicle`(`id`, `numberPlate`, `tradeMark`, `model`, `companyFk`, `warehouseFk`, `description`, `m3`, `isActive`, `deliveryPointFk`, `chassis`, `leasing`, `supplierFk`, `fuelTypeFk`, `bankPolicyFk`)
|
||||
VALUES
|
||||
|
@ -1302,9 +1304,10 @@ INSERT INTO `vn`.`train`(`id`, `name`)
|
|||
|
||||
INSERT INTO `vn`.`operator` (`workerFk`, `numberOfWagons`, `trainFk`, `itemPackingTypeFk`, `warehouseFk`, `sectorFk`, `labelerFk`)
|
||||
VALUES
|
||||
('1106', '1', '1', 'H', '1', '1', '1'),
|
||||
('9', '2', '1', 'H', '1', '1', '1'),
|
||||
('1107', '1', '1', 'V', '1', '1', '1');
|
||||
(1106, '1', '1', 'H', '1', '1', '1'),
|
||||
(9, '2', '1', 'H', '1', '1', '1'),
|
||||
(1107, '1', '1', 'V', '1', '1', '1'),
|
||||
(72, '1', '1', 'V', '1', '1', '1');
|
||||
|
||||
INSERT INTO `vn`.`collection`(`id`, `workerFk`, `stateFk`, `created`, `trainFk`)
|
||||
VALUES
|
||||
|
@ -1615,6 +1618,7 @@ INSERT INTO `bs`.`waste`(`buyerFk`, `year`, `week`, `itemFk`, `itemTypeFk`, `sal
|
|||
(19, 100, 1, 50, 100, 4, 1, 1.500, 1.500, 0.000, 1, 1, 'grouping', NULL, 0.00, 99.6, 99.4, 0, 1, 0, NULL, 1, util.VN_CURDATE()),
|
||||
(20, 100, 2, 5, 450, 3, 2, 1.000, 1.000, 0.000, 10, 10, NULL, NULL, 0.00, 7.30, 7.00, 0, 1, 0, NULL, 2.5, util.VN_CURDATE()),
|
||||
(21, 100,72, 55, 500, 5, 3, 1.000, 1.000, 0.000, 1, 1, 'packing', NULL, 0.00, 78.3, 75.6, 0, 1, 0, 1, 3, util.VN_CURDATE()),
|
||||
(22, 100, 4, 55, 0, 5, 0, 0, 0, 0.000, 1, 1, 'packing', NULL, 0.00, 78.3, 75.6, 0, 1, 0, 1, 3, util.VN_CURDATE()),
|
||||
(10000002, 12,88, 50.0000, 5000, 4, 1, 1.500, 1.500, 0.000, 1, 1, 'grouping', NULL, 0.00, 99.60, 99.40, 0, 1, 0, 1.00, 1,util.VN_CURDATE() - INTERVAL 2 MONTH);
|
||||
|
||||
INSERT INTO `hedera`.`order`(`id`, `date_send`, `customer_id`, `delivery_method_id`, `agency_id`, `address_id`, `company_id`, `note`, `source_app`, `confirmed`,`total`, `date_make`, `first_row_stamp`, `confirm_date`)
|
||||
|
@ -1957,11 +1961,11 @@ INSERT INTO `vn`.`claimBeginning`(`id`, `claimFk`, `saleFk`, `quantity`)
|
|||
|
||||
INSERT INTO `vn`.`claimDestination`(`id`, `description`, `addressFk`)
|
||||
VALUES
|
||||
(1, 'Bueno', NULL),
|
||||
(2, 'Basura/Perd.', 12),
|
||||
(1, 'Bueno', 11),
|
||||
(2, 'Basura/Perd.', NULL),
|
||||
(3, 'Confeccion', NULL),
|
||||
(4, 'Reclam.PRAG', 12),
|
||||
(5, 'Corregido', 11);
|
||||
(4, 'Reclam.PRAG', NULL),
|
||||
(5, 'Corregido', NULL);
|
||||
|
||||
INSERT INTO `vn`.`claimDevelopment`(`id`, `claimFk`, `claimResponsibleFk`, `workerFk`, `claimReasonFk`, `claimResultFk`, `claimRedeliveryFk`, `claimDestinationFk`)
|
||||
VALUES
|
||||
|
@ -1976,9 +1980,9 @@ INSERT INTO `vn`.`claimEnd`(`id`, `saleFk`, `claimFk`, `workerFk`, `claimDestina
|
|||
(1, 31, 4, 21, 2),
|
||||
(2, 32, 3, 21, 3);
|
||||
|
||||
INSERT INTO `vn`.`claimConfig`(`id`, `maxResponsibility`, `monthsToRefund`, `minShipped`,`daysToClaim`)
|
||||
INSERT INTO `vn`.`claimConfig`(`id`, `maxResponsibility`, `monthsToRefund`, `minShipped`,`daysToClaim`, `pickupDeliveryFk`, `warehouseFk`)
|
||||
VALUES
|
||||
(1, 5, 4, '2016-10-01', 7);
|
||||
(1, 5, 4, '2016-10-01', 7, 8, 4);
|
||||
|
||||
INSERT INTO `vn`.`claimRatio`(`clientFk`, `yearSale`, `claimAmount`, `claimingRate`, `priceIncreasing`, `packingRate`)
|
||||
VALUES
|
||||
|
@ -3063,9 +3067,10 @@ INSERT INTO `salix`.`url` (`appName`, `environment`, `url`)
|
|||
('salix', 'development', 'http://localhost:5000/#!/'),
|
||||
('docuware', 'development', 'http://docuware');
|
||||
|
||||
INSERT INTO `vn`.`report` (`id`, `name`, `paperSizeFk`, `method`)
|
||||
INSERT INTO `vn`.`report` (`name`, `method`)
|
||||
VALUES
|
||||
(3, 'invoice', NULL, 'InvoiceOuts/{refFk}/invoice-out-pdf');
|
||||
('invoice', 'InvoiceOuts/{refFk}/invoice-out-pdf'),
|
||||
('LabelBuy', 'Entries/{id}/{labelType}/buy-label');
|
||||
|
||||
INSERT INTO `vn`.`payDemDetail` (`id`, `detail`)
|
||||
VALUES
|
||||
|
@ -4145,3 +4150,6 @@ INSERT IGNORE INTO vn.vehicleType (id, name)
|
|||
|
||||
INSERT INTO edi.tableMultiConfig (fileName, toTable, file, `method`, updated)
|
||||
VALUES ('FG', 'genus', 'florecompc2', 'VBN/Genus', '2001-01-01');
|
||||
|
||||
INSERT INTO vn.addressWaste (addressFk, type)
|
||||
VALUES (11, 'fault');
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` EVENT `stock`.`log_clean`
|
||||
ON SCHEDULE EVERY 1 DAY
|
||||
STARTS '2022-01-28 09:29:18.000'
|
||||
ON COMPLETION PRESERVE
|
||||
ENABLE
|
||||
DO CALL log_clean$$
|
||||
DELIMITER ;
|
|
@ -1,8 +0,0 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` EVENT `stock`.`log_syncNoWait`
|
||||
ON SCHEDULE EVERY 5 SECOND
|
||||
STARTS '2017-06-27 17:15:02.000'
|
||||
ON COMPLETION NOT PRESERVE
|
||||
DISABLE
|
||||
DO CALL log_syncNoWait$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,8 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` EVENT `stock`.`stock_clean`
|
||||
ON SCHEDULE EVERY 60 SECOND
|
||||
STARTS '2025-01-01 00:00:00.000'
|
||||
ON COMPLETION PRESERVE
|
||||
ENABLE
|
||||
DO CALL stock_clean$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,8 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` EVENT `stock`.`stock_sync`
|
||||
ON SCHEDULE EVERY 5 SECOND
|
||||
STARTS '2025-01-01 00:00:00.000'
|
||||
ON COMPLETION PRESERVE
|
||||
DISABLE
|
||||
DO CALL stock_sync$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,91 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`buyLot_refresh`(
|
||||
`vTable` ENUM('lot', 'entry', 'travel'),
|
||||
`vId` INT)
|
||||
BEGIN
|
||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||
BEGIN
|
||||
ROLLBACK;
|
||||
RESIGNAL;
|
||||
END;
|
||||
|
||||
CREATE OR REPLACE TEMPORARY TABLE tBuyAlive
|
||||
ENGINE = MEMORY
|
||||
SELECT
|
||||
t.id travelFk,
|
||||
t.landed,
|
||||
t.landingHour,
|
||||
t.warehouseInFk,
|
||||
t.isReceived,
|
||||
t.isRaid,
|
||||
e.id entryFk,
|
||||
b.lotFk,
|
||||
b.itemFk,
|
||||
b.life,
|
||||
b.quantity
|
||||
FROM tLotStatus ls
|
||||
JOIN vn.buy b ON b.lotFk = ls.lotFk
|
||||
JOIN vn.entry e ON e.id = b.entryFk
|
||||
JOIN vn.travel t ON t.id = e.travelFk
|
||||
WHERE ls.isIncluded;
|
||||
|
||||
START TRANSACTION;
|
||||
|
||||
-- Delete excluded/deleted/dead lots
|
||||
|
||||
DELETE l FROM buyLot l
|
||||
JOIN tLotStatus ls USING(lotFk)
|
||||
WHERE NOT ls.isIncluded;
|
||||
|
||||
-- Delete undead lot picks
|
||||
|
||||
UPDATE buyOut o
|
||||
JOIN buyPick p ON p.outFk = o.outFk
|
||||
JOIN tLotStatus ls ON ls.lotFk = p.lotFk
|
||||
SET o.isSync = FALSE,
|
||||
o.lack = o.lack + p.quantity
|
||||
WHERE ls.isExcluded OR ls.isIncluded;
|
||||
|
||||
DELETE p FROM buyPick p
|
||||
JOIN tLotStatus ls USING(lotFk)
|
||||
WHERE ls.isExcluded OR ls.isIncluded;
|
||||
|
||||
-- Update alive outs
|
||||
|
||||
INSERT INTO buyLot (
|
||||
lotFk,
|
||||
isSync,
|
||||
isPicked,
|
||||
warehouseFk,
|
||||
itemFk,
|
||||
dated,
|
||||
expired,
|
||||
quantity,
|
||||
available
|
||||
)
|
||||
SELECT
|
||||
lotFk,
|
||||
FALSE,
|
||||
isReceived,
|
||||
warehouseInFk,
|
||||
itemFk,
|
||||
@dated := ADDTIME(landed, IFNULL(landingHour, '00:00:00')),
|
||||
@dated + INTERVAL life DAY,
|
||||
quantity,
|
||||
NULL
|
||||
FROM tBuyAlive
|
||||
ON DUPLICATE KEY UPDATE
|
||||
isSync = VALUES(isSync),
|
||||
isPicked = VALUES(isPicked),
|
||||
warehouseFk = VALUES(warehouseFk),
|
||||
itemFk = VALUES(itemFk),
|
||||
dated = VALUES(dated),
|
||||
expired = VALUES(expired),
|
||||
quantity = VALUES(quantity),
|
||||
available = VALUES(available);
|
||||
|
||||
COMMIT;
|
||||
|
||||
DROP TEMPORARY TABLE tBuyAlive;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,64 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`buyLot_requestQuantity`(
|
||||
vSelf INT,
|
||||
vRequested INT,
|
||||
vDated DATETIME,
|
||||
vOutFk INT,
|
||||
OUT vSupplied INT)
|
||||
BEGIN
|
||||
/**
|
||||
* Disassociates lot picks after the given date until the demanded quantity is
|
||||
* satisfied.
|
||||
*
|
||||
* @param vSelf The buyLot reference
|
||||
* @param vRequested The requested quantity
|
||||
* @param vDate The starting date for the associated outs
|
||||
* @param vOutFk The if of requesting out
|
||||
* @param vSupplied The supplied quantity
|
||||
*/
|
||||
DECLARE vPickFk INT;
|
||||
DECLARE vPickOutFk INT;
|
||||
DECLARE vPickQuantity INT;
|
||||
DECLARE vPickGranted INT;
|
||||
DECLARE vDone BOOL;
|
||||
|
||||
DECLARE vPicks CURSOR FOR
|
||||
SELECT p.id, o.outFk, p.quantity
|
||||
FROM buyPick p
|
||||
JOIN buyOut o USING(outFk)
|
||||
WHERE p.lotFk = vSelf
|
||||
AND (o.dated, o.outFk) > (vDated, vOutFk)
|
||||
ORDER BY o.dated DESC, o.created DESC, o.outFk DESC;
|
||||
|
||||
DECLARE CONTINUE HANDLER FOR NOT FOUND
|
||||
SET vDone = TRUE;
|
||||
|
||||
SET vSupplied = 0;
|
||||
|
||||
OPEN vPicks;
|
||||
|
||||
myLoop: LOOP
|
||||
SET vDone = FALSE;
|
||||
FETCH vPicks INTO vPickFk, vPickOutFk, vPickQuantity;
|
||||
|
||||
IF vDone THEN
|
||||
LEAVE myLoop;
|
||||
END IF;
|
||||
|
||||
SET vPickGranted = LEAST(vRequested - vSupplied, vPickQuantity);
|
||||
SET vSupplied = vSupplied + vPickGranted;
|
||||
CALL buyPick_remove(vPickFk, vPickGranted, vPickQuantity);
|
||||
|
||||
UPDATE buyOut
|
||||
SET isSync = FALSE,
|
||||
lack = lack + vPickGranted
|
||||
WHERE outFk = vPickOutFk;
|
||||
|
||||
IF vSupplied >= vRequested THEN
|
||||
LEAVE myLoop;
|
||||
END IF;
|
||||
END LOOP;
|
||||
|
||||
CLOSE vPicks;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -1,10 +1,10 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`inbound_sync`(vSelf INT)
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`buyLot_sync`(vSelf INT)
|
||||
BEGIN
|
||||
/**
|
||||
* Associates a inbound with their possible outbounds, updating it's available.
|
||||
* Associates a lot with their possible outs, updating it's available.
|
||||
*
|
||||
* @param vSelf The inbound identifier
|
||||
* @param vSelf The lot id
|
||||
*/
|
||||
DECLARE vDated DATETIME;
|
||||
DECLARE vExpired DATETIME;
|
||||
|
@ -14,37 +14,37 @@ BEGIN
|
|||
DECLARE vAvailable INT;
|
||||
DECLARE vSupplied INT;
|
||||
DECLARE vSuppliedFromRequest INT;
|
||||
DECLARE vOutboundFk INT;
|
||||
DECLARE vOutFk INT;
|
||||
DECLARE vLack INT;
|
||||
DECLARE vHasPicks BOOL;
|
||||
DECLARE vDone BOOL;
|
||||
|
||||
DECLARE vOutbounds CURSOR FOR
|
||||
SELECT id, lack, lack < quantity
|
||||
FROM outbound
|
||||
DECLARE vOuts CURSOR FOR
|
||||
SELECT outFk, lack, lack < quantity
|
||||
FROM buyOut
|
||||
WHERE warehouseFk = vWarehouse
|
||||
AND itemFk = vItem
|
||||
AND dated >= vDated
|
||||
AND (vExpired IS NULL OR dated < vExpired)
|
||||
ORDER BY dated, created;
|
||||
ORDER BY dated, created, outFk;
|
||||
|
||||
DECLARE CONTINUE HANDLER FOR NOT FOUND
|
||||
SET vDone = TRUE;
|
||||
|
||||
SELECT warehouseFk, itemFk, available, quantity, expired, dated
|
||||
INTO vWarehouse, vItem, vAvailable, vQuantity, vExpired, vDated
|
||||
FROM inbound
|
||||
WHERE id = vSelf;
|
||||
FROM buyLot
|
||||
WHERE lotFk = vSelf;
|
||||
|
||||
IF vAvailable IS NULL THEN
|
||||
SET vAvailable = vQuantity;
|
||||
END IF;
|
||||
|
||||
OPEN vOutbounds;
|
||||
OPEN vOuts;
|
||||
|
||||
myLoop: LOOP
|
||||
SET vDone = FALSE;
|
||||
FETCH vOutbounds INTO vOutboundFk, vLack, vHasPicks;
|
||||
FETCH vOuts INTO vOutFk, vLack, vHasPicks;
|
||||
|
||||
IF vDone THEN
|
||||
LEAVE myLoop;
|
||||
|
@ -54,19 +54,19 @@ BEGIN
|
|||
|
||||
IF vSupplied > 0 THEN
|
||||
SET vAvailable = vAvailable - vSupplied;
|
||||
UPDATE outbound
|
||||
UPDATE buyOut
|
||||
SET lack = lack - vSupplied
|
||||
WHERE id = vOutboundFk;
|
||||
WHERE outFk = vOutFk;
|
||||
END IF;
|
||||
|
||||
IF vHasPicks AND vAvailable > 0 THEN
|
||||
CALL outbound_requestQuantity(vOutboundFk, vAvailable, vDated, vSuppliedFromRequest);
|
||||
CALL buyOut_requestQuantity(vOutFk, vAvailable, vDated, vSelf, vSuppliedFromRequest);
|
||||
SET vSupplied = vSupplied + vSuppliedFromRequest;
|
||||
SET vAvailable = vAvailable - vSuppliedFromRequest;
|
||||
END IF;
|
||||
|
||||
IF vSupplied > 0 THEN
|
||||
CALL inbound_addPick(vSelf, vOutboundFk, vSupplied);
|
||||
CALL buyPick_add(vSelf, vOutFk, vSupplied);
|
||||
END IF;
|
||||
|
||||
IF vAvailable <= 0 THEN
|
||||
|
@ -74,11 +74,11 @@ BEGIN
|
|||
END IF;
|
||||
END LOOP;
|
||||
|
||||
CLOSE vOutbounds;
|
||||
CLOSE vOuts;
|
||||
|
||||
UPDATE inbound
|
||||
UPDATE buyLot
|
||||
SET isSync = TRUE,
|
||||
available = vAvailable
|
||||
WHERE id = vSelf;
|
||||
WHERE lotFk = vSelf;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,95 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`buyOut_refresh`(
|
||||
`vTable` VARCHAR(255),
|
||||
`vId` INT,
|
||||
`vSource` VARCHAR(255))
|
||||
BEGIN
|
||||
/**
|
||||
* This procedure contains the common code used to refresh the out lot cache.
|
||||
*
|
||||
* @param vTable The id source table
|
||||
* @param vId The lot id
|
||||
* @param vSource The lot source
|
||||
* @table tLotStatus Lots to modify
|
||||
* @table tLotAlive Updated/Created alive lots data
|
||||
*/
|
||||
DECLARE vHasLots BOOL;
|
||||
|
||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||
BEGIN
|
||||
ROLLBACK;
|
||||
RESIGNAL;
|
||||
END;
|
||||
|
||||
IF vTable = 'lot' THEN
|
||||
SELECT COUNT(*) > 0 INTO vHasLots FROM tLotStatus;
|
||||
|
||||
IF NOT vHasLots THEN
|
||||
INSERT INTO tLotStatus
|
||||
SET lotFk = vId,
|
||||
isExcluded = TRUE,
|
||||
isIncluded = FALSE;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
START TRANSACTION;
|
||||
|
||||
-- Delete excluded/deleted/dead outs
|
||||
|
||||
DELETE o FROM buyOut o
|
||||
JOIN tLotStatus ls ON ls.lotFk = o.outFk
|
||||
WHERE NOT ls.isIncluded;
|
||||
|
||||
-- Delete undead out picks
|
||||
|
||||
UPDATE buyLot l
|
||||
JOIN buyPick p ON p.lotFk = l.lotFk
|
||||
JOIN tLotStatus ls ON ls.lotFk = p.outFk
|
||||
SET l.isSync = FALSE,
|
||||
l.available = l.available + p.quantity
|
||||
WHERE ls.isExcluded OR ls.isIncluded;
|
||||
|
||||
DELETE p FROM buyPick p
|
||||
JOIN tLotStatus ls ON ls.lotFk = p.outFk
|
||||
WHERE ls.isExcluded OR ls.isIncluded;
|
||||
|
||||
-- Update alive outs
|
||||
|
||||
INSERT INTO buyOut (
|
||||
outFk,
|
||||
source,
|
||||
isSync,
|
||||
warehouseFk,
|
||||
dated,
|
||||
itemFk,
|
||||
quantity,
|
||||
lack,
|
||||
created,
|
||||
isPicked
|
||||
)
|
||||
SELECT
|
||||
lotFk,
|
||||
vSource,
|
||||
FALSE,
|
||||
warehouseFk,
|
||||
dated,
|
||||
itemFk,
|
||||
quantity,
|
||||
quantity,
|
||||
created,
|
||||
isPicked
|
||||
FROM tLotAlive
|
||||
ON DUPLICATE KEY UPDATE
|
||||
source = VALUES(source),
|
||||
warehouseFk = VALUES(warehouseFk),
|
||||
dated = VALUES(dated),
|
||||
itemFk = VALUES(itemFk),
|
||||
quantity = VALUES(quantity),
|
||||
lack = VALUES(lack),
|
||||
created = VALUES(created),
|
||||
isPicked = VALUES(isPicked),
|
||||
isSync = VALUES(isSync);
|
||||
|
||||
COMMIT;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,39 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`buyOut_refreshBuy`(
|
||||
`vTable` VARCHAR(255),
|
||||
`vId` INT)
|
||||
BEGIN
|
||||
CREATE OR REPLACE TEMPORARY TABLE tLotStatus
|
||||
ENGINE = MEMORY
|
||||
SELECT lotFk,
|
||||
@isExcluded := b.quantity <= 0 isExcluded,
|
||||
NOT @isExcluded AND b.isAlive isIncluded
|
||||
FROM vn.buy b
|
||||
JOIN vn.entry e ON e.id = b.entryFk
|
||||
WHERE
|
||||
(vTable = 'lot' AND b.lotFk = vId)
|
||||
OR (vTable = 'entry' AND e.id = vId)
|
||||
OR (vTable = 'travel' AND e.travelFk = vId);
|
||||
|
||||
CREATE OR REPLACE TEMPORARY TABLE tLotAlive
|
||||
ENGINE = MEMORY
|
||||
SELECT
|
||||
ls.lotFk,
|
||||
t.warehouseOutFk warehouseFk,
|
||||
ADDTIME(t.shipped, IFNULL(shipmentHour, '00:00:00')) dated,
|
||||
t.isDelivered isPicked,
|
||||
b.itemFk,
|
||||
b.quantity,
|
||||
b.created
|
||||
FROM tLotStatus ls
|
||||
JOIN vn.buy b ON b.lotFk = ls.lotFk
|
||||
JOIN vn.entry e ON e.id = b.entryFk
|
||||
JOIN vn.travel t ON t.id = e.travelFk
|
||||
WHERE ls.isIncluded;
|
||||
|
||||
CALL buyOut_refresh(vTable, vId, 'buy');
|
||||
CALL buyLot_refresh(vTable, vId);
|
||||
|
||||
DROP TEMPORARY TABLE tLotStatus, tLotAlive;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,36 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`buyOut_refreshOrder`(
|
||||
`vTable` VARCHAR(255),
|
||||
`vId` INT)
|
||||
BEGIN
|
||||
CREATE OR REPLACE TEMPORARY TABLE tLotStatus
|
||||
ENGINE = MEMORY
|
||||
SELECT lotFk,
|
||||
@isExcluded := o.confirmed OR NOT isReserved OR r.amount <= 0 isExcluded,
|
||||
NOT @isExcluded isIncluded
|
||||
FROM hedera.orderRow r
|
||||
JOIN hedera.`order` o ON o.id = r.orderFk
|
||||
WHERE
|
||||
(vTable = 'lot' AND r.lotFk = vId)
|
||||
OR (vTable = 'order' AND o.id = vId);
|
||||
|
||||
CREATE OR REPLACE TEMPORARY TABLE tLotAlive
|
||||
ENGINE = MEMORY
|
||||
SELECT
|
||||
ls.lotFk,
|
||||
r.warehouseFk,
|
||||
r.shipment dated,
|
||||
r.itemFk,
|
||||
r.amount quantity,
|
||||
r.created,
|
||||
FALSE isPicked
|
||||
FROM tLotStatus ls
|
||||
JOIN hedera.orderRow r ON r.lotFk = ls.lotFk
|
||||
JOIN hedera.`order` o ON o.id = r.orderFk
|
||||
WHERE ls.isIncluded;
|
||||
|
||||
CALL buyOut_refresh(vTable, vId, 'orderRow');
|
||||
|
||||
DROP TEMPORARY TABLE tLotStatus, tLotAlive;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,42 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`buyOut_refreshSale`(
|
||||
`vTable` VARCHAR(255),
|
||||
`vId` INT)
|
||||
BEGIN
|
||||
DECLARE vAliveDate DATE;
|
||||
|
||||
SELECT util.VN_CURDATE() - INTERVAL saleLife MONTH
|
||||
INTO vAliveDate
|
||||
FROM config LIMIT 1;
|
||||
|
||||
CREATE OR REPLACE TEMPORARY TABLE tLotStatus
|
||||
ENGINE = MEMORY
|
||||
SELECT lotFk,
|
||||
@isExcluded := s.quantity < 0 isExcluded,
|
||||
NOT @isExcluded AND t.isAlive isIncluded
|
||||
FROM vn.sale s
|
||||
JOIN vn.ticket t ON t.id = s.ticketFk
|
||||
WHERE
|
||||
(vTable = 'lot' AND s.lotFk = vId)
|
||||
OR (vTable = 'ticket' AND t.id = vId);
|
||||
|
||||
CREATE OR REPLACE TEMPORARY TABLE tLotAlive
|
||||
ENGINE = MEMORY
|
||||
SELECT
|
||||
ls.lotFk,
|
||||
t.warehouseFk,
|
||||
t.shipped dated,
|
||||
s.itemFk,
|
||||
s.quantity,
|
||||
s.created,
|
||||
s.isPicked
|
||||
FROM tLotStatus ls
|
||||
JOIN vn.sale s ON s.lotFk = ls.lotFk
|
||||
JOIN vn.ticket t ON t.id = s.ticketFk
|
||||
WHERE ls.isIncluded;
|
||||
|
||||
CALL buyOut_refresh(vTable, vId, 'sale');
|
||||
|
||||
DROP TEMPORARY TABLE tLotStatus, tLotAlive;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,64 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`buyOut_requestQuantity`(
|
||||
vSelf INT,
|
||||
vRequested INT,
|
||||
vDated DATETIME,
|
||||
vLotFk INT,
|
||||
OUT vSupplied INT)
|
||||
BEGIN
|
||||
/**
|
||||
* Disassociates out picks after the given date until the demanded quantity is
|
||||
* satisfied.
|
||||
*
|
||||
* @param vSelf The buyOut reference
|
||||
* @param vRequested The requested quantity
|
||||
* @param vDate The starting date for the associated lots
|
||||
* @param vLotFk The if of requesting lot
|
||||
* @param vSupplied The supplied quantity
|
||||
*/
|
||||
DECLARE vPickFk INT;
|
||||
DECLARE vPickLotFk INT;
|
||||
DECLARE vPickQuantity INT;
|
||||
DECLARE vPickGranted INT;
|
||||
DECLARE vDone BOOL;
|
||||
|
||||
DECLARE vPicks CURSOR FOR
|
||||
SELECT p.id, p.lotFk, p.quantity
|
||||
FROM buyPick p
|
||||
JOIN buyLot l USING(lotFk)
|
||||
WHERE p.outFk = vSelf
|
||||
AND (l.dated, p.lotFk) > (vDated, vLotFk)
|
||||
ORDER BY l.dated, p.lotFk;
|
||||
|
||||
DECLARE CONTINUE HANDLER FOR NOT FOUND
|
||||
SET vDone = TRUE;
|
||||
|
||||
SET vSupplied = 0;
|
||||
|
||||
OPEN vPicks;
|
||||
|
||||
myLoop: LOOP
|
||||
SET vDone = FALSE;
|
||||
FETCH vPicks INTO vPickFk, vPickLotFk, vPickQuantity;
|
||||
|
||||
IF vDone THEN
|
||||
LEAVE myLoop;
|
||||
END IF;
|
||||
|
||||
SET vPickGranted = LEAST(vRequested - vSupplied, vPickQuantity);
|
||||
SET vSupplied = vSupplied + vPickGranted;
|
||||
CALL buyPick_remove(vPickFk, vPickGranted, vPickQuantity);
|
||||
|
||||
UPDATE buyLot
|
||||
SET isSync = FALSE,
|
||||
available = available + vPickGranted
|
||||
WHERE lotFk = vPickLotFk;
|
||||
|
||||
IF vSupplied >= vRequested THEN
|
||||
LEAVE myLoop;
|
||||
END IF;
|
||||
END LOOP;
|
||||
|
||||
CLOSE vPicks;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -1,10 +1,10 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`outbound_sync`(vSelf INT)
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`buyOut_sync`(vSelf INT)
|
||||
BEGIN
|
||||
/**
|
||||
* Attaches a outbound with available inbounds.
|
||||
* Attaches an out with available lots.
|
||||
*
|
||||
* @param vSelf The outbound reference
|
||||
* @param vSelf The buyOut reference
|
||||
*/
|
||||
DECLARE vDated DATETIME;
|
||||
DECLARE vItem INT;
|
||||
|
@ -12,33 +12,33 @@ BEGIN
|
|||
DECLARE vLack INT;
|
||||
DECLARE vSupplied INT;
|
||||
DECLARE vSuppliedFromRequest INT;
|
||||
DECLARE vInboundFk INT;
|
||||
DECLARE vLotFk INT;
|
||||
DECLARE vAvailable INT;
|
||||
DECLARE vHasPicks BOOL;
|
||||
DECLARE vDone BOOL;
|
||||
|
||||
DECLARE vInbounds CURSOR FOR
|
||||
SELECT id, available, available < quantity
|
||||
FROM inbound
|
||||
DECLARE vBuyLots CURSOR FOR
|
||||
SELECT lotFk, available, available < quantity
|
||||
FROM buyLot
|
||||
WHERE warehouseFk = vWarehouse
|
||||
AND itemFk = vItem
|
||||
AND dated <= vDated
|
||||
AND (expired IS NULL OR expired > vDated)
|
||||
ORDER BY dated;
|
||||
ORDER BY dated, lotFk;
|
||||
|
||||
DECLARE CONTINUE HANDLER FOR NOT FOUND
|
||||
SET vDone = TRUE;
|
||||
|
||||
SELECT warehouseFk, itemFk, dated, lack
|
||||
INTO vWarehouse, vItem, vDated, vLack
|
||||
FROM outbound
|
||||
WHERE id = vSelf;
|
||||
FROM buyOut
|
||||
WHERE outFk = vSelf;
|
||||
|
||||
OPEN vInbounds;
|
||||
OPEN vBuyLots;
|
||||
|
||||
myLoop: LOOP
|
||||
SET vDone = FALSE;
|
||||
FETCH vInbounds INTO vInboundFk, vAvailable, vHasPicks;
|
||||
FETCH vBuyLots INTO vLotFk, vAvailable, vHasPicks;
|
||||
|
||||
IF vDone THEN
|
||||
LEAVE myLoop;
|
||||
|
@ -48,19 +48,19 @@ BEGIN
|
|||
|
||||
IF vSupplied > 0 THEN
|
||||
SET vLack = vLack - vSupplied;
|
||||
UPDATE inbound
|
||||
UPDATE buyLot
|
||||
SET available = available - vSupplied
|
||||
WHERE id = vInboundFk;
|
||||
WHERE lotFk = vLotFk;
|
||||
END IF;
|
||||
|
||||
IF vHasPicks AND vLack > 0 THEN
|
||||
CALL inbound_requestQuantity(vInboundFk, vLack, vDated, vSuppliedFromRequest);
|
||||
CALL buyLot_requestQuantity(vLotFk, vLack, vDated, vSelf, vSuppliedFromRequest);
|
||||
SET vSupplied = vSupplied + vSuppliedFromRequest;
|
||||
SET vLack = vLack - vSuppliedFromRequest;
|
||||
END IF;
|
||||
|
||||
IF vSupplied > 0 THEN
|
||||
CALL inbound_addPick(vInboundFk, vSelf, vSupplied);
|
||||
CALL buyPick_add(vLotFk, vSelf, vSupplied);
|
||||
END IF;
|
||||
|
||||
IF vLack = 0 THEN
|
||||
|
@ -68,11 +68,11 @@ BEGIN
|
|||
END IF;
|
||||
END LOOP;
|
||||
|
||||
CLOSE vInbounds;
|
||||
CLOSE vBuyLots;
|
||||
|
||||
UPDATE outbound
|
||||
UPDATE buyOut
|
||||
SET isSync = TRUE,
|
||||
lack = vLack
|
||||
WHERE id = vSelf;
|
||||
WHERE outFk = vSelf;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,15 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`buyPick_add`(
|
||||
vLotFk INT,
|
||||
vOutFk INT,
|
||||
vQuantity INT
|
||||
)
|
||||
BEGIN
|
||||
INSERT INTO buyPick
|
||||
SET lotFk = vLotFk,
|
||||
outFk = vOutFk,
|
||||
quantity = vQuantity
|
||||
ON DUPLICATE KEY UPDATE
|
||||
quantity = quantity + vQuantity;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,17 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`buyPick_remove`(
|
||||
vSelf INT,
|
||||
vQuantity INT,
|
||||
vTotalQuantity INT
|
||||
)
|
||||
BEGIN
|
||||
IF vQuantity < vTotalQuantity THEN
|
||||
UPDATE buyPick
|
||||
SET quantity = quantity - vQuantity
|
||||
WHERE id = vSelf;
|
||||
ELSE
|
||||
DELETE FROM buyPick
|
||||
WHERE id = vSelf;
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -1,16 +0,0 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`inbound_addPick`(
|
||||
vSelf INT,
|
||||
vOutboundFk INT,
|
||||
vQuantity INT
|
||||
)
|
||||
BEGIN
|
||||
INSERT INTO inboundPick
|
||||
SET
|
||||
inboundFk = vSelf,
|
||||
outboundFk = vOutboundFk,
|
||||
quantity = vQuantity
|
||||
ON DUPLICATE KEY UPDATE
|
||||
quantity = quantity + vQuantity;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -1,20 +0,0 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`inbound_removePick`(
|
||||
vSelf INT,
|
||||
vOutboundFk INT,
|
||||
vQuantity INT,
|
||||
vTotalQuantity INT
|
||||
)
|
||||
BEGIN
|
||||
IF vQuantity < vTotalQuantity THEN
|
||||
UPDATE inboundPick
|
||||
SET quantity = quantity - vQuantity
|
||||
WHERE inboundFk = vSelf
|
||||
AND outboundFk = vOutboundFk;
|
||||
ELSE
|
||||
DELETE FROM inboundPick
|
||||
WHERE inboundFk = vSelf
|
||||
AND outboundFk = vOutboundFk;
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -1,61 +0,0 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`inbound_requestQuantity`(
|
||||
vSelf INT,
|
||||
vRequested INT,
|
||||
vDated DATETIME,
|
||||
OUT vSupplied INT)
|
||||
BEGIN
|
||||
/**
|
||||
* Disassociates inbound picks after the given date until the
|
||||
* demanded quantity is satisfied.
|
||||
*
|
||||
* @param vSelf The inbound reference
|
||||
* @param vRequested The requested quantity
|
||||
* @param vDate The starting date for the associated outbounds
|
||||
* @param vSupplied The supplied quantity
|
||||
*/
|
||||
DECLARE vOutboundFk INT;
|
||||
DECLARE vPickQuantity INT;
|
||||
DECLARE vPickGranted INT;
|
||||
DECLARE vDone BOOL;
|
||||
|
||||
DECLARE vPicks CURSOR FOR
|
||||
SELECT p.outboundFk, p.quantity
|
||||
FROM inboundPick p
|
||||
JOIN outbound o ON o.id = p.outboundFk
|
||||
WHERE p.inboundFk = vSelf
|
||||
AND o.dated > vDated
|
||||
ORDER BY o.dated DESC, o.created DESC;
|
||||
|
||||
DECLARE CONTINUE HANDLER FOR NOT FOUND
|
||||
SET vDone = TRUE;
|
||||
|
||||
SET vSupplied = 0;
|
||||
|
||||
OPEN vPicks;
|
||||
|
||||
myLoop: LOOP
|
||||
SET vDone = FALSE;
|
||||
FETCH vPicks INTO vOutboundFk, vPickQuantity;
|
||||
|
||||
IF vDone THEN
|
||||
LEAVE myLoop;
|
||||
END IF;
|
||||
|
||||
SET vPickGranted = LEAST(vRequested - vSupplied, vPickQuantity);
|
||||
SET vSupplied = vSupplied + vPickGranted;
|
||||
CALL inbound_removePick(vSelf, vOutboundFk, vPickGranted, vPickQuantity);
|
||||
|
||||
UPDATE outbound
|
||||
SET isSync = FALSE,
|
||||
lack = lack + vPickGranted
|
||||
WHERE id = vOutboundFk;
|
||||
|
||||
IF vSupplied >= vRequested THEN
|
||||
LEAVE myLoop;
|
||||
END IF;
|
||||
END LOOP;
|
||||
|
||||
CLOSE vPicks;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -1,7 +0,0 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`log_clean`()
|
||||
BEGIN
|
||||
DELETE FROM inbound WHERE dated = vn.getInventoryDate();
|
||||
DELETE FROM outbound WHERE dated = vn.getInventoryDate();
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -1,19 +0,0 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`log_delete`(vTableName VARCHAR(255), vTableId INT)
|
||||
proc: BEGIN
|
||||
/**
|
||||
* Processes orphan transactions.
|
||||
*/
|
||||
IF vTableName NOT IN ('buy', 'sale', 'orderRow') THEN
|
||||
LEAVE proc;
|
||||
END IF;
|
||||
|
||||
DELETE FROM inbound
|
||||
WHERE tableName = vTableName COLLATE utf8_general_ci
|
||||
AND tableId = vTableId;
|
||||
|
||||
DELETE FROM outbound
|
||||
WHERE tableName = vTableName COLLATE utf8_general_ci
|
||||
AND tableId = vTableId;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -1,33 +0,0 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`log_refreshAll`()
|
||||
BEGIN
|
||||
/**
|
||||
* Recalculates the entire cache. It takes a considerable time,
|
||||
* please avoid calls to this procedure from commonly used operations.
|
||||
*/
|
||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||
BEGIN
|
||||
DO RELEASE_LOCK('stock.log_sync');
|
||||
RESIGNAL;
|
||||
END;
|
||||
|
||||
IF !GET_LOCK('stock.log_sync', 30) THEN
|
||||
CALL util.throw('Lock timeout exceeded');
|
||||
END IF;
|
||||
|
||||
TRUNCATE TABLE stock.`log`;
|
||||
TRUNCATE TABLE stock.`inbound`;
|
||||
TRUNCATE TABLE stock.`inboundPick`;
|
||||
TRUNCATE TABLE stock.`outbound`;
|
||||
TRUNCATE TABLE stock.`visible`;
|
||||
|
||||
CALL log_refreshSale(NULL, NULL);
|
||||
CALL log_refreshBuy(NULL, NULL);
|
||||
CALL log_refreshOrder(NULL, NULL);
|
||||
|
||||
UPDATE outbound SET isSync = TRUE;
|
||||
CALL log_sync(TRUE);
|
||||
|
||||
DO RELEASE_LOCK('stock.log_sync');
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -1,73 +0,0 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`log_refreshBuy`(
|
||||
`vTableName` VARCHAR(255),
|
||||
`vTableId` INT)
|
||||
BEGIN
|
||||
DROP TEMPORARY TABLE IF EXISTS tValues;
|
||||
CREATE TEMPORARY TABLE tValues
|
||||
ENGINE = MEMORY
|
||||
SELECT b.id buyFk,
|
||||
e.id entryFk,
|
||||
t.id travelFk,
|
||||
b.itemFk,
|
||||
t.isRaid,
|
||||
ADDTIME(t.shipped,
|
||||
IFNULL(t.shipmentHour, '00:00:00')) shipped,
|
||||
t.warehouseOutFk,
|
||||
t.isDelivered,
|
||||
ADDTIME(t.landed,
|
||||
IFNULL(t.landingHour, '00:00:00')) landed,
|
||||
t.warehouseInFk,
|
||||
t.isReceived,
|
||||
tp.life,
|
||||
ABS(b.quantity) quantity,
|
||||
b.created,
|
||||
b.quantity > 0 isIn,
|
||||
t.shipped < vn.getInventoryDate() lessThanInventory
|
||||
FROM vn.buy b
|
||||
JOIN vn.entry e ON e.id = b.entryFk
|
||||
JOIN vn.travel t ON t.id = e.travelFk
|
||||
JOIN vn.item i ON i.id = b.itemFk
|
||||
JOIN vn.itemType tp ON tp.id = i.typeFk
|
||||
WHERE (
|
||||
vTableId IS NULL
|
||||
OR (vTableName = 'travel' AND t.id = vTableId)
|
||||
OR (vTableName = 'entry' AND e.id = vTableId)
|
||||
OR (vTableName = 'buy' AND b.id = vTableId)
|
||||
)
|
||||
AND t.landed >= vn.getInventoryDate()
|
||||
AND b.quantity != 0;
|
||||
|
||||
REPLACE INTO inbound (
|
||||
tableName, tableId, warehouseFk, dated,
|
||||
itemFk, expired, quantity, isPicked
|
||||
)
|
||||
SELECT 'buy',
|
||||
buyFk,
|
||||
IF(isIn, warehouseInFk, warehouseOutFk),
|
||||
@dated := IF(isIn, landed, shipped),
|
||||
itemFk,
|
||||
TIMESTAMPADD(DAY, life, @dated),
|
||||
quantity,
|
||||
IF(isIn, isReceived, isDelivered) AND NOT isRaid
|
||||
FROM tValues
|
||||
WHERE isIn OR !lessThanInventory;
|
||||
|
||||
REPLACE INTO outbound (
|
||||
tableName, tableId, warehouseFk, dated,
|
||||
itemFk, created, quantity, isPicked
|
||||
)
|
||||
SELECT 'buy',
|
||||
buyFk,
|
||||
IF(isIn, warehouseOutFk, warehouseInFk),
|
||||
IF(isIn, shipped, landed),
|
||||
itemFk,
|
||||
created,
|
||||
quantity,
|
||||
IF(isIn, isDelivered, isReceived) AND NOT isRaid
|
||||
FROM tValues
|
||||
WHERE !isIn OR !lessThanInventory;
|
||||
|
||||
DROP TEMPORARY TABLE tValues;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -1,47 +0,0 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`log_refreshOrder`(
|
||||
`vTableName` VARCHAR(255),
|
||||
`vTableId` INT)
|
||||
BEGIN
|
||||
DECLARE vExpireTime INT DEFAULT 20;
|
||||
DECLARE vExpired DATETIME DEFAULT TIMESTAMPADD(MINUTE, -vExpireTime, util.VN_NOW());
|
||||
|
||||
DROP TEMPORARY TABLE IF EXISTS tValues;
|
||||
CREATE TEMPORARY TABLE tValues
|
||||
ENGINE = MEMORY
|
||||
SELECT
|
||||
r.id rowFk,
|
||||
r.itemFk,
|
||||
r.warehouseFk,
|
||||
r.shipment shipped,
|
||||
r.amount quantity,
|
||||
r.created
|
||||
FROM hedera.orderRow r
|
||||
JOIN hedera.`order` o ON o.id = r.orderFk
|
||||
WHERE (
|
||||
vTableId IS NULL
|
||||
OR (vTableName = 'order' AND o.id = vTableId)
|
||||
OR (vTableName = 'orderRow' AND r.id = vTableId)
|
||||
)
|
||||
AND !o.confirmed
|
||||
AND r.shipment >= vn.getInventoryDate()
|
||||
AND r.created >= vExpired
|
||||
AND r.amount != 0;
|
||||
|
||||
REPLACE INTO outbound (
|
||||
tableName, tableId, warehouseFk, dated,
|
||||
itemFk, created, expired, quantity
|
||||
)
|
||||
SELECT 'orderRow',
|
||||
rowFk,
|
||||
warehouseFk,
|
||||
shipped,
|
||||
itemFk,
|
||||
created,
|
||||
TIMESTAMPADD(MINUTE, vExpireTime, created),
|
||||
quantity
|
||||
FROM tValues;
|
||||
|
||||
DROP TEMPORARY TABLE tValues;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -1,66 +0,0 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`log_refreshSale`(
|
||||
`vTableName` VARCHAR(255),
|
||||
`vTableId` INT)
|
||||
BEGIN
|
||||
DROP TEMPORARY TABLE IF EXISTS tValues;
|
||||
CREATE TEMPORARY TABLE tValues
|
||||
ENGINE = MEMORY
|
||||
SELECT
|
||||
m.id saleFk,
|
||||
m.ticketFk,
|
||||
m.itemFk,
|
||||
t.warehouseFk,
|
||||
t.shipped,
|
||||
ABS(m.quantity) quantity,
|
||||
m.created,
|
||||
TIMESTAMPADD(DAY, tp.life, t.shipped) expired,
|
||||
m.quantity < 0 isIn,
|
||||
m.isPicked OR s.alertLevel > al.id isPicked
|
||||
FROM vn.sale m
|
||||
JOIN vn.ticket t ON t.id = m.ticketFk
|
||||
JOIN vn.ticketState s ON s.ticketFk = t.id
|
||||
JOIN vn.item i ON i.id = m.itemFk
|
||||
JOIN vn.itemType tp ON tp.id = i.typeFk
|
||||
JOIN vn.alertLevel al ON al.code = 'ON_PREPARATION'
|
||||
WHERE (
|
||||
vTableId IS NULL
|
||||
OR (vTableName = 'ticket' AND t.id = vTableId)
|
||||
OR (vTableName = 'sale' AND m.id = vTableId)
|
||||
)
|
||||
AND t.shipped >= vn.getInventoryDate()
|
||||
AND m.quantity != 0;
|
||||
|
||||
REPLACE INTO inbound (
|
||||
tableName, tableId, warehouseFk, dated,
|
||||
itemFk, expired, quantity, isPicked
|
||||
)
|
||||
SELECT 'sale',
|
||||
saleFk,
|
||||
warehouseFk,
|
||||
shipped,
|
||||
itemFk,
|
||||
expired,
|
||||
quantity,
|
||||
isPicked
|
||||
FROM tValues
|
||||
WHERE isIn;
|
||||
|
||||
REPLACE INTO outbound (
|
||||
tableName, tableId, warehouseFk, dated,
|
||||
itemFk, created, quantity, isPicked
|
||||
)
|
||||
SELECT 'sale',
|
||||
saleFk,
|
||||
warehouseFk,
|
||||
shipped,
|
||||
itemFk,
|
||||
created,
|
||||
quantity,
|
||||
isPicked
|
||||
FROM tValues
|
||||
WHERE !isIn;
|
||||
|
||||
DROP TEMPORARY TABLE tValues;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -1,123 +0,0 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`log_sync`(vSync BOOL)
|
||||
proc: BEGIN
|
||||
DECLARE vDone BOOL;
|
||||
DECLARE vLogId INT;
|
||||
DECLARE vHasPendingSync BOOL;
|
||||
DECLARE vOperation VARCHAR(255);
|
||||
DECLARE vTableName VARCHAR(255);
|
||||
DECLARE vTableId VARCHAR(255);
|
||||
DECLARE vInboundFk INT;
|
||||
DECLARE vOutboundFk INT;
|
||||
|
||||
DECLARE cInbound CURSOR FOR
|
||||
SELECT id FROM inbound
|
||||
WHERE !isSync
|
||||
ORDER BY dated;
|
||||
|
||||
DECLARE cOutbound CURSOR FOR
|
||||
SELECT id FROM outbound
|
||||
WHERE !isSync
|
||||
ORDER BY dated;
|
||||
|
||||
DECLARE CONTINUE HANDLER FOR NOT FOUND
|
||||
SET vDone = TRUE;
|
||||
|
||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||
BEGIN
|
||||
ROLLBACK;
|
||||
RESIGNAL;
|
||||
END;
|
||||
|
||||
-- Applies changes
|
||||
|
||||
opsLoop: LOOP
|
||||
START TRANSACTION;
|
||||
|
||||
SET vDone = FALSE;
|
||||
SELECT id, operation, tableName, tableId
|
||||
INTO vLogId, vOperation, vTableName, vTableId
|
||||
FROM `log`
|
||||
ORDER BY id LIMIT 1
|
||||
FOR UPDATE;
|
||||
|
||||
IF vDone THEN
|
||||
COMMIT;
|
||||
LEAVE opsLoop;
|
||||
END IF;
|
||||
|
||||
CALL log_delete(vTableName, vTableId);
|
||||
|
||||
IF vOperation = 'insert' THEN
|
||||
IF vTableName IN ('travel', 'entry', 'buy') THEN
|
||||
CALL log_refreshBuy(vTableName, vTableId);
|
||||
ELSEIF vTableName IN ('ticket', 'sale') THEN
|
||||
CALL log_refreshSale(vTableName, vTableId);
|
||||
ELSEIF vTableName IN ('order', 'orderRow') THEN
|
||||
CALL log_refreshOrder(vTableName, vTableId);
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
DELETE FROM `log` WHERE id = vLogId;
|
||||
SET vSync = TRUE;
|
||||
|
||||
COMMIT;
|
||||
END LOOP;
|
||||
|
||||
IF !vSync THEN
|
||||
LEAVE proc;
|
||||
END IF;
|
||||
|
||||
-- Deletes expired outbounds
|
||||
|
||||
DELETE FROM outbound WHERE expired <= util.VN_NOW();
|
||||
|
||||
-- Attaches desync inbounds
|
||||
|
||||
REPEAT
|
||||
OPEN cInbound;
|
||||
SET vHasPendingSync = FALSE;
|
||||
|
||||
inboundLoop: LOOP
|
||||
SET vDone = FALSE;
|
||||
FETCH cInbound INTO vInboundFk;
|
||||
|
||||
IF vDone THEN
|
||||
LEAVE inboundLoop;
|
||||
END IF;
|
||||
|
||||
START TRANSACTION;
|
||||
CALL inbound_sync(vInboundFk);
|
||||
COMMIT;
|
||||
|
||||
SET vHasPendingSync = TRUE;
|
||||
END LOOP;
|
||||
|
||||
CLOSE cInbound;
|
||||
UNTIL !vHasPendingSync END REPEAT;
|
||||
|
||||
-- Attaches desync outbounds
|
||||
|
||||
REPEAT
|
||||
OPEN cOutbound;
|
||||
SET vHasPendingSync = FALSE;
|
||||
|
||||
outboundLoop: LOOP
|
||||
SET vDone = FALSE;
|
||||
FETCH cOutbound INTO vOutboundFk;
|
||||
|
||||
IF vDone THEN
|
||||
LEAVE outboundLoop;
|
||||
END IF;
|
||||
|
||||
START TRANSACTION;
|
||||
CALL outbound_sync(vOutboundFk);
|
||||
COMMIT;
|
||||
|
||||
SET vHasPendingSync = TRUE;
|
||||
END LOOP;
|
||||
|
||||
CLOSE cOutbound;
|
||||
UNTIL !vHasPendingSync END REPEAT;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -1,16 +0,0 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`log_syncNoWait`()
|
||||
BEGIN
|
||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||
BEGIN
|
||||
DO RELEASE_LOCK('stock.log_sync');
|
||||
RESIGNAL;
|
||||
END;
|
||||
|
||||
IF GET_LOCK('stock.log_sync', 0) THEN
|
||||
CALL log_sync(FALSE);
|
||||
END IF;
|
||||
|
||||
DO RELEASE_LOCK('stock.log_sync');
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -1,61 +0,0 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`outbound_requestQuantity`(
|
||||
vSelf INT,
|
||||
vRequested INT,
|
||||
vDated DATETIME,
|
||||
OUT vSupplied INT)
|
||||
BEGIN
|
||||
/**
|
||||
* Disassociates outbound picks after the given date until the
|
||||
* demanded quantity is satisfied.
|
||||
*
|
||||
* @param vSelf The outbound reference
|
||||
* @param vRequested The requested quantity
|
||||
* @param vDate The starting date for the associated inbounds
|
||||
* @param vSupplied The supplied quantity
|
||||
*/
|
||||
DECLARE vInboundFk INT;
|
||||
DECLARE vPickQuantity INT;
|
||||
DECLARE vPickGranted INT;
|
||||
DECLARE vDone BOOL;
|
||||
|
||||
DECLARE vPicks CURSOR FOR
|
||||
SELECT p.inboundFk, p.quantity
|
||||
FROM inboundPick p
|
||||
JOIN inbound i ON i.id = p.inboundFk
|
||||
WHERE p.outboundFk = vSelf
|
||||
AND i.dated > vDated
|
||||
ORDER BY i.dated DESC;
|
||||
|
||||
DECLARE CONTINUE HANDLER FOR NOT FOUND
|
||||
SET vDone = TRUE;
|
||||
|
||||
SET vSupplied = 0;
|
||||
|
||||
OPEN vPicks;
|
||||
|
||||
myLoop: LOOP
|
||||
SET vDone = FALSE;
|
||||
FETCH vPicks INTO vInboundFk, vPickQuantity;
|
||||
|
||||
IF vDone THEN
|
||||
LEAVE myLoop;
|
||||
END IF;
|
||||
|
||||
SET vPickGranted = LEAST(vRequested - vSupplied, vPickQuantity);
|
||||
SET vSupplied = vSupplied + vPickGranted;
|
||||
CALL inbound_removePick(vInboundFk, vSelf, vPickGranted, vPickQuantity);
|
||||
|
||||
UPDATE inbound
|
||||
SET isSync = FALSE,
|
||||
available = available + vPickGranted
|
||||
WHERE id = vInboundFk;
|
||||
|
||||
IF vSupplied >= vRequested THEN
|
||||
LEAVE myLoop;
|
||||
END IF;
|
||||
END LOOP;
|
||||
|
||||
CLOSE vPicks;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,32 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`stock_clean`()
|
||||
BEGIN
|
||||
/**
|
||||
* Cleans current time dependent cache records.
|
||||
*/
|
||||
DECLARE vExpired DATETIME;
|
||||
DECLARE vAliveDate DATE;
|
||||
|
||||
-- Expired order reserves
|
||||
|
||||
SELECT SUBTIME(util.VN_NOW(), reserveTime)
|
||||
INTO vExpired
|
||||
FROM hedera.orderConfig LIMIT 1;
|
||||
|
||||
UPDATE hedera.order
|
||||
SET isReserved = FALSE
|
||||
WHERE created < vExpired
|
||||
AND isReserved;
|
||||
|
||||
-- Frozen old sales
|
||||
|
||||
SELECT util.VN_CURDATE() - INTERVAL saleLife DAY
|
||||
INTO vAliveDate
|
||||
FROM config LIMIT 1;
|
||||
|
||||
UPDATE vn.ticket
|
||||
SET isAlive = FALSE
|
||||
WHERE shipped < vAliveDate
|
||||
AND isAlive;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,87 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`stock_refreshAll`()
|
||||
BEGIN
|
||||
/**
|
||||
* Recalculates the entire cache. It takes a considerable time,
|
||||
* please avoid calls to this procedure from commonly used operations.
|
||||
*/
|
||||
DECLARE vDone BOOL;
|
||||
DECLARE vId INT;
|
||||
|
||||
DECLARE vBuys CURSOR FOR
|
||||
SELECT lotFk FROM vn.buy WHERE isAlive;
|
||||
|
||||
DECLARE vTickets CURSOR FOR
|
||||
SELECT id FROM vn.ticket WHERE isAlive;
|
||||
|
||||
DECLARE vOrders CURSOR FOR
|
||||
SELECT lotFk FROM hedera.orderRow WHERE isReserved;
|
||||
|
||||
DECLARE CONTINUE HANDLER FOR NOT FOUND
|
||||
SET vDone = TRUE;
|
||||
|
||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||
BEGIN
|
||||
DO RELEASE_LOCK('stock.stock_refreshAll');
|
||||
RESIGNAL;
|
||||
END;
|
||||
|
||||
IF NOT GET_LOCK('stock.stock_refreshAll', 30) THEN
|
||||
CALL util.throw('Lock timeout exceeded');
|
||||
END IF;
|
||||
|
||||
-- Prune cache
|
||||
|
||||
DELETE p FROM buyPick p JOIN buyLot l USING(lotFk);
|
||||
TRUNCATE TABLE buyLot;
|
||||
TRUNCATE TABLE buyOut;
|
||||
|
||||
-- Populate cache
|
||||
|
||||
OPEN vBuys;
|
||||
buyLoop: LOOP
|
||||
SET vDone = FALSE;
|
||||
FETCH vBuys INTO vId;
|
||||
|
||||
IF vDone THEN
|
||||
LEAVE buyLoop;
|
||||
END IF;
|
||||
|
||||
CALL buyOut_refreshBuy('lot', vId);
|
||||
END LOOP;
|
||||
CLOSE vBuys;
|
||||
|
||||
OPEN vOrders;
|
||||
orderLoop: LOOP
|
||||
SET vDone = FALSE;
|
||||
FETCH vOrders INTO vId;
|
||||
|
||||
IF vDone THEN
|
||||
LEAVE orderLoop;
|
||||
END IF;
|
||||
|
||||
CALL buyOut_refreshOrder('lot', vId);
|
||||
END LOOP;
|
||||
CLOSE vOrders;
|
||||
|
||||
OPEN vTickets;
|
||||
saleLoop: LOOP
|
||||
SET vDone = FALSE;
|
||||
FETCH vTickets INTO vId;
|
||||
|
||||
IF vDone THEN
|
||||
LEAVE saleLoop;
|
||||
END IF;
|
||||
|
||||
CALL buyOut_refreshSale('ticket', vId);
|
||||
END LOOP;
|
||||
CLOSE vTickets;
|
||||
|
||||
-- Synchronize
|
||||
|
||||
UPDATE buyOut SET isSync = TRUE;
|
||||
CALL stock_sync;
|
||||
|
||||
DO RELEASE_LOCK('stock.stock_refreshAll');
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,34 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`stock_sync`()
|
||||
BEGIN
|
||||
/**
|
||||
* Synchronizes all out of sync items. It can be called in parallel
|
||||
* since it generates a lock for each item (and warehouse) synchronization
|
||||
* process, see stock_syncItem().
|
||||
*/
|
||||
DECLARE vDone BOOL;
|
||||
DECLARE vWarehouseFk INT;
|
||||
DECLARE vItemFk INT;
|
||||
|
||||
DECLARE vItems CURSOR FOR
|
||||
SELECT itemFk, warehouseFk FROM buyLot WHERE NOT isSync
|
||||
UNION
|
||||
SELECT itemFk, warehouseFk FROM buyOut WHERE NOT isSync;
|
||||
|
||||
DECLARE CONTINUE HANDLER FOR NOT FOUND
|
||||
SET vDone = TRUE;
|
||||
|
||||
OPEN vItems;
|
||||
itemLoop: LOOP
|
||||
SET vDone = FALSE;
|
||||
FETCH vItems INTO vItemFk, vWarehouseFk;
|
||||
|
||||
IF vDone THEN
|
||||
LEAVE itemLoop;
|
||||
END IF;
|
||||
|
||||
CALL stock_syncItem(vItemFk, vWarehouseFk, 0);
|
||||
END LOOP;
|
||||
CLOSE vItems;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,88 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`stock_syncItem`(
|
||||
vItemFk INT,
|
||||
vWarehouseFk INT,
|
||||
vWait INT)
|
||||
myProc: BEGIN
|
||||
/**
|
||||
* Synchronizes out of sync item. It generates a lock for each item and
|
||||
* warehouse synchronization process.
|
||||
*
|
||||
* @param vItemFk The item id
|
||||
* @param vWarehouseFk The item warehouse id
|
||||
* @param vWait Maximum waiting time, see GET_LOCK()
|
||||
*/
|
||||
DECLARE vDone BOOL;
|
||||
DECLARE vHasPendingSync BOOL;
|
||||
DECLARE vLotFk INT;
|
||||
DECLARE vOutFk INT;
|
||||
DECLARE vLock VARCHAR(255);
|
||||
|
||||
DECLARE vLots CURSOR FOR
|
||||
SELECT lotFk FROM buyLot
|
||||
WHERE NOT isSync
|
||||
AND (itemFk, warehouseFk) = (vItemFk, vWarehouseFk)
|
||||
ORDER BY dated, lotFk;
|
||||
|
||||
DECLARE vOuts CURSOR FOR
|
||||
SELECT outFk FROM buyOut
|
||||
WHERE NOT isSync
|
||||
AND (itemFk, warehouseFk) = (vItemFk, vWarehouseFk)
|
||||
ORDER BY dated, created, outFk;
|
||||
|
||||
DECLARE CONTINUE HANDLER FOR NOT FOUND
|
||||
SET vDone = TRUE;
|
||||
|
||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||
BEGIN
|
||||
DO RELEASE_LOCK(vLock);
|
||||
ROLLBACK;
|
||||
RESIGNAL;
|
||||
END;
|
||||
|
||||
SET vLock = CONCAT_WS('/', 'stock.stock_syncItem', vWarehouseFk, vItemFk);
|
||||
|
||||
IF NOT GET_LOCK(vLock, vWait) THEN
|
||||
LEAVE myProc;
|
||||
END IF;
|
||||
|
||||
REPEAT
|
||||
SET vHasPendingSync = FALSE;
|
||||
|
||||
OPEN vLots;
|
||||
lotLoop: LOOP
|
||||
SET vDone = FALSE;
|
||||
FETCH vLots INTO vLotFk;
|
||||
|
||||
IF vDone THEN
|
||||
LEAVE lotLoop;
|
||||
END IF;
|
||||
|
||||
START TRANSACTION;
|
||||
CALL buyLot_sync(vLotFk);
|
||||
COMMIT;
|
||||
|
||||
SET vHasPendingSync = TRUE;
|
||||
END LOOP;
|
||||
CLOSE vLots;
|
||||
|
||||
OPEN vOuts;
|
||||
outLoop: LOOP
|
||||
SET vDone = FALSE;
|
||||
FETCH vOuts INTO vOutFk;
|
||||
|
||||
IF vDone THEN
|
||||
LEAVE outLoop;
|
||||
END IF;
|
||||
|
||||
START TRANSACTION;
|
||||
CALL buyOut_sync(vOutFk);
|
||||
COMMIT;
|
||||
|
||||
SET vHasPendingSync = TRUE;
|
||||
END LOOP;
|
||||
CLOSE vOuts;
|
||||
|
||||
UNTIL NOT vHasPendingSync END REPEAT;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -1,20 +0,0 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `stock`.`visible_log`(
|
||||
vIsPicked BOOL,
|
||||
vWarehouseFk INT,
|
||||
vItemFk INT,
|
||||
vQuantity INT
|
||||
)
|
||||
proc: BEGIN
|
||||
IF !vIsPicked THEN
|
||||
LEAVE proc;
|
||||
END IF;
|
||||
|
||||
INSERT INTO visible
|
||||
SET itemFk = vItemFk,
|
||||
warehouseFk = vWarehouseFk,
|
||||
quantity = vQuantity
|
||||
ON DUPLICATE KEY UPDATE
|
||||
quantity = quantity + VALUES(quantity);
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -1,22 +0,0 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `stock`.`inbound_afterDelete`
|
||||
AFTER DELETE ON `inbound`
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
UPDATE outbound o
|
||||
JOIN inboundPick ou ON ou.outboundFk = o.id
|
||||
SET o.lack = o.lack + ou.quantity,
|
||||
o.isSync = FALSE
|
||||
WHERE ou.inboundFk = OLD.id;
|
||||
|
||||
DELETE FROM inboundPick
|
||||
WHERE inboundFk = OLD.id;
|
||||
|
||||
CALL visible_log(
|
||||
OLD.isPicked,
|
||||
OLD.warehouseFk,
|
||||
OLD.itemFk,
|
||||
-OLD.quantity
|
||||
);
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -1,15 +0,0 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `stock`.`inbound_beforeInsert`
|
||||
BEFORE INSERT ON `inbound`
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
SET NEW.isPicked = NEW.isPicked OR NEW.dated < util.VN_CURDATE();
|
||||
|
||||
CALL visible_log(
|
||||
NEW.isPicked,
|
||||
NEW.warehouseFk,
|
||||
NEW.itemFk,
|
||||
NEW.quantity
|
||||
);
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -1,22 +0,0 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `stock`.`outbound_afterDelete`
|
||||
AFTER DELETE ON `outbound`
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
UPDATE inbound i
|
||||
JOIN inboundPick ou ON ou.inboundFk = i.id
|
||||
SET i.available = i.available + ou.quantity,
|
||||
i.isSync = FALSE
|
||||
WHERE ou.outboundFk = OLD.id;
|
||||
|
||||
DELETE FROM inboundPick
|
||||
WHERE outboundFk = OLD.id;
|
||||
|
||||
CALL visible_log(
|
||||
OLD.isPicked,
|
||||
OLD.warehouseFk,
|
||||
OLD.itemFk,
|
||||
OLD.quantity
|
||||
);
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -1,16 +0,0 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `stock`.`outbound_beforeInsert`
|
||||
BEFORE INSERT ON `outbound`
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
SET NEW.lack = NEW.quantity;
|
||||
SET NEW.isPicked = NEW.isPicked OR NEW.dated < util.VN_CURDATE();
|
||||
|
||||
CALL visible_log(
|
||||
NEW.isPicked,
|
||||
NEW.warehouseFk,
|
||||
NEW.itemFk,
|
||||
-NEW.quantity
|
||||
);
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,15 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` FUNCTION `vn`.`item_getLife`(vItemFk INT)
|
||||
RETURNS INT
|
||||
NOT DETERMINISTIC
|
||||
BEGIN
|
||||
DECLARE vLife INT;
|
||||
|
||||
SELECT t.life INTO vLife
|
||||
FROM itemType t
|
||||
JOIN item i ON i.typeFk = t.id
|
||||
WHERE i.id = vItemFk;
|
||||
|
||||
RETURN vLife;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -104,6 +104,24 @@ BEGIN
|
|||
LEFT JOIN agencyModeItemType ait
|
||||
ON ait.agencyModeFk = vAgencyModeFk
|
||||
AND ait.itemTypeFk = itt.id
|
||||
LEFT JOIN (
|
||||
SELECT i.id
|
||||
FROM item i
|
||||
JOIN priceDelta pd
|
||||
ON pd.itemTypeFk = i.typeFk
|
||||
AND (pd.minSize IS NULL OR pd.minSize <= i.`size`)
|
||||
AND (pd.maxSize IS NULL OR pd.maxSize >= i.`size`)
|
||||
AND (pd.inkFk IS NULL OR pd.inkFk = i.inkFk)
|
||||
AND (pd.originFk IS NULL OR pd.originFk = i.originFk)
|
||||
AND (pd.producerFk IS NULL OR pd.producerFk = i.producerFk)
|
||||
AND (pd.warehouseFk IS NULL OR pd.warehouseFk = vWarehouseFk)
|
||||
LEFT JOIN zoneGeo zg ON zg.id = pd.zoneGeoFk
|
||||
LEFT JOIN zoneGeo zg2 ON zg2.id = address_getGeo(vAddressFk)
|
||||
WHERE (pd.fromDated IS NULL OR pd.fromDated <= vShipped)
|
||||
AND (pd.toDated IS NULL OR pd.toDated >= vShipped)
|
||||
AND (pd.zoneGeoFk IS NULL OR zg2.lft BETWEEN zg.lft AND zg.rgt)
|
||||
AND pd.isHidden
|
||||
GROUP BY i.id) pd ON pd.id = i.itemFk
|
||||
WHERE a.calc_id = vAvailableCalc
|
||||
AND a.available > 0
|
||||
AND (ag.isAnyVolumeAllowed OR NOT itt.isUnconventionalSize)
|
||||
|
@ -113,7 +131,9 @@ BEGIN
|
|||
it.size <= z.itemMaxSize OR z.itemMaxSize IS NULL))
|
||||
AND cit.id IS NULL
|
||||
AND zit.id IS NULL
|
||||
AND ait.id IS NULL;
|
||||
AND ait.id IS NULL
|
||||
AND pd.id IS NULL
|
||||
;
|
||||
|
||||
DROP TEMPORARY TABLE tmp.buyUltimate;
|
||||
|
||||
|
|
|
@ -25,20 +25,23 @@ BEGIN
|
|||
DECLARE vPrintQueueFk INT;
|
||||
DECLARE vReportSize VARCHAR(255);
|
||||
DECLARE vIsThePrinterReal INT;
|
||||
DECLARE vPrinteSize VARCHAR(255);
|
||||
DECLARE vPrinterSize VARCHAR(255);
|
||||
DECLARE vPriorityFk INT;
|
||||
DECLARE vReportFk INT;
|
||||
DECLARE vTx BOOLEAN DEFAULT NOT @@in_transaction;
|
||||
|
||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||
BEGIN
|
||||
ROLLBACK;
|
||||
CALL util.tx_rollback(vTx);
|
||||
RESIGNAL;
|
||||
END;
|
||||
|
||||
|
||||
SELECT id, paperSizeFk INTO vReportFk, vReportSize
|
||||
FROM report
|
||||
WHERE name = vReportName;
|
||||
|
||||
SELECT id, paperSizeFk INTO vIsThePrinterReal, vPrinteSize
|
||||
SELECT id, paperSizeFk INTO vIsThePrinterReal, vPrinterSize
|
||||
FROM printer
|
||||
WHERE id = vPrinterFk;
|
||||
|
||||
|
@ -54,11 +57,10 @@ BEGIN
|
|||
CALL util.throw('reportNotExists');
|
||||
END IF;
|
||||
|
||||
IF vReportSize <> vPrinteSize THEN
|
||||
IF vReportSize <> vPrinterSize THEN
|
||||
CALL util.throw('incorrectSize');
|
||||
END IF;
|
||||
|
||||
START TRANSACTION;
|
||||
CALL util.tx_start(vTx);
|
||||
INSERT INTO printQueue
|
||||
SET printerFk = vPrinterFk,
|
||||
priorityFk = vPriorityFk,
|
||||
|
@ -78,6 +80,7 @@ BEGIN
|
|||
|
||||
SET vI = vI + 1;
|
||||
END WHILE;
|
||||
COMMIT;
|
||||
|
||||
CALL util.tx_commit(vTx);
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
|
|
@ -22,6 +22,10 @@ trig: BEGIN
|
|||
|
||||
SET NEW.editorFk = account.myUser_getId();
|
||||
|
||||
IF NEW.life IS NULL THEN
|
||||
SET NEW.life = item_getLife(NEW.itemFk);
|
||||
END IF;
|
||||
|
||||
SELECT it.workerFk INTO vBuyerFk
|
||||
FROM item i
|
||||
JOIN itemType it ON it.id = i.typeFk
|
||||
|
|
|
@ -25,6 +25,10 @@ trig:BEGIN
|
|||
|
||||
SET NEW.editorFk = account.myUser_getId();
|
||||
|
||||
IF NOT (NEW.itemFk <=> OLD.itemFk) AND NEW.life <=> OLD.life THEN
|
||||
SET NEW.life = item_getLife(NEW.itemFk);
|
||||
END IF;
|
||||
|
||||
SELECT defaultEntry INTO vDefaultEntry
|
||||
FROM entryConfig;
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
DROP TABLE stock.log;
|
|
@ -0,0 +1,16 @@
|
|||
DROP TABLE IF EXISTS stock.inboundPick;
|
||||
|
||||
CREATE TABLE stock.buyPick (
|
||||
id INT UNSIGNED auto_increment NOT NULL,
|
||||
lotFk INT(11) NOT NULL
|
||||
COMMENT 'Buy id',
|
||||
outFk INT(11) NOT NULL
|
||||
COMMENT 'Out id',
|
||||
quantity INT UNSIGNED NOT NULL
|
||||
COMMENT 'Picked quantity',
|
||||
PRIMARY KEY (id),
|
||||
CONSTRAINT buyPick_unique UNIQUE KEY (lotFk, outFk)
|
||||
)
|
||||
ENGINE=InnoDB
|
||||
DEFAULT CHARSET=utf8mb3
|
||||
COLLATE=utf8mb3_unicode_ci;
|
|
@ -0,0 +1,6 @@
|
|||
ALTER TABLE vn.buy
|
||||
ADD life INT UNSIGNED NULL
|
||||
COMMENT 'Lot life expressed in days',
|
||||
ADD isAlive BOOL NOT NULL DEFAULT TRUE
|
||||
COMMENT 'Whether it is alive',
|
||||
ADD INDEX(isAlive);
|
|
@ -0,0 +1,4 @@
|
|||
ALTER TABLE hedera.orderRow
|
||||
ADD isReserved BOOL NOT NULL DEFAULT TRUE
|
||||
COMMENT 'Whether has an available reservation',
|
||||
ADD INDEX(isReserved);
|
|
@ -0,0 +1,4 @@
|
|||
ALTER TABLE vn.ticket
|
||||
ADD isAlive BOOL NOT NULL DEFAULT TRUE
|
||||
COMMENT 'Whether it is alive',
|
||||
ADD INDEX(isAlive);
|
|
@ -0,0 +1,10 @@
|
|||
RENAME TABLE IF EXISTS stock.inbound TO stock.buyLot;
|
||||
|
||||
ALTER TABLE stock.buyLot
|
||||
DROP KEY source,
|
||||
DROP COLUMN tableName,
|
||||
CHANGE tableId lotFk int(10) unsigned NOT NULL,
|
||||
CHANGE isSync isSync tinyint(4) NOT NULL AFTER lotFk,
|
||||
DROP PRIMARY KEY,
|
||||
DROP COLUMN id,
|
||||
ADD PRIMARY KEY (lotFk);
|
|
@ -0,0 +1 @@
|
|||
DROP TABLE stock.visible;
|
|
@ -0,0 +1,10 @@
|
|||
RENAME TABLE IF EXISTS stock.outbound TO stock.buyOut;
|
||||
|
||||
ALTER TABLE stock.buyOut
|
||||
CHANGE IF EXISTS tableName source enum('buy','sale','orderRow') CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL,
|
||||
CHANGE IF EXISTS id outFk int(10) UNSIGNED NOT NULL,
|
||||
DROP INDEX IF EXISTS source,
|
||||
DROP COLUMN IF EXISTS tableId,
|
||||
DROP INDEX IF EXISTS expired,
|
||||
DROP COLUMN IF EXISTS expired,
|
||||
ADD INDEX IF NOT EXISTS (source);
|
|
@ -0,0 +1,8 @@
|
|||
CREATE TABLE stock.config (
|
||||
id INT UNSIGNED auto_increment NOT NULL,
|
||||
saleLife INT UNSIGNED NOT NULL COMMENT 'Maximum sales cache lifetime in days',
|
||||
CONSTRAINT config_pk PRIMARY KEY (id)
|
||||
)
|
||||
ENGINE=InnoDB
|
||||
DEFAULT CHARSET=utf8mb3
|
||||
COLLATE=utf8mb3_general_ci;
|
|
@ -0,0 +1,2 @@
|
|||
INSERT INTO stock.config (id, saleLife)
|
||||
VALUES (1, 90);
|
|
@ -0,0 +1 @@
|
|||
CREATE SEQUENCE IF NOT EXISTS vn.buyLot;
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE vn.sale
|
||||
ADD COLUMN IF NOT EXISTS lotFk INT UNSIGNED NOT NULL DEFAULT nextval(vn.buyLot) AFTER id;
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE hedera.orderRow
|
||||
ADD COLUMN IF NOT EXISTS lotFk INT UNSIGNED NOT NULL DEFAULT nextval(vn.buyLot) AFTER id;
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE vn.buy
|
||||
ADD COLUMN IF NOT EXISTS lotFk INT UNSIGNED NOT NULL DEFAULT nextval(vn.buyLot) AFTER id;
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE vn.sale
|
||||
ADD UNIQUE IF NOT EXISTS (lotFk);
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE hedera.orderRow
|
||||
ADD UNIQUE IF NOT EXISTS (lotFk);
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE vn.buy
|
||||
ADD UNIQUE IF NOT EXISTS (lotFk);
|
|
@ -0,0 +1,14 @@
|
|||
ALTER TABLE `vn`.`claimConfig`
|
||||
ADD COLUMN `pickupDeliveryFk` INT(11)
|
||||
COMMENT 'Agencia utilizada para las recogidas mediante reparto',
|
||||
ADD COLUMN `warehouseFk` smallint(6) unsigned
|
||||
COMMENT 'Almacén usado para los tickets de reclamaciones',
|
||||
|
||||
ADD CONSTRAINT `fk_claimConfig_pickupdeliveryFk`
|
||||
FOREIGN KEY (`pickupdeliveryFk`)
|
||||
REFERENCES `agencyMode` (`id`),
|
||||
|
||||
ADD CONSTRAINT `fk_claimConfig_warehouseFk`
|
||||
FOREIGN KEY (`warehouseFk`)
|
||||
REFERENCES `warehouse` (`id`);
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
INSERT IGNORE INTO vn.state (name,`order`,alertLevel,code,isPreviousPreparable,isPicked)
|
||||
VALUES ('Recogido',3,4,'PICKED_UP',0,1)
|
|
@ -0,0 +1,5 @@
|
|||
ALTER TABLE `vn`.`claimEnd`
|
||||
ADD COLUMN `shelvingFk` INT(11) DEFAULT NULL AFTER `editorFk`,
|
||||
ADD INDEX `claimEnd_fk_shelving` (`shelvingFk`),
|
||||
ADD CONSTRAINT `claimEnd_fk_shelving` FOREIGN KEY (`shelvingFk`)
|
||||
REFERENCES `shelving` (`id`) ON DELETE SET NULL ON UPDATE CASCADE;
|
|
@ -0,0 +1,8 @@
|
|||
UPDATE vn.claimDestination cd
|
||||
SET cd.addressFk = NULL
|
||||
WHERE code IN ('garbage/loss','manufacturing','supplierClaim','corrected');
|
||||
|
||||
UPDATE vn.claimDestination cd
|
||||
JOIN vn.addressWaste aw ON aw.`type` = 'fault'
|
||||
SET cd.addressFk = aw.addressFk
|
||||
WHERE code IN ('good');
|
|
@ -0,0 +1,8 @@
|
|||
UPDATE vn.claimEnd ce
|
||||
JOIN(
|
||||
SELECT id
|
||||
FROM vn.claimEnd
|
||||
WHERE claimDestinationFk NOT IN
|
||||
(SELECT id FROM vn.claimDestination WHERE id IS NOT NULL)
|
||||
) s ON ce.id = s.id
|
||||
SET ce.claimDestinationFk = 1;
|
|
@ -0,0 +1,9 @@
|
|||
ALTER TABLE vn.claimEnd
|
||||
MODIFY COLUMN claimDestinationFk tinyint(3) unsigned NOT NULL DEFAULT 1;
|
||||
|
||||
ALTER TABLE vn.claimEnd
|
||||
ADD CONSTRAINT fk_claimEnd_claimDestination
|
||||
FOREIGN KEY (claimDestinationFk)
|
||||
REFERENCES claimDestination(id)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE RESTRICT;
|
|
@ -0,0 +1,3 @@
|
|||
-- Place your SQL code here
|
||||
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
|
||||
VALUES ('Worker','getWorkerBusiness','READ','ALLOW','ROLE','hr');
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
|
||||
USE vn;
|
||||
|
||||
INSERT INTO vn.workerActivityType (code, description)
|
||||
VALUES('SHELVING_CLEAN_START', 'SE INICIA LIMPIEZA CARRO'),
|
||||
('SHELVING_CLEAN_STOP', 'SE FINALIZA LIMPIEZA CARRO');
|
||||
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
ALTER TABLE vn.priceDelta ADD IF NOT EXISTS isHidden BOOL
|
||||
DEFAULT FALSE NOT NULL
|
||||
COMMENT 'Hides the itemType when building de catalog recordset';
|
|
@ -258,5 +258,6 @@
|
|||
"clonedFromTicketWeekly": ", that is a cloned sale from ticket {{ ticketWeekly }}",
|
||||
"negativeReplaced": "Replaced item [#{{oldItemId}}]({{{oldItemUrl}}}) {{oldItem}} with [#{{newItemId}}]({{{newItemUrl}}}) {{newItem}} from ticket [{{ticketId}}]({{{ticketUrl}}})",
|
||||
"The tag and priority can't be repeated": "The tag and priority can't be repeated",
|
||||
"duplicateWarehouse": "The introduced warehouse already exists"
|
||||
"The introduced warehouse already exists": "The introduced warehouse already exists",
|
||||
"The code already exists": "The code already exists"
|
||||
}
|
||||
|
|
|
@ -399,5 +399,6 @@
|
|||
"Price cannot be blank": "El precio no puede estar en blanco",
|
||||
"clonedFromTicketWeekly": ", que es una linea clonada del ticket {{ticketWeekly}}",
|
||||
"negativeReplaced": "Sustituido el articulo [#{{oldItemId}}]({{{oldItemUrl}}}) {{oldItem}} por [#{{newItemId}}]({{{newItemUrl}}}) {{newItem}} del ticket [{{ticketId}}]({{{ticketUrl}}})",
|
||||
"duplicateWarehouse": "El almacén seleccionado ya existe en la zona"
|
||||
"The introduced warehouse already exists": "El almacén seleccionado ya existe en la zona",
|
||||
"The code already exists": "El código ya existe"
|
||||
}
|
|
@ -74,66 +74,77 @@ module.exports = Self => {
|
|||
}
|
||||
|
||||
try {
|
||||
const worker = await models.Worker.findOne({
|
||||
where: {id: userId}
|
||||
const claim = await models.Claim.findOne(filter, myOptions);
|
||||
const today = Date.vnNew();
|
||||
let agencyModeFk;
|
||||
let nickname;
|
||||
let state;
|
||||
let discountValue = null;
|
||||
let packages = 0;
|
||||
const claimConfig = await models.ClaimConfig.findOne();
|
||||
const warehouseFk = claimConfig.warehouseFk;
|
||||
if (claim.pickup === null || claim.pickup == 'agency') {
|
||||
state = await models.State.findOne({
|
||||
where: {code: 'DELIVERED'}
|
||||
}, myOptions);
|
||||
|
||||
const obsevationType = await models.ObservationType.findOne({
|
||||
where: {code: 'salesPerson'}
|
||||
}, myOptions);
|
||||
|
||||
const agencyMode = await models.AgencyMode.findOne({
|
||||
where: {code: 'refund'}
|
||||
}, myOptions);
|
||||
|
||||
const state = await models.State.findOne({
|
||||
where: {code: 'DELIVERED'}
|
||||
agencyModeFk = agencyMode.id;
|
||||
nickname = `Abono del: ${claim.ticketFk}`;
|
||||
} else {
|
||||
discountValue = 100;
|
||||
packages = 1;
|
||||
state = await models.State.findOne({
|
||||
where: {code: 'WAITING_FOR_PICKUP'}
|
||||
}, myOptions);
|
||||
|
||||
const zone = await models.Zone.findOne({
|
||||
where: {agencyModeFk: agencyMode.id}
|
||||
}, myOptions);
|
||||
|
||||
const claim = await models.Claim.findOne(filter, myOptions);
|
||||
const today = Date.vnNew();
|
||||
nickname = `Recogida pendiente del: ${claim.ticketFk}`;
|
||||
|
||||
agencyModeFk = claimConfig.pickupDeliveryFk;
|
||||
}
|
||||
const nextShipped = await models.Agency.getShipped(
|
||||
ctx, today, claim.ticket().addressFk, agencyModeFk, warehouseFk, myOptions
|
||||
);
|
||||
const newRefundTicket = await models.Ticket.create({
|
||||
clientFk: claim.ticket().clientFk,
|
||||
shipped: today,
|
||||
landed: today,
|
||||
nickname: `Abono del: ${claim.ticketFk}`,
|
||||
warehouseFk: claim.ticket().warehouseFk,
|
||||
shipped: nextShipped.shipped,
|
||||
landed: null,
|
||||
nickname,
|
||||
warehouseFk,
|
||||
companyFk: claim.ticket().companyFk,
|
||||
addressFk: claim.ticket().addressFk,
|
||||
agencyModeFk: agencyMode.id,
|
||||
zoneFk: zone.id
|
||||
agencyModeFk,
|
||||
zoneFk: claim.ticket().zoneFk,
|
||||
packages
|
||||
}, myOptions);
|
||||
|
||||
if (claim.pickup == 'pickup') {
|
||||
const observationDelivery =
|
||||
await models.ObservationType.findOne({where: {code: 'delivery'}}, myOptions);
|
||||
|
||||
await saveObservation({
|
||||
description: `recoger reclamación: ${claim.id}`,
|
||||
ticketFk: newRefundTicket.id,
|
||||
observationTypeFk: observationDelivery.id
|
||||
}, myOptions);
|
||||
}
|
||||
await models.TicketRefund.create({
|
||||
refundTicketFk: newRefundTicket.id,
|
||||
originalTicketFk: claim.ticket().id
|
||||
}, myOptions);
|
||||
|
||||
await saveObservation({
|
||||
description: `Reclama ticket: ${claim.ticketFk}`,
|
||||
ticketFk: newRefundTicket.id,
|
||||
observationTypeFk: obsevationType.id
|
||||
}, myOptions);
|
||||
const salesToRefund = await models.ClaimBeginning.find(salesFilter, myOptions);
|
||||
const createdSales = await addSalesToTicket(salesToRefund, newRefundTicket.id, discountValue, myOptions);
|
||||
await insertIntoClaimEnd(createdSales, id, userId, myOptions);
|
||||
|
||||
await models.Ticket.state(ctx, {
|
||||
ticketFk: newRefundTicket.id,
|
||||
stateFk: state.id,
|
||||
userFk: worker.id
|
||||
userFk: userId
|
||||
}, myOptions);
|
||||
|
||||
const salesToRefund = await models.ClaimBeginning.find(salesFilter, myOptions);
|
||||
const createdSales = await addSalesToTicket(salesToRefund, newRefundTicket.id, myOptions);
|
||||
await insertIntoClaimEnd(createdSales, id, worker.id, myOptions);
|
||||
|
||||
await Self.rawSql('CALL vn.ticketCalculateClon(?, ?)', [
|
||||
newRefundTicket.id, claim.ticketFk
|
||||
], myOptions);
|
||||
|
||||
if (tx) await tx.commit();
|
||||
|
||||
return newRefundTicket;
|
||||
|
@ -143,23 +154,36 @@ module.exports = Self => {
|
|||
}
|
||||
};
|
||||
|
||||
async function addSalesToTicket(salesToRefund, ticketId, options) {
|
||||
let formatedSales = [];
|
||||
salesToRefund.forEach(sale => {
|
||||
let formatedSale = {
|
||||
itemFk: sale.sale().itemFk,
|
||||
ticketFk: ticketId,
|
||||
concept: sale.sale().concept,
|
||||
quantity: -Math.abs(sale.quantity),
|
||||
price: sale.sale().price,
|
||||
discount: sale.sale().discount,
|
||||
reserved: sale.sale().reserved,
|
||||
isPicked: sale.sale().isPicked,
|
||||
created: sale.sale().created
|
||||
async function addSalesToTicket(salesToRefund, newTicketId, discountValue, options) {
|
||||
const createdSales = [];
|
||||
const models = Self.app.models;
|
||||
for (const saleToRefund of salesToRefund) {
|
||||
const oldSale = saleToRefund.sale();
|
||||
const newSaleData = {
|
||||
itemFk: oldSale.itemFk,
|
||||
ticketFk: newTicketId,
|
||||
concept: oldSale.concept,
|
||||
quantity: -Math.abs(saleToRefund.quantity),
|
||||
price: oldSale.price,
|
||||
discount: discountValue ?? oldSale.discount,
|
||||
reserved: oldSale.reserved,
|
||||
isPicked: oldSale.isPicked,
|
||||
created: oldSale.created
|
||||
};
|
||||
formatedSales.push(formatedSale);
|
||||
const newSale = await models.Sale.create(newSaleData, options);
|
||||
const oldSaleComponents = await models.SaleComponent.find({
|
||||
where: {saleFk: oldSale.id}
|
||||
}, options);
|
||||
const newComponents = oldSaleComponents.map(component => {
|
||||
const data = component.toJSON ? component.toJSON() : {...component};
|
||||
delete data.id;
|
||||
data.saleFk = newSale.id;
|
||||
return data;
|
||||
});
|
||||
return await Self.app.models.Sale.create(formatedSales, options);
|
||||
await models.SaleComponent.create(newComponents, options);
|
||||
createdSales.push(newSale);
|
||||
}
|
||||
return createdSales;
|
||||
}
|
||||
|
||||
async function insertIntoClaimEnd(createdSales, claimId, workerId, options) {
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
const LoopBackContext = require('loopback-context');
|
||||
const models = app.models;
|
||||
|
||||
describe('claimBeginning', () => {
|
||||
const claimManagerId = 72;
|
||||
const activeCtx = {
|
||||
accessToken: {userId: claimManagerId},
|
||||
__: value => value
|
||||
};
|
||||
const ctx = {req: activeCtx};
|
||||
|
||||
describe('importToNewRefundTicket()', () => {
|
||||
it('should create a new ticket with negative sales and insert the negative sales into claimEnd', async() => {
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||
active: activeCtx
|
||||
});
|
||||
let claimId = 1;
|
||||
|
||||
const tx = await models.Entry.beginTransaction({});
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const ticket = await models.ClaimBeginning.importToNewRefundTicket(ctx, claimId, options);
|
||||
|
||||
const refundTicketSales = await models.Sale.find({
|
||||
where: {ticketFk: ticket.id}
|
||||
}, options);
|
||||
const salesInsertedInClaimEnd = await models.ClaimEnd.find({
|
||||
where: {claimFk: claimId}
|
||||
}, options);
|
||||
|
||||
expect(refundTicketSales.length).toEqual(1);
|
||||
expect(refundTicketSales[0].quantity).toEqual(-5);
|
||||
expect(salesInsertedInClaimEnd[0].saleFk).toEqual(refundTicketSales[0].id);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,99 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
const LoopBackContext = require('loopback-context');
|
||||
const models = app.models;
|
||||
|
||||
describe('importToNewRefundTicket()', () => {
|
||||
let tx;
|
||||
const claimManagerId = 72;
|
||||
const activeCtx = {
|
||||
accessToken: {userId: claimManagerId},
|
||||
};
|
||||
let ctx = {req: activeCtx};
|
||||
let options;
|
||||
const claimId = 1;
|
||||
const expectedDate = Date.vnNew();
|
||||
|
||||
beforeEach(async() => {
|
||||
LoopBackContext.getCurrentContext = () => ({
|
||||
active: activeCtx,
|
||||
});
|
||||
tx = await models.Entry.beginTransaction({});
|
||||
options = {transaction: tx};
|
||||
spyOn(models.Agency, 'getShipped').and.returnValue(Promise.resolve({shipped: expectedDate}));
|
||||
});
|
||||
|
||||
afterEach(async() => {
|
||||
await tx.rollback();
|
||||
});
|
||||
|
||||
it('should create a new ticket with negative sales and insert the negative sales into claimEnd', async() => {
|
||||
const ticket = await models.ClaimBeginning.importToNewRefundTicket(ctx, claimId, options);
|
||||
|
||||
const refundTicketSales = await models.Sale.find({
|
||||
where: {ticketFk: ticket.id}
|
||||
}, options);
|
||||
const salesInsertedInClaimEnd = await models.ClaimEnd.find({
|
||||
where: {claimFk: claimId}
|
||||
}, options);
|
||||
|
||||
expect(refundTicketSales.length).toEqual(1);
|
||||
expect(refundTicketSales[0].quantity).toEqual(-5);
|
||||
expect(salesInsertedInClaimEnd[0].saleFk).toEqual(refundTicketSales[0].id);
|
||||
});
|
||||
|
||||
it('should set DELIVERED state and refund agency mode', async() => {
|
||||
const state = await models.State.findOne({
|
||||
where: {code: 'DELIVERED'}
|
||||
}, options);
|
||||
const ticket = await models.ClaimBeginning.importToNewRefundTicket(ctx, claimId, options);
|
||||
const ticketTracking = await models.TicketTracking.findOne({
|
||||
where: {ticketFk: ticket.id},
|
||||
order: 'id DESC'
|
||||
}, options);
|
||||
|
||||
const newSales = await models.Sale.find({
|
||||
where: {ticketFk: ticket.id}
|
||||
}, options);
|
||||
|
||||
newSales.forEach(sale => {
|
||||
expect(sale.discount).toEqual(0);
|
||||
});
|
||||
|
||||
expect(ticketTracking.stateFk).toEqual(state.id);
|
||||
});
|
||||
|
||||
it('should set WAITING_FOR_PICKUP state for delivery pickups', async() => {
|
||||
const state = await models.State.findOne({
|
||||
where: {code: 'WAITING_FOR_PICKUP'}
|
||||
}, options);
|
||||
await models.Claim.updateAll({id: claimId}, {pickup: 'delivery'}, options);
|
||||
const ticket = await models.ClaimBeginning.importToNewRefundTicket(ctx, claimId, options);
|
||||
const ticketTracking = await models.TicketTracking.findOne({
|
||||
where: {ticketFk: ticket.id},
|
||||
order: 'id DESC'
|
||||
}, options);
|
||||
const newSales = await models.Sale.find({
|
||||
where: {ticketFk: ticket.id}
|
||||
}, options);
|
||||
|
||||
newSales.forEach(sale => {
|
||||
expect(sale.discount).toEqual(100);
|
||||
});
|
||||
|
||||
expect(ticketTracking.stateFk).toEqual(state.id);
|
||||
});
|
||||
|
||||
it('should set DELIVERED state for agency pickups', async() => {
|
||||
const state = await models.State.findOne({
|
||||
where: {code: 'DELIVERED'}
|
||||
}, options);
|
||||
await models.Claim.updateAll({id: claimId}, {pickup: 'agency'}, options);
|
||||
const ticket = await models.ClaimBeginning.importToNewRefundTicket(ctx, claimId, options);
|
||||
const ticketTracking = await models.TicketTracking.findOne({
|
||||
where: {ticketFk: ticket.id},
|
||||
order: 'id DESC'
|
||||
}, options);
|
||||
|
||||
expect(ticketTracking.stateFk).toEqual(state.id);
|
||||
});
|
||||
});
|
|
@ -51,10 +51,13 @@ module.exports = Self => {
|
|||
s.concept,
|
||||
s.price,
|
||||
s.discount,
|
||||
s.quantity * s.price * ((100 - s.discount) / 100) total
|
||||
s.quantity * s.price * ((100 - s.discount) / 100) total,
|
||||
ce.shelvingFk,
|
||||
sh.code shelvingCode
|
||||
FROM vn.claimEnd ce
|
||||
LEFT JOIN vn.sale s ON s.id = ce.saleFk
|
||||
LEFT JOIN vn.ticket t ON t.id = s.ticketFk
|
||||
LEFT JOIN vn.shelving sh ON sh.id = ce.shelvingFk
|
||||
) ce`
|
||||
);
|
||||
|
||||
|
|
|
@ -3,12 +3,14 @@ module.exports = Self => {
|
|||
description: `Imports lines from claimBeginning to a new ticket
|
||||
with specific shipped, landed dates, agency and company`,
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
accepts: [
|
||||
{
|
||||
arg: 'id',
|
||||
type: 'number',
|
||||
description: 'The claim id',
|
||||
http: {source: 'path'}
|
||||
}],
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: ['Object'],
|
||||
root: true
|
||||
|
@ -22,8 +24,6 @@ module.exports = Self => {
|
|||
Self.regularizeClaim = async(ctx, claimFk, options) => {
|
||||
const models = Self.app.models;
|
||||
const $t = ctx.req.__; // $translate
|
||||
const resolvedState = 3;
|
||||
|
||||
let tx;
|
||||
const myOptions = {};
|
||||
|
||||
|
@ -37,25 +37,39 @@ module.exports = Self => {
|
|||
|
||||
try {
|
||||
const claimEnds = await models.ClaimEnd.find({
|
||||
include: {
|
||||
where: {claimFk: claimFk},
|
||||
include: [
|
||||
{
|
||||
relation: 'claimDestination',
|
||||
fields: ['addressFk']
|
||||
scope: {fields: ['addressFk']}
|
||||
},
|
||||
where: {claimFk: claimFk}
|
||||
{
|
||||
relation: 'shelving',
|
||||
scope: {
|
||||
fields: ['code', 'parkingFk'],
|
||||
include: {
|
||||
relation: 'parking',
|
||||
scope: {
|
||||
fields: ['sectorFk'],
|
||||
include: {
|
||||
relation: 'sector',
|
||||
scope: {fields: ['warehouseFk']}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}, myOptions);
|
||||
|
||||
for (let claimEnd of claimEnds) {
|
||||
const destination = claimEnd.claimDestination();
|
||||
const sale = await getSale(claimEnd.saleFk, myOptions);
|
||||
const addressId = destination && destination.addressFk;
|
||||
|
||||
let address;
|
||||
if (addressId)
|
||||
address = await models.Address.findById(addressId, null, myOptions);
|
||||
const addressId = destination?.addressFk;
|
||||
|
||||
const salesPerson = sale.ticket().client().salesPersonUser();
|
||||
if (salesPerson) {
|
||||
const nickname = address && address.nickname || destination.description;
|
||||
const nickname = destination.description;
|
||||
const url = await Self.app.models.Url.getUrl();
|
||||
const message = $t('Sent units from ticket', {
|
||||
quantity: sale.quantity,
|
||||
|
@ -69,18 +83,21 @@ module.exports = Self => {
|
|||
await models.Chat.sendCheckingPresence(ctx, salesPerson.id, message);
|
||||
}
|
||||
|
||||
if (!address) continue;
|
||||
if (!addressId) continue;
|
||||
|
||||
const warehouseFk = claimEnd.shelving().parking().sector().warehouseFk;
|
||||
const address = await models.Address.findById(addressId, null, myOptions);
|
||||
|
||||
let ticketFk = await getTicketId({
|
||||
addressFk: addressId,
|
||||
companyFk: sale.ticket().companyFk,
|
||||
warehouseFk: sale.ticket().warehouseFk
|
||||
warehouseFk: warehouseFk
|
||||
}, myOptions);
|
||||
|
||||
if (!ticketFk) {
|
||||
ctx.args = {
|
||||
clientId: address.clientFk,
|
||||
warehouseId: sale.ticket().warehouseFk,
|
||||
warehouseId: warehouseFk,
|
||||
companyId: sale.ticket().companyFk,
|
||||
addressId: addressId
|
||||
};
|
||||
|
@ -90,15 +107,43 @@ module.exports = Self => {
|
|||
ticketFk: ticketFk,
|
||||
itemFk: sale.itemFk,
|
||||
concept: sale.concept,
|
||||
quantity: -sale.quantity,
|
||||
quantity: sale.quantity,
|
||||
price: sale.price,
|
||||
discount: 100
|
||||
}, myOptions);
|
||||
|
||||
const [buyFk] = await Self.rawSql('SELECT vn.buy_getLastWithoutInventory(?, ?) buyFk',
|
||||
[sale.itemFk, warehouseFk], myOptions
|
||||
);
|
||||
await Self.rawSql('CALL vn.itemShelving_add(?, ?, ?, NULL, NULL, NULL, ?)',
|
||||
[claimEnd.shelving().code, buyFk.buyFk, -sale.quantity, warehouseFk],
|
||||
myOptions
|
||||
);
|
||||
const operator = await models.Operator.findById(
|
||||
ctx.req.accessToken.userId, {fields: ['labelerFk']}, myOptions);
|
||||
|
||||
const params = JSON.stringify({
|
||||
copies: 1,
|
||||
id: buyFk.buyFk,
|
||||
labelType: 'qr'
|
||||
});
|
||||
|
||||
await Self.rawSql(`CALL vn.report_print( ?, ?, ?, ?, ?)`,
|
||||
['LabelBuy',
|
||||
operator?.labelerFk,
|
||||
ctx.req.accessToken.userId,
|
||||
params,
|
||||
'normal'
|
||||
],
|
||||
myOptions);
|
||||
}
|
||||
const resolvedState = await models.ClaimState.findOne({
|
||||
where: {code: 'resolved'}
|
||||
}, myOptions);
|
||||
|
||||
let claim = await Self.findById(claimFk, null, myOptions);
|
||||
claim = await claim.updateAttributes({
|
||||
claimStateFk: resolvedState
|
||||
claimStateFk: resolvedState.id
|
||||
}, myOptions);
|
||||
|
||||
if (tx) await tx.commit();
|
||||
|
@ -151,7 +196,7 @@ module.exports = Self => {
|
|||
}
|
||||
}, options);
|
||||
|
||||
return ticket && ticket.id;
|
||||
return ticket?.id;
|
||||
}
|
||||
|
||||
async function createTicket(ctx, options) {
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
const LoopBackContext = require('loopback-context');
|
||||
|
||||
describe('claim regularizeClaim()', () => {
|
||||
const userId = 18;
|
||||
const ctx = beforeAll.mockLoopBackContext(userId);
|
||||
ctx.req.__ = (value, params) => {
|
||||
return params.nickname;
|
||||
};
|
||||
const userId = 72;
|
||||
const chatModel = models.Chat;
|
||||
const claimId = 1;
|
||||
const ticketId = 1;
|
||||
|
@ -13,9 +10,27 @@ describe('claim regularizeClaim()', () => {
|
|||
const resolvedState = 3;
|
||||
const trashDestination = 2;
|
||||
const okDestination = 1;
|
||||
const trashAddress = 12;
|
||||
let claimEnds = [];
|
||||
let trashTicket;
|
||||
const activeCtx = {accessToken: {userId}};
|
||||
let ctx = {req: activeCtx};
|
||||
let tx;
|
||||
let options;
|
||||
|
||||
beforeEach(async() => {
|
||||
LoopBackContext.getCurrentContext = () => ({
|
||||
active: activeCtx,
|
||||
});
|
||||
|
||||
ctx.req.__ = (_value, params) => {
|
||||
return params.nickname;
|
||||
};
|
||||
tx = await models.Claim.beginTransaction({});
|
||||
options = {transaction: tx};
|
||||
});
|
||||
|
||||
afterEach(async() => {
|
||||
await tx.rollback();
|
||||
});
|
||||
|
||||
async function importTicket(ticketId, claimId, userId, options) {
|
||||
const ticketSales = await models.Sale.find({
|
||||
|
@ -34,11 +49,6 @@ describe('claim regularizeClaim()', () => {
|
|||
}
|
||||
|
||||
it('should send a chat message with value "Trash" and then change claim state to resolved', async() => {
|
||||
const tx = await models.Claim.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
|
||||
|
||||
claimEnds = await importTicket(ticketId, claimId, userId, options);
|
||||
|
@ -50,68 +60,62 @@ describe('claim regularizeClaim()', () => {
|
|||
await models.Claim.regularizeClaim(ctx, claimId, options);
|
||||
let claimAfter = await models.Claim.findById(claimId, null, options);
|
||||
|
||||
trashTicket = await models.Ticket.findOne({where: {addressFk: 12}}, options);
|
||||
|
||||
expect(trashTicket.addressFk).toEqual(trashAddress);
|
||||
expect(claimBefore.claimStateFk).toEqual(pendentState);
|
||||
expect(claimAfter.claimStateFk).toEqual(resolvedState);
|
||||
expect(chatModel.sendCheckingPresence).toHaveBeenCalledWith(ctx, 18, 'Trash');
|
||||
expect(chatModel.sendCheckingPresence).toHaveBeenCalledTimes(4);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should send a chat message with value "Bueno" and then change claim state to resolved', async() => {
|
||||
const tx = await models.Claim.beginTransaction({});
|
||||
it('should change claim state to resolved', async() => {
|
||||
const addressMissingFk = 11;
|
||||
const shelvingFk = 1;
|
||||
const warehouseFk = 6;
|
||||
const minDate = Date.vnNew();
|
||||
minDate.setHours(0, 0, 0, 0);
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
const maxDate = Date.vnNew();
|
||||
maxDate.setHours(23, 59, 59, 59);
|
||||
|
||||
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
|
||||
|
||||
claimEnds = await importTicket(ticketId, claimId, userId, options);
|
||||
|
||||
for (claimEnd of claimEnds)
|
||||
await claimEnd.updateAttributes({claimDestinationFk: okDestination}, options);
|
||||
for (let claimEnd of claimEnds)
|
||||
await claimEnd.updateAttributes({claimDestinationFk: okDestination, shelvingFk}, options);
|
||||
|
||||
const sale = await models.Sale.findOne({
|
||||
include: [
|
||||
{
|
||||
relation: 'ticket',
|
||||
scope: {
|
||||
fields: ['clientFk', 'companyFk']
|
||||
}
|
||||
}],
|
||||
where: {id: claimEnds[0].saleFk}
|
||||
}, options);
|
||||
|
||||
await models.Claim.regularizeClaim(ctx, claimId, options);
|
||||
|
||||
expect(chatModel.sendCheckingPresence).toHaveBeenCalledWith(ctx, 18, 'Bueno');
|
||||
expect(chatModel.sendCheckingPresence).toHaveBeenCalledTimes(4);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
const ticket = await models.Ticket.findOne({
|
||||
where: {
|
||||
addressFk: addressMissingFk,
|
||||
companyFk: sale.ticket().companyFk,
|
||||
warehouseFk: warehouseFk,
|
||||
shipped: {between: [minDate, maxDate]},
|
||||
landed: {between: [minDate, maxDate]}
|
||||
}
|
||||
});
|
||||
}, options);
|
||||
|
||||
it('should send a chat message to the salesPerson when claim isPickUp is enabled', async() => {
|
||||
const tx = await models.Claim.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
|
||||
|
||||
claimEnds = await importTicket(ticketId, claimId, userId, options);
|
||||
|
||||
for (claimEnd of claimEnds)
|
||||
await claimEnd.updateAttributes({claimDestinationFk: okDestination}, options);
|
||||
|
||||
await models.Claim.regularizeClaim(ctx, claimId, options);
|
||||
|
||||
expect(chatModel.sendCheckingPresence).toHaveBeenCalledWith(ctx, 18, 'Bueno');
|
||||
expect(chatModel.sendCheckingPresence).toHaveBeenCalledTimes(4);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
const missingSale = await models.Sale.findOne({
|
||||
where: {
|
||||
ticketFk: ticket.id
|
||||
}
|
||||
}, options);
|
||||
|
||||
const claimBeginning = await models.ClaimBeginning.findOne({
|
||||
where: {
|
||||
claimFk: claimId
|
||||
}
|
||||
}, options);
|
||||
|
||||
expect(missingSale.quantity).toBe(claimBeginning.quantity);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
"Claim": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"ClaimConfig": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"ClaimContainer": {
|
||||
"dataSource": "claimStorage"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
|
||||
{
|
||||
"name": "ClaimConfig",
|
||||
"base": "VnModel",
|
||||
"mixins": {
|
||||
"Loggable": true
|
||||
},
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "claimConfig"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
"maxResponsibility": {
|
||||
"type": "number"
|
||||
},
|
||||
"monthsToRefund": {
|
||||
"type": "number"
|
||||
},
|
||||
"minShipped": {
|
||||
"type": "date"
|
||||
},
|
||||
"pickupdeliveryFk": {
|
||||
"type": "number"
|
||||
},
|
||||
"warehouseFk": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
"pickupDelivery": {
|
||||
"type": "belongsTo",
|
||||
"model": "AgencyMode",
|
||||
"foreignKey": "pickupdeliveryFk"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -41,6 +41,11 @@
|
|||
"type": "belongsTo",
|
||||
"model": "ClaimDestination",
|
||||
"foreignKey": "claimDestinationFk"
|
||||
},
|
||||
"shelving": {
|
||||
"type": "belongsTo",
|
||||
"model": "Shelving",
|
||||
"foreignKey": "shelvingFk"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,17 @@ module.exports = function(Self) {
|
|||
password: String(Math.random() * 100000000000000)
|
||||
};
|
||||
|
||||
const supplier = await models.Supplier.findOne({
|
||||
where: {nif: data.fi}
|
||||
});
|
||||
|
||||
const role = supplier ? await models.VnRole.findOne({
|
||||
where: {name: 'supplier'}
|
||||
}) : null;
|
||||
|
||||
if (role)
|
||||
user.roleFk = role.id;
|
||||
|
||||
try {
|
||||
const province = await models.Province.findOne({
|
||||
where: {id: data.provinceFk},
|
||||
|
|
|
@ -48,11 +48,11 @@ describe('Client Create', () => {
|
|||
expect(error.message).toEqual('An email is necessary');
|
||||
});
|
||||
|
||||
it('should create a new account with dailyInvoice', async() => {
|
||||
it('should create a new account with dailyInvoice and role supplier', async() => {
|
||||
const newAccount = {
|
||||
userName: 'deadpool',
|
||||
email: 'deadpool@marvel.com',
|
||||
fi: '16195279J',
|
||||
fi: '07972486L',
|
||||
name: 'Wade',
|
||||
socialName: 'DEADPOOL MARVEL',
|
||||
street: 'WALL STREET',
|
||||
|
@ -61,7 +61,6 @@ describe('Client Create', () => {
|
|||
provinceFk: 1
|
||||
};
|
||||
|
||||
try {
|
||||
const province = await models.Province.findById(newAccount.provinceFk, {
|
||||
fields: ['id', 'name', 'autonomyFk'],
|
||||
include: {
|
||||
|
@ -71,7 +70,9 @@ describe('Client Create', () => {
|
|||
|
||||
const client = await models.Client.createWithUser(newAccount, options);
|
||||
const account = await models.VnUser.findOne({where: {name: newAccount.userName}}, options);
|
||||
const supplierRole = await models.VnRole.findOne({where: {name: 'supplier'}}, options);
|
||||
|
||||
expect(account.roleFk).toEqual(supplierRole.id);
|
||||
expect(province.autonomy().hasDailyInvoice).toBeTruthy();
|
||||
expect(account.name).toEqual(newAccount.userName);
|
||||
expect(client.id).toEqual(account.id);
|
||||
|
@ -81,13 +82,9 @@ describe('Client Create', () => {
|
|||
expect(client.socialName).toEqual(newAccount.socialName);
|
||||
expect(client.businessTypeFk).toEqual(newAccount.businessTypeFk);
|
||||
expect(client.hasDailyInvoice).toBeTruthy();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should create a new account without dailyInvoice', async() => {
|
||||
it('should create a new account without dailyInvoice and role customer', async() => {
|
||||
const newAccount = {
|
||||
userName: 'deadpool',
|
||||
email: 'deadpool@marvel.com',
|
||||
|
@ -100,7 +97,6 @@ describe('Client Create', () => {
|
|||
provinceFk: 3
|
||||
};
|
||||
|
||||
try {
|
||||
const province = await models.Province.findById(newAccount.provinceFk, {
|
||||
fields: ['id', 'name', 'autonomyFk'],
|
||||
include: {
|
||||
|
@ -109,13 +105,12 @@ describe('Client Create', () => {
|
|||
}, options);
|
||||
|
||||
const client = await models.Client.createWithUser(newAccount, options);
|
||||
const vnUser = await models.VnUser.findOne({where: {name: newAccount.userName}}, options);
|
||||
const customerRole = await models.VnRole.findOne({where: {name: 'customer'}}, options);
|
||||
|
||||
expect(vnUser.roleFk).toEqual(customerRole.id);
|
||||
expect(province.autonomy.hasDailyInvoice).toBeFalsy();
|
||||
expect(client.hasDailyInvoice).toBeFalsy();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should not be able to create a user if exists', async() => {
|
||||
|
|
|
@ -46,29 +46,24 @@ module.exports = Self => {
|
|||
}
|
||||
|
||||
try {
|
||||
const itemDestination = await models.ClaimDestination.findOne({
|
||||
include: {
|
||||
relation: 'address',
|
||||
scope: {
|
||||
fields: ['clientFk']
|
||||
}
|
||||
},
|
||||
where: {description: 'Corregido'}
|
||||
const addressWaste = await models.AddressWaste.findOne({
|
||||
where: {type: 'fault'},
|
||||
include: 'address'
|
||||
}, myOptions);
|
||||
|
||||
const item = await models.Item.findById(itemFk, null, myOptions);
|
||||
|
||||
let ticketId = await getTicketId({
|
||||
clientFk: itemDestination.address.clientFk,
|
||||
addressFk: itemDestination.addressFk,
|
||||
clientFk: addressWaste.address().clientFk,
|
||||
addressFk: addressWaste.addressFk,
|
||||
warehouseFk: warehouseFk
|
||||
}, myOptions);
|
||||
|
||||
if (!ticketId) {
|
||||
ctx.args = {
|
||||
clientId: itemDestination.address().clientFk,
|
||||
clientId: addressWaste.address().clientFk,
|
||||
warehouseId: warehouseFk,
|
||||
addressId: itemDestination.addressFk
|
||||
addressId: addressWaste.addressFk
|
||||
};
|
||||
ticketId = await createTicket(ctx, myOptions);
|
||||
}
|
||||
|
@ -121,7 +116,7 @@ module.exports = Self => {
|
|||
}
|
||||
}, options);
|
||||
|
||||
return ticket && ticket.id;
|
||||
return ticket?.id;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
module.exports = Self => {
|
||||
Self.validatesUniquenessOf('code', {
|
||||
message: `The code already exists`
|
||||
});
|
||||
};
|
|
@ -1,4 +1,8 @@
|
|||
module.exports = Self => {
|
||||
require('../methods/shelving/getSummary')(Self);
|
||||
require('../methods/shelving/addLog')(Self);
|
||||
|
||||
Self.validatesUniquenessOf('code', {
|
||||
message: `The code already exists`
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const smtp = require('vn-print/core/smtp');
|
||||
const config = require('vn-print/core/config');
|
||||
const Email = require('vn-print/core/email');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('closeAll', {
|
||||
|
@ -44,8 +45,7 @@ module.exports = Self => {
|
|||
LIMIT 1`, [toDate, toDate], myOptions);
|
||||
|
||||
await Self.rawSql(`
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.ticket_close;
|
||||
CREATE TEMPORARY TABLE tmp.ticket_close
|
||||
CREATE OR REPLACE TEMPORARY TABLE tmp.ticket_close
|
||||
ENGINE = MEMORY
|
||||
WITH wTickets AS(
|
||||
SELECT t.id ticketFk
|
||||
|
@ -63,11 +63,12 @@ module.exports = Self => {
|
|||
FROM wTicketsTracking wt
|
||||
JOIN ticketTracking tt ON tt.id = wt.maxTracking
|
||||
) SELECT tls.ticketFk,
|
||||
t.clientFk,
|
||||
t.clientFk clientId,
|
||||
c.name clientName,
|
||||
c.email recipient,
|
||||
c.isToBeMailed,
|
||||
eu.email salesPersonEmail,
|
||||
t.addressFk,
|
||||
t.addressFk addressId,
|
||||
c.hasDailyInvoice,
|
||||
c.hasToInvoiceByAddress,
|
||||
t.totalWithVat,
|
||||
|
@ -79,7 +80,7 @@ module.exports = Self => {
|
|||
JOIN agencyMode am ON am.id = t.agencyModeFk
|
||||
JOIN client c ON c.id = t.clientFk
|
||||
LEFT JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk
|
||||
WHERE (al.code = 'PACKED' OR (am.code = 'refund' AND al.code <> 'delivered'));
|
||||
WHERE al.code = 'PACKED' OR (am.code = 'refund' AND al.code <> 'delivered');
|
||||
CALL ticket_close();
|
||||
`, [dateFrom, dateTo], myOptions);
|
||||
|
||||
|
@ -98,19 +99,25 @@ module.exports = Self => {
|
|||
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,
|
||||
const clients = await Self.rawSql(`
|
||||
SELECT *,
|
||||
SUM(totalWithVat) total,
|
||||
'quick' serialType
|
||||
FROM tmp.ticket_close
|
||||
WHERE hasDailyInvoice
|
||||
GROUP BY IF (hasToInvoiceByAddress, addressFk, clientFk), companyFk
|
||||
HAVING total > 0;
|
||||
GROUP BY IF (hasToInvoiceByAddress, addressId, clientId), companyFk
|
||||
HAVING total > 0
|
||||
`, [], myOptions);
|
||||
|
||||
const [ticketsToMail] = await Self.rawSql(`
|
||||
SELECT *
|
||||
FROM tmp.ticket_close
|
||||
WHERE NOT hasDailyInvoice
|
||||
AND isToBeMailed
|
||||
AND salesPersonEmail IS NOT NULL
|
||||
AND salesPersonEmail <> ''
|
||||
AND recipient IS NOT NULL
|
||||
AND recipient <> '';
|
||||
DROP TEMPORARY TABLE tmp.ticket_close;
|
||||
`, [], myOptions);
|
||||
|
||||
|
@ -130,21 +137,23 @@ module.exports = Self => {
|
|||
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;
|
||||
await handleInvoicingError(error, client, failedClients);
|
||||
}
|
||||
}
|
||||
|
||||
failedClients.push({
|
||||
id: client.clientId,
|
||||
address: client.addressId,
|
||||
error
|
||||
});
|
||||
for (const ticket of ticketsToMail) {
|
||||
const args = {
|
||||
id: ticket.ticketFk,
|
||||
recipientId: ticket.clientId,
|
||||
recipient: ticket.recipient,
|
||||
replyTo: ticket.salesPersonEmail,
|
||||
};
|
||||
|
||||
try {
|
||||
const email = new Email('delivery-note-link', args);
|
||||
await email.send();
|
||||
} catch (error) {
|
||||
await handleInvoicingError(error, ticket, failedClients);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -188,4 +197,22 @@ module.exports = Self => {
|
|||
html: body,
|
||||
}).catch(err => console.error(err));
|
||||
}
|
||||
|
||||
async function handleInvoicingError(error, entity, failedClients) {
|
||||
await Self.rawSql(`
|
||||
INSERT INTO util.debug (variable, value)
|
||||
VALUES ('invoicingTicketError', ?)
|
||||
`, [entity.clientId + ' - ' + error]);
|
||||
|
||||
if (error.responseCode == 450) {
|
||||
await invalidEmail(entity);
|
||||
return;
|
||||
}
|
||||
|
||||
failedClients.push({
|
||||
id: entity.clientId,
|
||||
address: entity.addressId,
|
||||
error
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -33,6 +33,11 @@ module.exports = Self => {
|
|||
type: 'date',
|
||||
description: `The to date filter`
|
||||
},
|
||||
{
|
||||
arg: 'shipped',
|
||||
type: 'date',
|
||||
description: `The shipped date filter`
|
||||
},
|
||||
{
|
||||
arg: 'nickname',
|
||||
type: 'string',
|
||||
|
@ -201,6 +206,7 @@ module.exports = Self => {
|
|||
case 'clientFk':
|
||||
case 'agencyModeFk':
|
||||
case 'warehouseFk':
|
||||
case 'shipped':
|
||||
param = `t.${param}`;
|
||||
return {[param]: value};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,255 @@
|
|||
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||
const buildFilter = require('vn-loopback/util/filter').buildFilter;
|
||||
const mergeFilters = require('vn-loopback/util/filter').mergeFilters;
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('getWorkerBusiness', {
|
||||
description: 'Returns an array of business from an specified worker',
|
||||
accessType: 'READ',
|
||||
accepts: [{
|
||||
arg: 'id',
|
||||
type: 'number',
|
||||
required: true,
|
||||
description: 'The worker id',
|
||||
http: {source: 'path'}
|
||||
},
|
||||
{
|
||||
arg: 'filter',
|
||||
type: 'object',
|
||||
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string'
|
||||
},
|
||||
{
|
||||
arg: 'started',
|
||||
type: 'date',
|
||||
description: 'started',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'ended',
|
||||
type: 'date',
|
||||
description: 'ended',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'companyCodeFk',
|
||||
type: 'string',
|
||||
description: 'companyCodeFk',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'reasonEndFk',
|
||||
type: 'number',
|
||||
description: 'reasonEndFk',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'reasondEnd',
|
||||
type: 'string',
|
||||
description: 'reasondEnd',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'departmentFk',
|
||||
type: 'number',
|
||||
description: 'departmentFk',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'department',
|
||||
type: 'string',
|
||||
description: 'department',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'workerBusinessProfessionalCategoryFk',
|
||||
type: 'number',
|
||||
description: 'workerBusinessProfessionalCategoryFk',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'workerBusinessProfessionalCategory',
|
||||
type: 'string',
|
||||
description: 'workerBusinessProfessionalCategory',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'calendarTypeFk',
|
||||
type: 'number',
|
||||
description: 'calendarTypeFk',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'calendarType',
|
||||
type: 'string',
|
||||
description: 'calendarType',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'workcenterFk',
|
||||
type: 'number',
|
||||
description: 'workcenterFk',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'workCenter',
|
||||
type: 'string',
|
||||
description: 'workCenter',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'workerBusinessCategoryFk',
|
||||
type: 'number',
|
||||
description: 'WorkerBusinessCategoryFk',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'workerBusinessCategory',
|
||||
type: 'string',
|
||||
description: 'workerBusinessCategory',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'occupationCodeFk',
|
||||
type: 'number',
|
||||
description: 'occupationCodeFk',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'occupationCode',
|
||||
type: 'string',
|
||||
description: 'occupationCode',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'rate',
|
||||
type: 'number',
|
||||
description: 'rate',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'workerBusinessTypeFk',
|
||||
type: 'number',
|
||||
description: 'workerBusinessTypeFk',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'workerBusinessType',
|
||||
type: 'string',
|
||||
description: 'workerBusinessType',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'amount',
|
||||
type: 'number',
|
||||
description: 'amount',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'basicSalary',
|
||||
type: 'number',
|
||||
description: 'amount',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'notes',
|
||||
type: 'string',
|
||||
description: 'notes',
|
||||
http: {source: 'query'}
|
||||
}],
|
||||
returns: {
|
||||
type: ['object'],
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: '/:id/getWorkerBusiness',
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.getWorkerBusiness = async(ctx, id, filter, options) => {
|
||||
const myOptions = {};
|
||||
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
let conn = Self.dataSource.connector;
|
||||
let where = buildFilter(ctx.args, (param, value) => {
|
||||
switch (param) {
|
||||
case 'started':
|
||||
case 'ended':
|
||||
case 'companyCodeFk':
|
||||
case 'reasonEndFk':
|
||||
case 'reasondEnd':
|
||||
case 'departmentFk':
|
||||
case 'department':
|
||||
case 'workerBusinessProfessionalCategoryFk':
|
||||
case 'workerBusinessProfessionalCategory':
|
||||
case 'calendarTypeFk':
|
||||
case 'calendarType':
|
||||
case 'workcenterFk':
|
||||
case 'workCenter':
|
||||
case 'workerBusinessCategoryFk':
|
||||
case 'workerBusinessCategory':
|
||||
case 'occupationCodeFk':
|
||||
case 'occupationCode':
|
||||
case 'rate':
|
||||
case 'workerBusinessTypeFk':
|
||||
case 'workerBusinessType':
|
||||
case 'amount':
|
||||
case 'basicSalary':
|
||||
case 'notes':
|
||||
}
|
||||
});
|
||||
where = {...where, ...{workerFk: id}};
|
||||
filter = mergeFilters(filter, {where});
|
||||
|
||||
let stmts = [];
|
||||
let stmt;
|
||||
|
||||
stmt = new ParameterizedSQL(
|
||||
`SELECT * FROM(
|
||||
SELECT b.id,
|
||||
b.workerFk,
|
||||
b.started,
|
||||
b.ended,
|
||||
b.companyCodeFk,
|
||||
b.reasonEndFk,
|
||||
bre.reason,
|
||||
b.departmentFk,
|
||||
d.name departmentName,
|
||||
b.occupationCodeFk,
|
||||
oc.name occupationName,
|
||||
b.workerBusinessProfessionalCategoryFk,
|
||||
pf.description professionalDescription,
|
||||
b.calendarTypeFk,
|
||||
ct.description calendarTypeDescription,
|
||||
b.workcenterFk,
|
||||
wc.name workCenterName,
|
||||
b.workerBusinessCategoryFk,
|
||||
py.description payrollDescription,
|
||||
b.workerBusinessTypeFk,
|
||||
wt.name workerBusinessTypeName,
|
||||
b.amount,
|
||||
b.basicSalary,
|
||||
b.notes
|
||||
FROM business b
|
||||
LEFT JOIN businessReasonEnd bre ON bre.id = b.reasonEndFk
|
||||
LEFT JOIN occupationCode oc ON oc.code = b.occupationCodeFk
|
||||
LEFT JOIN department d ON d.id = b.departmentFk
|
||||
LEFT JOIN professionalCategory pf ON pf.id = b.workerBusinessProfessionalCategoryFk
|
||||
JOIN calendarType ct ON ct.id = b.calendarTypeFk
|
||||
LEFT JOIN workCenter wc ON wc.id = b.workcenterFk
|
||||
LEFT JOIN payrollCategories py ON py.id = b.workerBusinessCategoryFk
|
||||
LEFT JOIN workerBusinessType wt ON wt.id = b.workerBusinessTypeFk
|
||||
) sub
|
||||
`
|
||||
);
|
||||
|
||||
stmt.merge(conn.makeSuffix(filter));
|
||||
stmts.push(stmt);
|
||||
|
||||
let sql = ParameterizedSQL.join(stmts, ';');
|
||||
let result = await conn.executeStmt(sql, myOptions);
|
||||
return result;
|
||||
};
|
||||
};
|
|
@ -21,6 +21,7 @@ module.exports = Self => {
|
|||
require('../methods/worker/setPassword')(Self);
|
||||
require('../methods/worker/getAvailablePda')(Self);
|
||||
require('../methods/worker/myTeam')(Self);
|
||||
require('../methods/worker/getWorkerBusiness')(Self);
|
||||
|
||||
Self.canModifyAbsenceInPast = async(ctx, time) => {
|
||||
const hasPrivs = await Self.app.models.ACL.checkAccessAcl(ctx, 'Worker', 'canModifyAbsenceInPast', 'WRITE');
|
||||
|
|
|
@ -3,7 +3,7 @@ let UserError = require('vn-loopback/util/user-error');
|
|||
module.exports = Self => {
|
||||
Self.rewriteDbError(function(err) {
|
||||
if (err.code === 'ER_DUP_ENTRY')
|
||||
return new UserError(`duplicateWarehouse`);
|
||||
return new UserError(`The introduced warehouse already exists`);
|
||||
return err;
|
||||
});
|
||||
};
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
buttons:
|
||||
webAcccess: Visita la nostra Web
|
||||
info: Ajuda'ns a millorar
|
||||
fiscalAddress: VERDNATURA LEVANTE SL, B97367486 C/ Fenollar, 2. 46680 ALGEMESÍ
|
||||
· verdnatura.es · clientes@verdnatura.es
|
||||
disclaimer: '- AVÍS - Aquest missatge és privat i confidencial, i ha de ser utilitzat
|
||||
exclusivament per la persona destinatària del mateix. Si has rebut aquest missatge
|
||||
per error, et preguem que ho comuniquis al remitent i esborres aquest missatge
|
||||
i qualsevol document adjunt que pugui contenir. Verdnatura Levante SL no renuncia
|
||||
a la confidencialitat ni a cap privilegi per causa de transmissió errònia o mal
|
||||
funcionament. Igualment, no es fa responsable dels canvis, alteracions, errors
|
||||
o omissions que es puguin fer al missatge un cop enviat.'
|
||||
privacy: En compliment del que disposa la Llei Orgànica 15/1999, de Protecció de
|
||||
Dades de Caràcter Personal, et comuniquem que les dades personals que facilitis
|
||||
s'inclouran en fitxers automatitzats de VERDNATURA LEVANTE S.L., podent en tot
|
||||
moment exercir els drets d'accés, rectificació, cancel·lació i oposició,
|
||||
comunicant-ho per escrit al domicili social de l'entitat. La finalitat del
|
||||
fitxer és la gestió administrativa, comptabilitat i facturació.
|
|
@ -0,0 +1,11 @@
|
|||
subject: El teu albarà
|
||||
title: El teu albarà
|
||||
dear: Estimat client
|
||||
description: Ja està disponible l'albarà corresponent a la comanda <strong>{0}</strong>. <br/>
|
||||
Pots veure'l fent clic <a href="https://shop.verdnatura.es/#!form=ecomerce/ticket&ticket={0}">en aquest enllaç</a>.
|
||||
copyLink: 'Com a alternativa, pots copiar el següent enllaç al teu navegador:'
|
||||
poll: Si ho desitges, pots respondre a la nostra enquesta de satisfacció per
|
||||
ajudar-nos a oferir un millor servei. La teva opinió és molt important per a nosaltres!
|
||||
help: Qualsevol dubte que tinguis, no dubtis a consultar-nos, <strong>estem aquí
|
||||
per atendre't!</strong>
|
||||
conclusion: Gràcies per la teva atenció!
|
Loading…
Reference in New Issue