Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 2615-waste_detail
This commit is contained in:
commit
41ee6e70a5
|
@ -20,17 +20,37 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.removeFile = async(ctx, id) => {
|
Self.removeFile = async(ctx, id, options) => {
|
||||||
const models = Self.app.models;
|
let tx;
|
||||||
const dms = await models.Dms.findById(id);
|
let myOptions = {};
|
||||||
const trashDmsType = await models.DmsType.findOne({
|
|
||||||
where: {code: 'trash'}
|
|
||||||
});
|
|
||||||
|
|
||||||
const hasWriteRole = await models.DmsType.hasWriteRole(ctx, dms.dmsTypeFk);
|
if (typeof options == 'object')
|
||||||
if (!hasWriteRole)
|
Object.assign(myOptions, options);
|
||||||
throw new UserError(`You don't have enough privileges`);
|
|
||||||
|
|
||||||
return dms.updateAttribute('dmsTypeFk', trashDmsType.id);
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const models = Self.app.models;
|
||||||
|
const dms = await models.Dms.findById(id, null, myOptions);
|
||||||
|
const trashDmsType = await models.DmsType.findOne({
|
||||||
|
where: {code: 'trash'}
|
||||||
|
}, myOptions);
|
||||||
|
|
||||||
|
const hasWriteRole = await models.DmsType.hasWriteRole(ctx, dms.dmsTypeFk, myOptions);
|
||||||
|
if (!hasWriteRole)
|
||||||
|
throw new UserError(`You don't have enough privileges`);
|
||||||
|
|
||||||
|
await dms.updateAttribute('dmsTypeFk', trashDmsType.id, myOptions);
|
||||||
|
|
||||||
|
if (tx) await tx.commit();
|
||||||
|
|
||||||
|
return dms;
|
||||||
|
} catch (e) {
|
||||||
|
if (tx) await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,25 +8,23 @@
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"id": {
|
"id": {
|
||||||
"type": "Number",
|
"type": "number",
|
||||||
"id": true,
|
"id": true,
|
||||||
"description": "The id"
|
"description": "The id"
|
||||||
},
|
},
|
||||||
"name": {
|
"name": {
|
||||||
"type": "String",
|
"type": "string",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
"collectionFk": {
|
"collectionFk": {
|
||||||
"type": "String",
|
"type": "string",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
"updated": {
|
"updated": {
|
||||||
"type": "Number"
|
"type": "number"
|
||||||
},
|
},
|
||||||
"nRefs": {
|
"nRefs": {
|
||||||
"type": "Number",
|
"type": "number"
|
||||||
"required": true,
|
|
||||||
"default": 1
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"relations": {
|
"relations": {
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
ALTER TABLE `vn`.`department`
|
|
||||||
ADD code VARCHAR(45) NULL AFTER id;
|
|
||||||
|
|
||||||
UPDATE `vn`.`department` t SET t.code = 'IT', t.chatName = 'informatica-cau' WHERE t.id = 31;
|
|
|
@ -1,2 +0,0 @@
|
||||||
ALTER TABLE `vn`.`itemImageQueue`
|
|
||||||
ADD attempts INT default 0 NULL AFTER error;
|
|
|
@ -1,5 +0,0 @@
|
||||||
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
|
||||||
VALUES
|
|
||||||
('SupplierAccount', '*', '*', 'ALLOW', 'ROLE', 'administrative'),
|
|
||||||
('Entry', '*', '*', 'ALLOW', 'ROLE', 'administrative'),
|
|
||||||
('InvoiceIn', '*', '*', 'ALLOW', 'ROLE', 'administrative');
|
|
|
@ -1,137 +0,0 @@
|
||||||
DROP PROCEDURE `vn`.`item_getBalance`;
|
|
||||||
|
|
||||||
DELIMITER $$
|
|
||||||
$$
|
|
||||||
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`item_getBalance`(IN vItemId INT, IN vWarehouse INT)
|
|
||||||
BEGIN
|
|
||||||
DECLARE vDateInventory DATETIME;
|
|
||||||
DECLARE vCurdate DATE DEFAULT CURDATE();
|
|
||||||
DECLARE vDayEnd DATETIME DEFAULT util.dayEnd(vCurdate);
|
|
||||||
|
|
||||||
SELECT inventoried INTO vDateInventory FROM config;
|
|
||||||
SET @a = 0;
|
|
||||||
SET @currentLineFk = 0;
|
|
||||||
SET @shipped = '';
|
|
||||||
|
|
||||||
SELECT DATE(@shipped:= shipped) shipped,
|
|
||||||
alertLevel,
|
|
||||||
stateName,
|
|
||||||
origin,
|
|
||||||
reference,
|
|
||||||
clientFk,
|
|
||||||
name,
|
|
||||||
`in`,
|
|
||||||
`out`,
|
|
||||||
@a := @a + IFNULL(`in`,0) - IFNULL(`out`,0) as balance,
|
|
||||||
@currentLineFk := IF (@shipped < CURDATE()
|
|
||||||
OR (@shipped = CURDATE() AND (isPicked OR alertLevel >= 2)),
|
|
||||||
lineFk,@currentLineFk) lastPreparedLineFk,
|
|
||||||
isTicket,
|
|
||||||
lineFk,
|
|
||||||
isPicked,
|
|
||||||
clientType
|
|
||||||
FROM
|
|
||||||
( SELECT tr.landed AS shipped,
|
|
||||||
b.quantity AS `in`,
|
|
||||||
NULL AS `out`,
|
|
||||||
al.alertLevel AS alertLevel,
|
|
||||||
st.name AS stateName,
|
|
||||||
s.name AS name,
|
|
||||||
e.ref AS reference,
|
|
||||||
e.id AS origin,
|
|
||||||
s.id AS clientFk,
|
|
||||||
IF(al.alertLevel = 3, TRUE, FALSE) isPicked,
|
|
||||||
FALSE AS isTicket,
|
|
||||||
b.id lineFk,
|
|
||||||
NULL `order`,
|
|
||||||
NULL AS clientType
|
|
||||||
FROM buy b
|
|
||||||
JOIN entry e ON e.id = b.entryFk
|
|
||||||
JOIN travel tr ON tr.id = e.travelFk
|
|
||||||
JOIN supplier s ON s.id = e.supplierFk
|
|
||||||
JOIN alertLevel al ON al.alertLevel =
|
|
||||||
CASE
|
|
||||||
WHEN tr.shipped < CURDATE() THEN 3
|
|
||||||
WHEN tr.shipped = CURDATE() AND tr.isReceived = TRUE THEN 3
|
|
||||||
ELSE 0
|
|
||||||
END
|
|
||||||
JOIN state st ON st.code = al.code
|
|
||||||
WHERE tr.landed >= vDateInventory
|
|
||||||
AND vWarehouse = tr.warehouseInFk
|
|
||||||
AND b.itemFk = vItemId
|
|
||||||
AND e.isInventory = FALSE
|
|
||||||
AND e.isRaid = FALSE
|
|
||||||
UNION ALL
|
|
||||||
|
|
||||||
SELECT tr.shipped,
|
|
||||||
NULL as `in`,
|
|
||||||
b.quantity AS `out`,
|
|
||||||
al.alertLevel AS alertLevel,
|
|
||||||
st.name AS stateName,
|
|
||||||
s.name AS name,
|
|
||||||
e.ref AS reference,
|
|
||||||
e.id AS origin,
|
|
||||||
s.id AS clientFk,
|
|
||||||
IF(al.alertLevel = 3, TRUE, FALSE) isPicked,
|
|
||||||
FALSE AS isTicket,
|
|
||||||
b.id,
|
|
||||||
NULL `order`,
|
|
||||||
NULL AS clientType
|
|
||||||
FROM buy b
|
|
||||||
JOIN entry e ON e.id = b.entryFk
|
|
||||||
JOIN travel tr ON tr.id = e.travelFk
|
|
||||||
JOIN warehouse w ON w.id = tr.warehouseOutFk
|
|
||||||
JOIN supplier s ON s.id = e.supplierFk
|
|
||||||
JOIN alertLevel al ON al.alertLevel =
|
|
||||||
CASE
|
|
||||||
WHEN tr.shipped < CURDATE() THEN 3
|
|
||||||
WHEN tr.shipped = CURDATE() AND tr.isReceived = TRUE THEN 3
|
|
||||||
ELSE 0
|
|
||||||
END
|
|
||||||
JOIN state st ON st.code = al.code
|
|
||||||
WHERE tr.shipped >= vDateInventory
|
|
||||||
AND vWarehouse =tr.warehouseOutFk
|
|
||||||
AND s.id <> 4
|
|
||||||
AND b.itemFk = vItemId
|
|
||||||
AND e.isInventory = FALSE
|
|
||||||
AND w.isFeedStock = FALSE
|
|
||||||
AND e.isRaid = FALSE
|
|
||||||
UNION ALL
|
|
||||||
|
|
||||||
SELECT DATE(t.shipped),
|
|
||||||
NULL as `in`,
|
|
||||||
s.quantity AS `out`,
|
|
||||||
al.alertLevel AS alertLevel,
|
|
||||||
st.name AS stateName,
|
|
||||||
t.nickname AS name,
|
|
||||||
t.refFk AS reference,
|
|
||||||
t.id AS origin,
|
|
||||||
t.clientFk,
|
|
||||||
stk.id AS isPicked,
|
|
||||||
TRUE AS isTicket,
|
|
||||||
s.id,
|
|
||||||
st.`order`,
|
|
||||||
ct.code AS clientType
|
|
||||||
FROM sale s
|
|
||||||
JOIN ticket t ON t.id = s.ticketFk
|
|
||||||
LEFT JOIN ticketState ts ON ts.ticket = t.id
|
|
||||||
LEFT JOIN state st ON st.code = ts.code
|
|
||||||
JOIN client c ON c.id = t.clientFk
|
|
||||||
JOIN clientType ct ON ct.id = c.clientTypeFk
|
|
||||||
JOIN alertLevel al ON al.alertLevel =
|
|
||||||
CASE
|
|
||||||
WHEN t.shipped < curdate() THEN 3
|
|
||||||
WHEN t.shipped > util.dayEnd(curdate()) THEN 0
|
|
||||||
ELSE IFNULL(ts.alertLevel, 0)
|
|
||||||
END
|
|
||||||
LEFT JOIN state stPrep ON stPrep.`code` = 'PREPARED'
|
|
||||||
LEFT JOIN saleTracking stk ON stk.saleFk = s.id AND stk.stateFk = stPrep.id
|
|
||||||
WHERE t.shipped >= vDateInventory
|
|
||||||
AND s.itemFk = vItemId
|
|
||||||
AND vWarehouse =t.warehouseFk
|
|
||||||
ORDER BY shipped, alertLevel DESC, isTicket, `order` DESC, isPicked DESC, `in` DESC, `out` DESC
|
|
||||||
) AS itemDiary;
|
|
||||||
|
|
||||||
END$$
|
|
||||||
DELIMITER ;
|
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
ALTER TABLE `vn`.`supplier` ADD COLUMN `workerFk` INT(11) NULL DEFAULT NULL COMMENT 'Responsible for approving invoices' AFTER `isTrucker`;
|
|
||||||
ALTER TABLE `vn`.`supplier` ADD CONSTRAINT `supplier_workerFk` FOREIGN KEY (`workerFk`) REFERENCES `vn`.`worker` (`id`) ON UPDATE CASCADE;
|
|
|
@ -1,4 +0,0 @@
|
||||||
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
|
||||||
VALUES
|
|
||||||
('StarredModule', '*', '*', 'ALLOW', 'ROLE', 'employee'),
|
|
||||||
('ItemBotanical', '*', 'WRITE', 'ALLOW', 'ROLE', 'logisticBoss');
|
|
|
@ -1,20 +0,0 @@
|
||||||
CREATE TABLE `salix`.`module` (
|
|
||||||
`code` VARCHAR(45) COLLATE utf8_unicode_ci NOT NULL,
|
|
||||||
PRIMARY KEY (`code`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
|
||||||
|
|
||||||
INSERT INTO `salix`.`module`(`code`)
|
|
||||||
VALUES
|
|
||||||
('Items'),
|
|
||||||
('Orders'),
|
|
||||||
('Clients'),
|
|
||||||
('Entries'),
|
|
||||||
('Travels'),
|
|
||||||
('Invoices out'),
|
|
||||||
('Suppliers'),
|
|
||||||
('Claims'),
|
|
||||||
('Routes'),
|
|
||||||
('Tickets'),
|
|
||||||
('Workers'),
|
|
||||||
('Users'),
|
|
||||||
('Zones');
|
|
|
@ -1,10 +0,0 @@
|
||||||
CREATE TABLE `vn`.`starredModule` (
|
|
||||||
`id` INT(11) unsigned NOT NULL AUTO_INCREMENT,
|
|
||||||
`workerFk` INT(10) NOT NULL,
|
|
||||||
`moduleFk` VARCHAR(45) COLLATE utf8_unicode_ci NOT NULL,
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY `starred_workerFk` (`workerFk`),
|
|
||||||
KEY `starred_moduleFk` (`moduleFk`),
|
|
||||||
CONSTRAINT `starred_workerFk` FOREIGN KEY (`workerFk`) REFERENCES `vn`.`worker` (`id`) ON UPDATE CASCADE,
|
|
||||||
CONSTRAINT `starred_moduleFk` FOREIGN KEY (`moduleFk`) REFERENCES `salix`.`module` (`code`) ON UPDATE CASCADE
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
|
|
@ -1,5 +0,0 @@
|
||||||
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
|
||||||
VALUES
|
|
||||||
('Genus', '*', 'WRITE', 'ALLOW', 'ROLE', 'logisticBoss'),
|
|
||||||
('Specie', '*', 'WRITE', 'ALLOW', 'ROLE', 'logisticBoss'),
|
|
||||||
('InvoiceOut', 'createPdf', 'WRITE', 'ALLOW', 'ROLE', 'invoicing');
|
|
File diff suppressed because one or more lines are too long
|
@ -294,6 +294,10 @@ INSERT INTO `vn`.`clientManaCache`(`clientFk`, `mana`, `dated`)
|
||||||
(103, 0, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
|
(103, 0, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
|
||||||
(104, -30, DATE_ADD(CURDATE(), INTERVAL -1 MONTH));
|
(104, -30, DATE_ADD(CURDATE(), INTERVAL -1 MONTH));
|
||||||
|
|
||||||
|
INSERT INTO `vn`.`clientConfig`(`riskTolerance`)
|
||||||
|
VALUES
|
||||||
|
(200);
|
||||||
|
|
||||||
INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `provinceFk`, `phone`, `mobile`, `isActive`, `clientFk`, `agencyModeFk`, `longitude`, `latitude`, `isEqualizated`, `isDefaultAddress`)
|
INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `provinceFk`, `phone`, `mobile`, `isActive`, `clientFk`, `agencyModeFk`, `longitude`, `latitude`, `isEqualizated`, `isDefaultAddress`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 'Bruce Wayne', '1007 Mountain Drive, Gotham', 'Silla', 46460, 1, 1111111111, 222222222, 1, 101, 2, NULL, NULL, 0, 1),
|
(1, 'Bruce Wayne', '1007 Mountain Drive, Gotham', 'Silla', 46460, 1, 1111111111, 222222222, 1, 101, 2, NULL, NULL, 0, 1),
|
||||||
|
@ -711,14 +715,14 @@ INSERT INTO `vn`.`itemCategory`(`id`, `name`, `display`, `color`, `icon`, `code`
|
||||||
(7, 'Accessories', 1, NULL, 'icon-accessory', 'accessory'),
|
(7, 'Accessories', 1, NULL, 'icon-accessory', 'accessory'),
|
||||||
(8, 'Fruit', 1, NULL, 'icon-fruit', 'fruit');
|
(8, 'Fruit', 1, NULL, 'icon-fruit', 'fruit');
|
||||||
|
|
||||||
INSERT INTO `vn`.`itemType`(`id`, `code`, `name`, `categoryFk`, `life`,`workerFk`, `isPackaging`)
|
INSERT INTO `vn`.`itemType`(`id`, `code`, `name`, `categoryFk`, `warehouseFk`, `life`,`workerFk`, `isPackaging`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 'CRI', 'Crisantemo', 2, 31, 35, 0),
|
(1, 'CRI', 'Crisantemo', 2, 1, 31, 35, 0),
|
||||||
(2, 'ITG', 'Anthurium', 1, 31, 35, 0),
|
(2, 'ITG', 'Anthurium', 1, 1, 31, 35, 0),
|
||||||
(3, 'WPN', 'Paniculata', 2, 31, 35, 0),
|
(3, 'WPN', 'Paniculata', 2, 1, 31, 35, 0),
|
||||||
(4, 'PRT', 'Delivery ports', 3, NULL, 35, 1),
|
(4, 'PRT', 'Delivery ports', 3, 1, NULL, 35, 1),
|
||||||
(5, 'CON', 'Container', 3, NULL, 35, 1),
|
(5, 'CON', 'Container', 3, 1, NULL, 35, 1),
|
||||||
(6, 'ALS', 'Alstroemeria', 1, 31, 35, 0);
|
(6, 'ALS', 'Alstroemeria', 1, 1, 31, 35, 0);
|
||||||
|
|
||||||
INSERT INTO `vn`.`ink`(`id`, `name`, `picture`, `showOrder`, `hex`)
|
INSERT INTO `vn`.`ink`(`id`, `name`, `picture`, `showOrder`, `hex`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -2259,7 +2263,10 @@ INSERT INTO `vn`.`duaInvoiceIn`(`id`, `duaFk`, `invoiceInFk`)
|
||||||
(10, 10, 10);
|
(10, 10, 10);
|
||||||
|
|
||||||
INSERT INTO `vn`.`ticketRecalc`(`ticketFk`)
|
INSERT INTO `vn`.`ticketRecalc`(`ticketFk`)
|
||||||
SELECT `id` FROM `vn`.`ticket`;
|
SELECT `id`
|
||||||
|
FROM `vn`.`ticket` t
|
||||||
|
LEFT JOIN vn.ticketRecalc tr ON tr.ticketFk = t.id
|
||||||
|
WHERE tr.ticketFk IS NULL;
|
||||||
|
|
||||||
CALL `vn`.`ticket_doRecalc`();
|
CALL `vn`.`ticket_doRecalc`();
|
||||||
|
|
||||||
|
|
10056
db/dump/structure.sql
10056
db/dump/structure.sql
File diff suppressed because it is too large
Load Diff
|
@ -86,6 +86,8 @@ IGNORETABLES=(
|
||||||
--ignore-table=vn.warehouseJoined
|
--ignore-table=vn.warehouseJoined
|
||||||
--ignore-table=vn.workerTeam__
|
--ignore-table=vn.workerTeam__
|
||||||
--ignore-table=vn.XDiario__
|
--ignore-table=vn.XDiario__
|
||||||
|
--ignore-table=sage.movConta
|
||||||
|
--ignore-table=sage.movContaCopia
|
||||||
)
|
)
|
||||||
mysqldump \
|
mysqldump \
|
||||||
--defaults-file=config.production.ini \
|
--defaults-file=config.production.ini \
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
const app = require('vn-loopback/server/server');
|
||||||
|
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||||
|
|
||||||
|
describe('item_getBalance()', () => {
|
||||||
|
it(`should return the item balance ordered by alert level`, async() => {
|
||||||
|
let stmts = [];
|
||||||
|
|
||||||
|
let params = {
|
||||||
|
warehouseFk: 1,
|
||||||
|
itemFk: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
const conn = await app.models.Item.dataSource.connector;
|
||||||
|
|
||||||
|
stmts.push(new ParameterizedSQL('CALL vn.item_getBalance(?, ?)', [
|
||||||
|
params.warehouseFk,
|
||||||
|
params.itemFk
|
||||||
|
]));
|
||||||
|
|
||||||
|
let sql = ParameterizedSQL.join(stmts, ';');
|
||||||
|
let result = await conn.executeStmt(sql);
|
||||||
|
let itemBalance = result[0];
|
||||||
|
|
||||||
|
expect(itemBalance[0].alertLevel).toBeGreaterThanOrEqual(itemBalance[1].alertLevel);
|
||||||
|
expect(itemBalance[1].alertLevel).toBeGreaterThanOrEqual(itemBalance[2].alertLevel);
|
||||||
|
expect(itemBalance[2].alertLevel).toBeGreaterThanOrEqual(itemBalance[3].alertLevel);
|
||||||
|
expect(itemBalance[3].alertLevel).toBeGreaterThanOrEqual(itemBalance[4].alertLevel);
|
||||||
|
expect(itemBalance[4].alertLevel).toBeGreaterThanOrEqual(itemBalance[5].alertLevel);
|
||||||
|
expect(itemBalance[5].alertLevel).toBeGreaterThanOrEqual(itemBalance[6].alertLevel);
|
||||||
|
});
|
||||||
|
});
|
|
@ -59,6 +59,6 @@ describe('Account create and basic data path', () => {
|
||||||
await page.accessToSection('account.card.roles');
|
await page.accessToSection('account.card.roles');
|
||||||
const rolesCount = await page.countElement(selectors.accountRoles.anyResult);
|
const rolesCount = await page.countElement(selectors.accountRoles.anyResult);
|
||||||
|
|
||||||
expect(rolesCount).toEqual(3);
|
expect(rolesCount).toEqual(4);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -81,6 +81,6 @@ describe('Account Role create and basic data path', () => {
|
||||||
await page.accessToSection('account.role.card.inherited');
|
await page.accessToSection('account.role.card.inherited');
|
||||||
const rolesCount = await page.countElement(selectors.accountRoleInheritance.anyResult);
|
const rolesCount = await page.countElement(selectors.accountRoleInheritance.anyResult);
|
||||||
|
|
||||||
expect(rolesCount).toEqual(6);
|
expect(rolesCount).toEqual(7);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,7 +3,7 @@ module.exports = Self => {
|
||||||
description: 'Returns a list of allowed contentTypes',
|
description: 'Returns a list of allowed contentTypes',
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
returns: {
|
returns: {
|
||||||
type: ['Object'],
|
type: ['object'],
|
||||||
root: true
|
root: true
|
||||||
},
|
},
|
||||||
http: {
|
http: {
|
||||||
|
|
|
@ -4,12 +4,12 @@ module.exports = Self => {
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: {
|
accepts: {
|
||||||
arg: 'id',
|
arg: 'id',
|
||||||
type: 'Number',
|
type: 'number',
|
||||||
description: 'The document id',
|
description: 'The document id',
|
||||||
http: {source: 'path'}
|
http: {source: 'path'}
|
||||||
},
|
},
|
||||||
returns: {
|
returns: {
|
||||||
type: 'Object',
|
type: 'object',
|
||||||
root: true
|
root: true
|
||||||
},
|
},
|
||||||
http: {
|
http: {
|
||||||
|
@ -18,16 +18,36 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.removeFile = async(ctx, id) => {
|
Self.removeFile = async(ctx, id, options) => {
|
||||||
const models = Self.app.models;
|
let tx;
|
||||||
const targetClaimDms = await models.ClaimDms.findById(id);
|
let myOptions = {};
|
||||||
const targetDms = await models.Dms.findById(targetClaimDms.dmsFk);
|
|
||||||
const trashDmsType = await models.DmsType.findOne({where: {code: 'trash'}});
|
|
||||||
|
|
||||||
await models.Dms.removeFile(ctx, targetClaimDms.dmsFk);
|
if (typeof options == 'object')
|
||||||
await targetClaimDms.destroy();
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
return targetDms.updateAttribute('dmsTypeFk', trashDmsType.id);
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const models = Self.app.models;
|
||||||
|
const targetClaimDms = await models.ClaimDms.findById(id, null, myOptions);
|
||||||
|
const targetDms = await models.Dms.findById(targetClaimDms.dmsFk, null, myOptions);
|
||||||
|
const trashDmsType = await models.DmsType.findOne({where: {code: 'trash'}}, myOptions);
|
||||||
|
|
||||||
|
await models.Dms.removeFile(ctx, targetClaimDms.dmsFk, myOptions);
|
||||||
|
await targetClaimDms.destroy(myOptions);
|
||||||
|
|
||||||
|
await targetDms.updateAttribute('dmsTypeFk', trashDmsType.id, myOptions);
|
||||||
|
|
||||||
|
if (tx) await tx.commit();
|
||||||
|
|
||||||
|
return targetDms;
|
||||||
|
} catch (e) {
|
||||||
|
if (tx) await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -17,24 +17,45 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.importTicketSales = async(ctx, params) => {
|
Self.importTicketSales = async(ctx, params, options) => {
|
||||||
let models = Self.app.models;
|
let models = Self.app.models;
|
||||||
let userId = ctx.req.accessToken.userId;
|
let userId = ctx.req.accessToken.userId;
|
||||||
let worker = await models.Worker.findOne({where: {userFk: userId}});
|
|
||||||
|
|
||||||
let ticketSales = await models.Sale.find({
|
let tx;
|
||||||
where: {ticketFk: params.ticketFk}
|
let myOptions = {};
|
||||||
});
|
|
||||||
|
|
||||||
let claimEnds = [];
|
if (typeof options == 'object')
|
||||||
ticketSales.forEach(sale => {
|
Object.assign(myOptions, options);
|
||||||
claimEnds.push({
|
|
||||||
saleFk: sale.id,
|
if (!myOptions.transaction) {
|
||||||
claimFk: params.claimFk,
|
tx = await Self.beginTransaction({});
|
||||||
workerFk: worker.id
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const worker = await models.Worker.findOne({where: {userFk: userId}}, myOptions);
|
||||||
|
|
||||||
|
let ticketSales = await models.Sale.find({
|
||||||
|
where: {ticketFk: params.ticketFk}
|
||||||
|
}, myOptions);
|
||||||
|
|
||||||
|
let claimEnds = [];
|
||||||
|
ticketSales.forEach(sale => {
|
||||||
|
claimEnds.push({
|
||||||
|
saleFk: sale.id,
|
||||||
|
claimFk: params.claimFk,
|
||||||
|
workerFk: worker.id
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
return await Self.create(claimEnds);
|
const createdClaimEnds = await Self.create(claimEnds, myOptions);
|
||||||
|
|
||||||
|
if (tx) await tx.commit();
|
||||||
|
|
||||||
|
return createdClaimEnds;
|
||||||
|
} catch (e) {
|
||||||
|
if (tx) await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,25 +1,26 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('Claim importTicketSales()', () => {
|
describe('Claim importTicketSales()', () => {
|
||||||
let claimEnds;
|
|
||||||
|
|
||||||
afterAll(async done => {
|
|
||||||
claimEnds.forEach(async line => {
|
|
||||||
await line.destroy();
|
|
||||||
});
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should import sales to a claim actions from an specific ticket', async() => {
|
it('should import sales to a claim actions from an specific ticket', async() => {
|
||||||
let ctx = {req: {accessToken: {userId: 5}}};
|
const ctx = {req: {accessToken: {userId: 5}}};
|
||||||
claimEnds = await app.models.ClaimEnd.importTicketSales(ctx, {
|
|
||||||
claimFk: 1,
|
|
||||||
ticketFk: 1
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(claimEnds.length).toEqual(4);
|
const tx = await app.models.Entry.beginTransaction({});
|
||||||
expect(claimEnds[0].saleFk).toEqual(1);
|
try {
|
||||||
expect(claimEnds[2].saleFk).toEqual(3);
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
const claimEnds = await app.models.ClaimEnd.importTicketSales(ctx, {
|
||||||
|
claimFk: 1,
|
||||||
|
ticketFk: 1
|
||||||
|
}, options);
|
||||||
|
|
||||||
|
expect(claimEnds.length).toEqual(4);
|
||||||
|
expect(claimEnds[0].saleFk).toEqual(1);
|
||||||
|
expect(claimEnds[2].saleFk).toEqual(3);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -24,15 +24,22 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.createFromSales = async(ctx, ticketId, sales) => {
|
Self.createFromSales = async(ctx, ticketId, sales, options) => {
|
||||||
|
let tx;
|
||||||
|
let myOptions = {};
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const userId = ctx.req.accessToken.userId;
|
const userId = ctx.req.accessToken.userId;
|
||||||
const tx = await Self.beginTransaction({});
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let options = {transaction: tx};
|
const ticket = await models.Ticket.findById(ticketId, null, myOptions);
|
||||||
|
|
||||||
const ticket = await models.Ticket.findById(ticketId, null, options);
|
|
||||||
if (ticket.isDeleted)
|
if (ticket.isDeleted)
|
||||||
throw new UserError(`You can't create a claim for a removed ticket`);
|
throw new UserError(`You can't create a claim for a removed ticket`);
|
||||||
|
|
||||||
|
@ -41,7 +48,7 @@ module.exports = Self => {
|
||||||
clientFk: ticket.clientFk,
|
clientFk: ticket.clientFk,
|
||||||
ticketCreated: ticket.shipped,
|
ticketCreated: ticket.shipped,
|
||||||
workerFk: userId
|
workerFk: userId
|
||||||
}, options);
|
}, myOptions);
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
|
||||||
for (const sale of sales) {
|
for (const sale of sales) {
|
||||||
|
@ -49,17 +56,18 @@ module.exports = Self => {
|
||||||
saleFk: sale.id,
|
saleFk: sale.id,
|
||||||
claimFk: newClaim.id,
|
claimFk: newClaim.id,
|
||||||
quantity: sale.quantity
|
quantity: sale.quantity
|
||||||
}, options);
|
}, myOptions);
|
||||||
|
|
||||||
promises.push(newClaimBeginning);
|
promises.push(newClaimBeginning);
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
|
|
||||||
await tx.commit();
|
if (tx) await tx.commit();
|
||||||
|
|
||||||
return newClaim;
|
return newClaim;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
await tx.rollback();
|
if (tx) await tx.rollback();
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,58 +10,67 @@ module.exports = Self => {
|
||||||
accepts: [
|
accepts: [
|
||||||
{
|
{
|
||||||
arg: 'filter',
|
arg: 'filter',
|
||||||
type: 'Object',
|
type: 'object',
|
||||||
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
|
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
|
||||||
http: {source: 'query'}
|
http: {source: 'query'}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
arg: 'tags',
|
arg: 'tags',
|
||||||
type: ['Object'],
|
type: ['object'],
|
||||||
description: 'List of tags to filter with',
|
description: 'List of tags to filter with',
|
||||||
http: {source: 'query'}
|
http: {source: 'query'}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
arg: 'search',
|
arg: 'search',
|
||||||
type: 'String',
|
type: 'string',
|
||||||
description: `If it's and integer searchs by id, otherwise it searchs by client name`,
|
description: `If it's and integer searchs by id, otherwise it searchs by client name`,
|
||||||
http: {source: 'query'}
|
http: {source: 'query'}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
arg: 'client',
|
arg: 'client',
|
||||||
type: 'String',
|
type: 'string',
|
||||||
description: 'The worker name',
|
description: 'The worker name',
|
||||||
http: {source: 'query'}
|
http: {source: 'query'}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
arg: 'id',
|
arg: 'id',
|
||||||
type: 'Integer',
|
type: 'integer',
|
||||||
description: 'The claim id',
|
description: 'The claim id',
|
||||||
http: {source: 'query'}
|
http: {source: 'query'}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
arg: 'clientFk',
|
arg: 'clientFk',
|
||||||
type: 'Integer',
|
type: 'integer',
|
||||||
description: 'The client id',
|
description: 'The client id',
|
||||||
http: {source: 'query'}
|
http: {source: 'query'}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
arg: 'claimStateFk',
|
arg: 'claimStateFk',
|
||||||
type: 'Integer',
|
type: 'integer',
|
||||||
description: 'The claim state id',
|
description: 'The claim state id',
|
||||||
http: {source: 'query'}
|
http: {source: 'query'}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
arg: 'salesPersonFk',
|
arg: 'salesPersonFk',
|
||||||
type: 'Integer',
|
type: 'integer',
|
||||||
description: 'The salesPerson id',
|
description: 'The salesPerson id',
|
||||||
http: {source: 'query'}
|
http: {source: 'query'}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
arg: 'attenderFk',
|
arg: 'attenderFk',
|
||||||
type: 'Integer',
|
type: 'integer',
|
||||||
description: 'The attender worker id',
|
description: 'The attender worker id',
|
||||||
http: {source: 'query'}
|
http: {source: 'query'}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
arg: 'created',
|
arg: 'created',
|
||||||
type: 'Date',
|
type: 'date',
|
||||||
description: 'The to date filter',
|
description: 'The to date filter',
|
||||||
http: {source: 'query'}
|
http: {source: 'query'}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
returns: {
|
returns: {
|
||||||
type: ['Object'],
|
type: ['object'],
|
||||||
root: true
|
root: true
|
||||||
},
|
},
|
||||||
http: {
|
http: {
|
||||||
|
|
|
@ -18,32 +18,39 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.regularizeClaim = async(ctx, claimFk) => {
|
Self.regularizeClaim = async(ctx, claimFk, options) => {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const $t = ctx.req.__; // $translate
|
const $t = ctx.req.__; // $translate
|
||||||
const resolvedState = 3;
|
const resolvedState = 3;
|
||||||
|
|
||||||
let tx = await Self.beginTransaction({});
|
let tx;
|
||||||
try {
|
let myOptions = {};
|
||||||
let options = {transaction: tx};
|
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
const claimEnds = await models.ClaimEnd.find({
|
const claimEnds = await models.ClaimEnd.find({
|
||||||
include: {
|
include: {
|
||||||
relation: 'claimDestination',
|
relation: 'claimDestination',
|
||||||
fields: ['addressFk']
|
fields: ['addressFk']
|
||||||
},
|
},
|
||||||
where: {claimFk: claimFk}
|
where: {claimFk: claimFk}
|
||||||
}, options);
|
}, myOptions);
|
||||||
|
|
||||||
for (let i = 0; i < claimEnds.length; i++) {
|
for (let claimEnd of claimEnds) {
|
||||||
const claimEnd = claimEnds[i];
|
|
||||||
const destination = claimEnd.claimDestination();
|
const destination = claimEnd.claimDestination();
|
||||||
const sale = await getSale(claimEnd.saleFk, options);
|
const sale = await getSale(claimEnd.saleFk, myOptions);
|
||||||
const addressId = destination && destination.addressFk;
|
const addressId = destination && destination.addressFk;
|
||||||
|
|
||||||
let address;
|
let address;
|
||||||
if (addressId)
|
if (addressId)
|
||||||
address = await models.Address.findById(addressId, null, options);
|
address = await models.Address.findById(addressId, null, myOptions);
|
||||||
|
|
||||||
const salesPerson = sale.ticket().client().salesPersonUser();
|
const salesPerson = sale.ticket().client().salesPersonUser();
|
||||||
if (salesPerson) {
|
if (salesPerson) {
|
||||||
|
@ -67,7 +74,7 @@ module.exports = Self => {
|
||||||
addressFk: addressId,
|
addressFk: addressId,
|
||||||
companyFk: sale.ticket().companyFk,
|
companyFk: sale.ticket().companyFk,
|
||||||
warehouseFk: sale.ticket().warehouseFk
|
warehouseFk: sale.ticket().warehouseFk
|
||||||
}, options);
|
}, myOptions);
|
||||||
|
|
||||||
if (!ticketFk) {
|
if (!ticketFk) {
|
||||||
ticketFk = await createTicket(ctx, {
|
ticketFk = await createTicket(ctx, {
|
||||||
|
@ -75,7 +82,7 @@ module.exports = Self => {
|
||||||
warehouseId: sale.ticket().warehouseFk,
|
warehouseId: sale.ticket().warehouseFk,
|
||||||
companyId: sale.ticket().companyFk,
|
companyId: sale.ticket().companyFk,
|
||||||
addressId: addressId
|
addressId: addressId
|
||||||
}, options);
|
}, myOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
await models.Sale.create({
|
await models.Sale.create({
|
||||||
|
@ -85,19 +92,19 @@ module.exports = Self => {
|
||||||
quantity: -sale.quantity,
|
quantity: -sale.quantity,
|
||||||
price: sale.price,
|
price: sale.price,
|
||||||
discount: 100
|
discount: 100
|
||||||
}, options);
|
}, myOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
let claim = await Self.findById(claimFk, null, options);
|
let claim = await Self.findById(claimFk, null, myOptions);
|
||||||
claim = await claim.updateAttributes({
|
claim = await claim.updateAttributes({
|
||||||
claimStateFk: resolvedState
|
claimStateFk: resolvedState
|
||||||
}, options);
|
}, myOptions);
|
||||||
|
|
||||||
await tx.commit();
|
if (tx) await tx.commit();
|
||||||
|
|
||||||
return claim;
|
return claim;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
await tx.rollback();
|
if (tx) await tx.rollback();
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,36 +10,45 @@ describe('Claim createFromSales()', () => {
|
||||||
const ctx = {req: {accessToken: {userId: 1}}};
|
const ctx = {req: {accessToken: {userId: 1}}};
|
||||||
|
|
||||||
it('should create a new claim', async() => {
|
it('should create a new claim', async() => {
|
||||||
let claim = await app.models.Claim.createFromSales(ctx, ticketId, newSale);
|
const tx = await app.models.Claim.beginTransaction({});
|
||||||
|
|
||||||
expect(claim.ticketFk).toEqual(ticketId);
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
let claimBeginning = await app.models.ClaimBeginning.findOne({where: {claimFk: claim.id}});
|
const claim = await app.models.Claim.createFromSales(ctx, ticketId, newSale, options);
|
||||||
|
|
||||||
expect(claimBeginning.saleFk).toEqual(newSale[0].id);
|
expect(claim.ticketFk).toEqual(ticketId);
|
||||||
expect(claimBeginning.quantity).toEqual(newSale[0].quantity);
|
|
||||||
|
|
||||||
const createdClaimId = claim.id;
|
let claimBeginning = await app.models.ClaimBeginning.findOne({where: {claimFk: claim.id}}, options);
|
||||||
|
|
||||||
// restores
|
expect(claimBeginning.saleFk).toEqual(newSale[0].id);
|
||||||
await app.models.Claim.destroyById(createdClaimId);
|
expect(claimBeginning.quantity).toEqual(newSale[0].quantity);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not be able to create a claim if exists that sale', async() => {
|
it('should not be able to create a claim if exists that sale', async() => {
|
||||||
let claim = await app.models.Claim.createFromSales(ctx, ticketId, newSale);
|
const tx = await app.models.Claim.beginTransaction({});
|
||||||
const createdClaimId = claim.id;
|
|
||||||
|
|
||||||
let error;
|
let error;
|
||||||
|
|
||||||
await app.models.Claim.createFromSales(ctx, ticketId, newSale)
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
.catch(e => {
|
await app.models.Claim.createFromSales(ctx, ticketId, newSale, options);
|
||||||
error = e;
|
|
||||||
});
|
await app.models.Claim.createFromSales(ctx, ticketId, newSale, options);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
error = e;
|
||||||
|
await tx.rollback();
|
||||||
|
}
|
||||||
|
|
||||||
expect(error.toString()).toContain(`A claim with that sale already exists`);
|
expect(error.toString()).toContain(`A claim with that sale already exists`);
|
||||||
|
|
||||||
// restores
|
|
||||||
await app.models.Claim.destroyById(createdClaimId);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -21,81 +21,94 @@ describe('regularizeClaim()', () => {
|
||||||
let claimEnds = [];
|
let claimEnds = [];
|
||||||
let trashTicket;
|
let trashTicket;
|
||||||
|
|
||||||
afterEach(async done => {
|
it('should send a chat message with value "Trash" and then change claim state to resolved', async() => {
|
||||||
|
const tx = await app.models.Claim.beginTransaction({});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let claim = await app.models.Claim.findById(claimFk);
|
const options = {transaction: tx};
|
||||||
await claim.updateAttributes({
|
|
||||||
claimStateFk: pendentState,
|
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
|
||||||
hasToPickUp: false
|
|
||||||
});
|
claimEnds = await app.models.ClaimEnd.importTicketSales(ctx, {
|
||||||
|
claimFk: claimFk,
|
||||||
|
ticketFk: 1
|
||||||
|
}, options);
|
||||||
|
|
||||||
for (claimEnd of claimEnds)
|
for (claimEnd of claimEnds)
|
||||||
await claimEnd.destroy();
|
await claimEnd.updateAttributes({claimDestinationFk: trashDestination}, options);
|
||||||
|
|
||||||
if (trashTicket)
|
let claimBefore = await app.models.Claim.findById(claimFk, null, options);
|
||||||
await app.models.Ticket.destroyById(trashTicket.id);
|
await app.models.Claim.regularizeClaim(ctx, claimFk, options);
|
||||||
} catch (error) {
|
let claimAfter = await app.models.Claim.findById(claimFk, null, options);
|
||||||
console.error(error);
|
|
||||||
|
trashTicket = await app.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;
|
||||||
}
|
}
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should send a chat message with value "Trash" and then change claim state to resolved', async() => {
|
|
||||||
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
|
|
||||||
|
|
||||||
claimEnds = await app.models.ClaimEnd.importTicketSales(ctx, {
|
|
||||||
claimFk: claimFk,
|
|
||||||
ticketFk: 1
|
|
||||||
});
|
|
||||||
|
|
||||||
for (claimEnd of claimEnds)
|
|
||||||
await claimEnd.updateAttributes({claimDestinationFk: trashDestination});
|
|
||||||
|
|
||||||
let claimBefore = await app.models.Claim.findById(claimFk);
|
|
||||||
await app.models.Claim.regularizeClaim(ctx, claimFk);
|
|
||||||
let claimAfter = await app.models.Claim.findById(claimFk);
|
|
||||||
|
|
||||||
trashTicket = await app.models.Ticket.findOne({where: {addressFk: 12}});
|
|
||||||
|
|
||||||
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);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should send a chat message with value "Bueno" and then change claim state to resolved', async() => {
|
it('should send a chat message with value "Bueno" and then change claim state to resolved', async() => {
|
||||||
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
|
const tx = await app.models.Claim.beginTransaction({});
|
||||||
|
|
||||||
claimEnds = await app.models.ClaimEnd.importTicketSales(ctx, {
|
try {
|
||||||
claimFk: claimFk,
|
const options = {transaction: tx};
|
||||||
ticketFk: 1
|
|
||||||
});
|
|
||||||
|
|
||||||
for (claimEnd of claimEnds)
|
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
|
||||||
await claimEnd.updateAttributes({claimDestinationFk: okDestination});
|
|
||||||
|
|
||||||
await app.models.Claim.regularizeClaim(ctx, claimFk);
|
claimEnds = await app.models.ClaimEnd.importTicketSales(ctx, {
|
||||||
|
claimFk: claimFk,
|
||||||
|
ticketFk: 1
|
||||||
|
}, options);
|
||||||
|
|
||||||
expect(chatModel.sendCheckingPresence).toHaveBeenCalledWith(ctx, 18, 'Bueno');
|
for (claimEnd of claimEnds)
|
||||||
expect(chatModel.sendCheckingPresence).toHaveBeenCalledTimes(4);
|
await claimEnd.updateAttributes({claimDestinationFk: okDestination}, options);
|
||||||
|
|
||||||
|
await app.models.Claim.regularizeClaim(ctx, claimFk, options);
|
||||||
|
|
||||||
|
expect(chatModel.sendCheckingPresence).toHaveBeenCalledWith(ctx, 18, 'Bueno');
|
||||||
|
expect(chatModel.sendCheckingPresence).toHaveBeenCalledTimes(4);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should send a chat message to the salesPerson when claim isPickUp is enabled', async() => {
|
it('should send a chat message to the salesPerson when claim isPickUp is enabled', async() => {
|
||||||
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
|
const tx = await app.models.Claim.beginTransaction({});
|
||||||
|
|
||||||
claimEnds = await app.models.ClaimEnd.importTicketSales(ctx, {
|
try {
|
||||||
claimFk: claimFk,
|
const options = {transaction: tx};
|
||||||
ticketFk: 1
|
|
||||||
});
|
|
||||||
|
|
||||||
for (claimEnd of claimEnds)
|
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
|
||||||
await claimEnd.updateAttributes({claimDestinationFk: okDestination});
|
|
||||||
|
|
||||||
await app.models.Claim.regularizeClaim(ctx, claimFk);
|
claimEnds = await app.models.ClaimEnd.importTicketSales(ctx, {
|
||||||
|
claimFk: claimFk,
|
||||||
|
ticketFk: 1
|
||||||
|
}, options);
|
||||||
|
|
||||||
expect(chatModel.sendCheckingPresence).toHaveBeenCalledWith(ctx, 18, 'Bueno');
|
for (claimEnd of claimEnds)
|
||||||
expect(chatModel.sendCheckingPresence).toHaveBeenCalledTimes(4);
|
await claimEnd.updateAttributes({claimDestinationFk: okDestination}, options);
|
||||||
|
|
||||||
|
await app.models.Claim.regularizeClaim(ctx, claimFk, options);
|
||||||
|
|
||||||
|
expect(chatModel.sendCheckingPresence).toHaveBeenCalledWith(ctx, 18, 'Bueno');
|
||||||
|
expect(chatModel.sendCheckingPresence).toHaveBeenCalledTimes(4);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('Update Claim', () => {
|
describe('Update Claim', () => {
|
||||||
let newDate = new Date();
|
const newDate = new Date();
|
||||||
const originalData = {
|
const originalData = {
|
||||||
ticketFk: 3,
|
ticketFk: 3,
|
||||||
clientFk: 101,
|
clientFk: 101,
|
||||||
|
@ -14,89 +14,114 @@ describe('Update Claim', () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
it(`should throw an error as the user doesn't have rights`, async() => {
|
it(`should throw an error as the user doesn't have rights`, async() => {
|
||||||
let newClaim = await app.models.Claim.create(originalData);
|
const tx = await app.models.Claim.beginTransaction({});
|
||||||
const forbiddenState = 3;
|
|
||||||
const salesPersonId = 18;
|
let error;
|
||||||
const ctx = {
|
|
||||||
req: {
|
try {
|
||||||
accessToken: {
|
const options = {transaction: tx};
|
||||||
userId: salesPersonId
|
|
||||||
|
const newClaim = await app.models.Claim.create(originalData, options);
|
||||||
|
|
||||||
|
const forbiddenState = 3;
|
||||||
|
const salesPersonId = 18;
|
||||||
|
const ctx = {
|
||||||
|
req: {
|
||||||
|
accessToken: {
|
||||||
|
userId: salesPersonId
|
||||||
|
}
|
||||||
|
},
|
||||||
|
args: {
|
||||||
|
claimStateFk: forbiddenState,
|
||||||
|
observation: 'valid observation'
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
args: {
|
await app.models.Claim.updateClaim(ctx, newClaim.id, options);
|
||||||
claimStateFk: forbiddenState,
|
|
||||||
observation: 'valid observation'
|
await tx.rollback();
|
||||||
}
|
} catch (e) {
|
||||||
};
|
error = e;
|
||||||
await app.models.Claim.updateClaim(ctx, newClaim.id)
|
await tx.rollback();
|
||||||
.catch(e => {
|
}
|
||||||
error = e;
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(error.message).toEqual(`You don't have enough privileges to change that field`);
|
expect(error.message).toEqual(`You don't have enough privileges to change that field`);
|
||||||
|
|
||||||
// restores
|
|
||||||
await app.models.Claim.destroyById(newClaim.id);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should success to update the claim within privileges `, async() => {
|
it(`should success to update the claim within privileges `, async() => {
|
||||||
let newClaim = await app.models.Claim.create(originalData);
|
const tx = await app.models.Claim.beginTransaction({});
|
||||||
|
|
||||||
const canceledState = 4;
|
try {
|
||||||
const claimManagerId = 72;
|
const options = {transaction: tx};
|
||||||
const ctx = {
|
|
||||||
req: {
|
const newClaim = await app.models.Claim.create(originalData, options);
|
||||||
accessToken: {
|
|
||||||
userId: claimManagerId
|
const canceledState = 4;
|
||||||
|
const claimManagerId = 72;
|
||||||
|
const ctx = {
|
||||||
|
req: {
|
||||||
|
accessToken: {
|
||||||
|
userId: claimManagerId
|
||||||
|
}
|
||||||
|
},
|
||||||
|
args: {
|
||||||
|
observation: 'valid observation',
|
||||||
|
claimStateFk: canceledState,
|
||||||
|
hasToPickUp: false
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
args: {
|
await app.models.Claim.updateClaim(ctx, newClaim.id, options);
|
||||||
observation: 'valid observation',
|
|
||||||
claimStateFk: canceledState,
|
|
||||||
hasToPickUp: false
|
|
||||||
}
|
|
||||||
};
|
|
||||||
await app.models.Claim.updateClaim(ctx, newClaim.id);
|
|
||||||
|
|
||||||
let updatedClaim = await app.models.Claim.findById(newClaim.id);
|
let updatedClaim = await app.models.Claim.findById(newClaim.id, null, options);
|
||||||
|
|
||||||
expect(updatedClaim.observation).toEqual(ctx.args.observation);
|
expect(updatedClaim.observation).toEqual(ctx.args.observation);
|
||||||
|
|
||||||
// restores
|
await tx.rollback();
|
||||||
await app.models.Claim.destroyById(newClaim.id);
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should change some sensible fields as claimManager', async() => {
|
it('should change some sensible fields as claimManager', async() => {
|
||||||
let newClaim = await app.models.Claim.create(originalData);
|
const tx = await app.models.Claim.beginTransaction({});
|
||||||
const chatModel = app.models.Chat;
|
|
||||||
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
|
|
||||||
|
|
||||||
const claimManagerId = 72;
|
try {
|
||||||
const ctx = {
|
const options = {transaction: tx};
|
||||||
req: {
|
|
||||||
accessToken: {userId: claimManagerId},
|
|
||||||
headers: {origin: 'http://localhost'}
|
|
||||||
},
|
|
||||||
args: {
|
|
||||||
claimStateFk: 3,
|
|
||||||
workerFk: 5,
|
|
||||||
observation: 'another valid observation',
|
|
||||||
hasToPickUp: true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
ctx.req.__ = (value, params) => {
|
|
||||||
return params.nickname;
|
|
||||||
};
|
|
||||||
await app.models.Claim.updateClaim(ctx, newClaim.id);
|
|
||||||
|
|
||||||
let updatedClaim = await app.models.Claim.findById(newClaim.id);
|
const newClaim = await app.models.Claim.create(originalData, options);
|
||||||
|
|
||||||
expect(updatedClaim.observation).toEqual(ctx.args.observation);
|
const chatModel = app.models.Chat;
|
||||||
expect(updatedClaim.claimStateFk).toEqual(ctx.args.claimStateFk);
|
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
|
||||||
expect(updatedClaim.workerFk).toEqual(ctx.args.workerFk);
|
|
||||||
expect(chatModel.sendCheckingPresence).toHaveBeenCalled();
|
|
||||||
|
|
||||||
// restores
|
const claimManagerId = 72;
|
||||||
await app.models.Claim.destroyById(newClaim.id);
|
const ctx = {
|
||||||
|
req: {
|
||||||
|
accessToken: {userId: claimManagerId},
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
},
|
||||||
|
args: {
|
||||||
|
claimStateFk: 3,
|
||||||
|
workerFk: 5,
|
||||||
|
observation: 'another valid observation',
|
||||||
|
hasToPickUp: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ctx.req.__ = (value, params) => {
|
||||||
|
return params.nickname;
|
||||||
|
};
|
||||||
|
await app.models.Claim.updateClaim(ctx, newClaim.id, options);
|
||||||
|
|
||||||
|
let updatedClaim = await app.models.Claim.findById(newClaim.id, null, options);
|
||||||
|
|
||||||
|
expect(updatedClaim.observation).toEqual(ctx.args.observation);
|
||||||
|
expect(updatedClaim.claimStateFk).toEqual(ctx.args.claimStateFk);
|
||||||
|
expect(updatedClaim.workerFk).toEqual(ctx.args.workerFk);
|
||||||
|
expect(chatModel.sendCheckingPresence).toHaveBeenCalled();
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('Update Claim', () => {
|
describe('Update Claim', () => {
|
||||||
let newDate = new Date();
|
const newDate = new Date();
|
||||||
let newInstance;
|
const original = {
|
||||||
let original = {
|
|
||||||
ticketFk: 3,
|
ticketFk: 3,
|
||||||
clientFk: 101,
|
clientFk: 101,
|
||||||
ticketCreated: newDate,
|
ticketCreated: newDate,
|
||||||
|
@ -14,30 +13,43 @@ describe('Update Claim', () => {
|
||||||
observation: 'observation'
|
observation: 'observation'
|
||||||
};
|
};
|
||||||
|
|
||||||
beforeAll(async done => {
|
|
||||||
newInstance = await app.models.Claim.create(original);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async done => {
|
|
||||||
await app.models.Claim.destroyById(newInstance.id);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should update the claim isChargedToMana attribute', async() => {
|
it('should update the claim isChargedToMana attribute', async() => {
|
||||||
const ctx = {args: {isChargedToMana: false}};
|
const tx = await app.models.Claim.beginTransaction({});
|
||||||
const result = await app.models.Claim.updateClaimAction(ctx, newInstance.id);
|
|
||||||
|
|
||||||
expect(result.id).toEqual(newInstance.id);
|
try {
|
||||||
expect(result.isChargedToMana).toBeFalsy();
|
const options = {transaction: tx};
|
||||||
|
const ctx = {args: {isChargedToMana: false}};
|
||||||
|
|
||||||
|
const newInstance = await app.models.Claim.create(original, options);
|
||||||
|
const result = await app.models.Claim.updateClaimAction(ctx, newInstance.id, options);
|
||||||
|
|
||||||
|
expect(result.id).toEqual(newInstance.id);
|
||||||
|
expect(result.isChargedToMana).toBeFalsy();
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update the claim responsibility attribute', async() => {
|
it('should update the claim responsibility attribute', async() => {
|
||||||
const ctx = {args: {responsibility: 2}};
|
const tx = await app.models.Claim.beginTransaction({});
|
||||||
const result = await app.models.Claim.updateClaimAction(ctx, newInstance.id);
|
|
||||||
|
|
||||||
expect(result.id).toEqual(newInstance.id);
|
try {
|
||||||
expect(result.responsibility).toEqual(2);
|
const options = {transaction: tx};
|
||||||
|
const ctx = {args: {responsibility: 2}};
|
||||||
|
|
||||||
|
const newInstance = await app.models.Claim.create(original, options);
|
||||||
|
const result = await app.models.Claim.updateClaimAction(ctx, newInstance.id, options);
|
||||||
|
|
||||||
|
expect(result.id).toEqual(newInstance.id);
|
||||||
|
expect(result.responsibility).toEqual(2);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,25 +4,26 @@ module.exports = Self => {
|
||||||
description: 'Update a claim with privileges',
|
description: 'Update a claim with privileges',
|
||||||
accepts: [{
|
accepts: [{
|
||||||
arg: 'ctx',
|
arg: 'ctx',
|
||||||
type: 'Object',
|
type: 'object',
|
||||||
http: {source: 'context'}
|
http: {source: 'context'}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
arg: 'id',
|
arg: 'id',
|
||||||
type: 'Number',
|
type: 'number',
|
||||||
description: 'Claim id',
|
description: 'Claim id',
|
||||||
http: {source: 'path'}
|
http: {source: 'path'}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
arg: 'workerFk',
|
arg: 'workerFk',
|
||||||
type: 'Number'
|
type: 'number'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
arg: 'claimStateFk',
|
arg: 'claimStateFk',
|
||||||
type: 'Number'
|
type: 'number'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
arg: 'observation',
|
arg: 'observation',
|
||||||
type: 'String'
|
type: 'string'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
arg: 'hasToPickUp',
|
arg: 'hasToPickUp',
|
||||||
|
@ -38,51 +39,69 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.updateClaim = async(ctx, id) => {
|
Self.updateClaim = async(ctx, id, options) => {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const userId = ctx.req.accessToken.userId;
|
const userId = ctx.req.accessToken.userId;
|
||||||
const args = ctx.args;
|
const args = ctx.args;
|
||||||
const $t = ctx.req.__; // $translate
|
const $t = ctx.req.__; // $translate
|
||||||
const claim = await models.Claim.findById(id, {
|
let tx;
|
||||||
include: {
|
let myOptions = {};
|
||||||
relation: 'client',
|
|
||||||
scope: {
|
if (typeof options == 'object')
|
||||||
include: {
|
Object.assign(myOptions, options);
|
||||||
relation: 'salesPersonUser'
|
|
||||||
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const claim = await models.Claim.findById(id, {
|
||||||
|
include: {
|
||||||
|
relation: 'client',
|
||||||
|
scope: {
|
||||||
|
include: {
|
||||||
|
relation: 'salesPersonUser'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}, myOptions);
|
||||||
|
let changedHasToPickUp = false;
|
||||||
|
if (args.hasToPickUp)
|
||||||
|
changedHasToPickUp = true;
|
||||||
|
|
||||||
|
if (args.claimStateFk) {
|
||||||
|
const canUpdate = await canChangeState(ctx, claim.claimStateFk, myOptions);
|
||||||
|
const hasRights = await canChangeState(ctx, args.claimStateFk, myOptions);
|
||||||
|
const isClaimManager = await models.Account.hasRole(userId, 'claimManager', myOptions);
|
||||||
|
|
||||||
|
if (!canUpdate || !hasRights || changedHasToPickUp && !isClaimManager)
|
||||||
|
throw new UserError(`You don't have enough privileges to change that field`);
|
||||||
|
}
|
||||||
|
delete args.ctx;
|
||||||
|
const updatedClaim = await claim.updateAttributes(args, myOptions);
|
||||||
|
// Get sales person from claim client
|
||||||
|
const salesPerson = claim.client().salesPersonUser();
|
||||||
|
if (salesPerson && changedHasToPickUp && updatedClaim.hasToPickUp) {
|
||||||
|
const origin = ctx.req.headers.origin;
|
||||||
|
const message = $t('Claim will be picked', {
|
||||||
|
claimId: claim.id,
|
||||||
|
clientName: claim.client().name,
|
||||||
|
claimUrl: `${origin}/#!/claim/${claim.id}/summary`
|
||||||
|
});
|
||||||
|
await models.Chat.sendCheckingPresence(ctx, salesPerson.id, message);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
let changedHasToPickUp = false;
|
|
||||||
if (args.hasToPickUp)
|
|
||||||
changedHasToPickUp = true;
|
|
||||||
|
|
||||||
if (args.claimStateFk) {
|
if (tx) await tx.commit();
|
||||||
const canUpdate = await canChangeState(ctx, claim.claimStateFk);
|
|
||||||
const hasRights = await canChangeState(ctx, args.claimStateFk);
|
|
||||||
const isClaimManager = await models.Account.hasRole(userId, 'claimManager');
|
|
||||||
|
|
||||||
if (!canUpdate || !hasRights || changedHasToPickUp && !isClaimManager)
|
return updatedClaim;
|
||||||
throw new UserError(`You don't have enough privileges to change that field`);
|
} catch (e) {
|
||||||
|
if (tx) await tx.rollback();
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
delete args.ctx;
|
|
||||||
const updatedClaim = await claim.updateAttributes(args);
|
|
||||||
// Get sales person from claim client
|
|
||||||
const salesPerson = claim.client().salesPersonUser();
|
|
||||||
if (salesPerson && changedHasToPickUp && updatedClaim.hasToPickUp) {
|
|
||||||
const origin = ctx.req.headers.origin;
|
|
||||||
const message = $t('Claim will be picked', {
|
|
||||||
claimId: claim.id,
|
|
||||||
clientName: claim.client().name,
|
|
||||||
claimUrl: `${origin}/#!/claim/${claim.id}/summary`
|
|
||||||
});
|
|
||||||
await models.Chat.sendCheckingPresence(ctx, salesPerson.id, message);
|
|
||||||
}
|
|
||||||
|
|
||||||
return updatedClaim;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
async function canChangeState(ctx, id) {
|
async function canChangeState(ctx, id, options) {
|
||||||
let models = Self.app.models;
|
let models = Self.app.models;
|
||||||
let userId = ctx.req.accessToken.userId;
|
let userId = ctx.req.accessToken.userId;
|
||||||
|
|
||||||
|
@ -90,9 +109,9 @@ module.exports = Self => {
|
||||||
include: {
|
include: {
|
||||||
relation: 'writeRole'
|
relation: 'writeRole'
|
||||||
}
|
}
|
||||||
});
|
}, options);
|
||||||
let stateRole = state.writeRole().name;
|
let stateRole = state.writeRole().name;
|
||||||
let canUpdate = await models.Account.hasRole(userId, stateRole);
|
let canUpdate = await models.Account.hasRole(userId, stateRole, options);
|
||||||
|
|
||||||
return canUpdate;
|
return canUpdate;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,12 +28,32 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.updateClaimAction = async(ctx, id) => {
|
Self.updateClaimAction = async(ctx, id, options) => {
|
||||||
const models = Self.app.models;
|
let tx;
|
||||||
const claim = await models.Claim.findById(id);
|
let myOptions = {};
|
||||||
const args = ctx.args;
|
|
||||||
delete args.ctx;
|
|
||||||
|
|
||||||
return await claim.updateAttributes(args);
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const models = Self.app.models;
|
||||||
|
const claim = await models.Claim.findById(id, null, myOptions);
|
||||||
|
const args = ctx.args;
|
||||||
|
delete args.ctx;
|
||||||
|
|
||||||
|
const updatedClaim = await claim.updateAttributes(args, myOptions);
|
||||||
|
|
||||||
|
if (tx) await tx.commit();
|
||||||
|
|
||||||
|
return updatedClaim;
|
||||||
|
} catch (e) {
|
||||||
|
if (tx) await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,40 +4,46 @@ module.exports = Self => {
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: [{
|
accepts: [{
|
||||||
arg: 'id',
|
arg: 'id',
|
||||||
type: 'Number',
|
type: 'number',
|
||||||
description: 'The claim id',
|
description: 'The claim id',
|
||||||
http: {source: 'path'}
|
http: {source: 'path'}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
arg: 'warehouseId',
|
arg: 'warehouseId',
|
||||||
type: 'Number',
|
type: 'number',
|
||||||
description: 'The warehouse id',
|
description: 'The warehouse id',
|
||||||
required: true
|
required: true
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
arg: 'companyId',
|
arg: 'companyId',
|
||||||
type: 'Number',
|
type: 'number',
|
||||||
description: 'The company id',
|
description: 'The company id',
|
||||||
required: true
|
required: true
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
arg: 'dmsTypeId',
|
arg: 'dmsTypeId',
|
||||||
type: 'Number',
|
type: 'number',
|
||||||
description: 'The dms type id',
|
description: 'The dms type id',
|
||||||
required: true
|
required: true
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
arg: 'reference',
|
arg: 'reference',
|
||||||
type: 'String',
|
type: 'string',
|
||||||
required: true
|
required: true
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
arg: 'description',
|
arg: 'description',
|
||||||
type: 'String',
|
type: 'string',
|
||||||
required: true
|
required: true
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
arg: 'hasFile',
|
arg: 'hasFile',
|
||||||
type: 'Boolean',
|
type: 'boolean',
|
||||||
description: 'True if has an attached file',
|
description: 'True if has an attached file',
|
||||||
required: true
|
required: true
|
||||||
}],
|
}],
|
||||||
returns: {
|
returns: {
|
||||||
type: 'Object',
|
type: 'object',
|
||||||
root: true
|
root: true
|
||||||
},
|
},
|
||||||
http: {
|
http: {
|
||||||
|
@ -46,31 +52,38 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.uploadFile = async(ctx, id) => {
|
Self.uploadFile = async(ctx, id, options) => {
|
||||||
|
let tx;
|
||||||
|
let myOptions = {};
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const promises = [];
|
const promises = [];
|
||||||
const tx = await Self.beginTransaction({});
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const options = {transaction: tx};
|
const uploadedFiles = await models.Dms.uploadFile(ctx, myOptions);
|
||||||
|
|
||||||
const uploadedFiles = await models.Dms.uploadFile(ctx, options);
|
|
||||||
uploadedFiles.forEach(dms => {
|
uploadedFiles.forEach(dms => {
|
||||||
const newClaimDms = models.ClaimDms.create({
|
const newClaimDms = models.ClaimDms.create({
|
||||||
claimFk: id,
|
claimFk: id,
|
||||||
dmsFk: dms.id
|
dmsFk: dms.id
|
||||||
}, options);
|
}, myOptions);
|
||||||
|
|
||||||
promises.push(newClaimDms);
|
promises.push(newClaimDms);
|
||||||
});
|
});
|
||||||
const resolvedPromises = await Promise.all(promises);
|
const resolvedPromises = await Promise.all(promises);
|
||||||
|
|
||||||
await tx.commit();
|
if (tx) await tx.commit();
|
||||||
|
|
||||||
return resolvedPromises;
|
return resolvedPromises;
|
||||||
} catch (err) {
|
} catch (e) {
|
||||||
await tx.rollback();
|
if (tx) await tx.rollback();
|
||||||
throw err;
|
throw e;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,10 +10,10 @@ module.exports = Self => {
|
||||||
description: 'The routes ids to clone'
|
description: 'The routes ids to clone'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
arg: 'started',
|
arg: 'created',
|
||||||
type: 'date',
|
type: 'date',
|
||||||
required: true,
|
required: true,
|
||||||
description: 'The started date for all routes'
|
description: 'The created date for all routes'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
returns: {
|
returns: {
|
||||||
|
@ -26,7 +26,7 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.clone = async(ids, started) => {
|
Self.clone = async(ids, created) => {
|
||||||
const tx = await Self.beginTransaction({});
|
const tx = await Self.beginTransaction({});
|
||||||
try {
|
try {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
@ -39,8 +39,7 @@ module.exports = Self => {
|
||||||
throw new Error(`The amount of routes found don't match`);
|
throw new Error(`The amount of routes found don't match`);
|
||||||
|
|
||||||
const routes = originalRoutes.map(route => {
|
const routes = originalRoutes.map(route => {
|
||||||
route.started = started;
|
route.created = created;
|
||||||
route.created = new Date();
|
|
||||||
return route;
|
return route;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -38,10 +38,10 @@ module.exports = Self => {
|
||||||
for (let zoneAgencyMode of zoneAgencyModes)
|
for (let zoneAgencyMode of zoneAgencyModes)
|
||||||
zoneIds.push(zoneAgencyMode.zoneFk);
|
zoneIds.push(zoneAgencyMode.zoneFk);
|
||||||
|
|
||||||
const minDate = new Date(route.finished);
|
const minDate = new Date(route.created);
|
||||||
minDate.setHours(0, 0, 0, 0);
|
minDate.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
const maxDate = new Date(route.finished);
|
const maxDate = new Date(route.created);
|
||||||
maxDate.setHours(23, 59, 59, 59);
|
maxDate.setHours(23, 59, 59, 59);
|
||||||
|
|
||||||
let tickets = await Self.app.models.Ticket.find({
|
let tickets = await Self.app.models.Ticket.find({
|
||||||
|
@ -49,7 +49,7 @@ module.exports = Self => {
|
||||||
agencyModeFk: route.agencyModeFk,
|
agencyModeFk: route.agencyModeFk,
|
||||||
zoneFk: {inq: zoneIds},
|
zoneFk: {inq: zoneIds},
|
||||||
id: {nin: idsToExclude},
|
id: {nin: idsToExclude},
|
||||||
landed: {between: [minDate, maxDate]}
|
created: {between: [minDate, maxDate]}
|
||||||
},
|
},
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('route clone()', () => {
|
describe('route clone()', () => {
|
||||||
const startDate = new Date();
|
const createdDate = new Date();
|
||||||
it('should throw an error if the amount of ids pased to the clone function do no match the database', async() => {
|
it('should throw an error if the amount of ids pased to the clone function do no match the database', async() => {
|
||||||
const ids = [996, 997, 998, 999];
|
const ids = [996, 997, 998, 999];
|
||||||
|
|
||||||
let error;
|
let error;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await app.models.Route.clone(ids, startDate);
|
await app.models.Route.clone(ids, createdDate);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error = e;
|
error = e;
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ describe('route clone()', () => {
|
||||||
it('should clone two routes', async() => {
|
it('should clone two routes', async() => {
|
||||||
const ids = [1, 2];
|
const ids = [1, 2];
|
||||||
|
|
||||||
const clones = await app.models.Route.clone(ids, startDate);
|
const clones = await app.models.Route.clone(ids, createdDate);
|
||||||
|
|
||||||
expect(clones.length).toEqual(2);
|
expect(clones.length).toEqual(2);
|
||||||
|
|
||||||
|
|
|
@ -104,9 +104,8 @@
|
||||||
<tpl-body>
|
<tpl-body>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-date-picker
|
<vn-date-picker
|
||||||
label="Starting date"
|
label="Starting date"
|
||||||
ng-model="$ctrl.startedDate"
|
ng-model="$ctrl.createdDate">
|
||||||
required="true">
|
|
||||||
</vn-date-picker>
|
</vn-date-picker>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
</tpl-body>
|
</tpl-body>
|
||||||
|
|
|
@ -41,19 +41,26 @@ export default class Controller extends Section {
|
||||||
}
|
}
|
||||||
|
|
||||||
openClonationDialog() {
|
openClonationDialog() {
|
||||||
this.startedDate = new Date();
|
|
||||||
this.$.clonationDialog.show();
|
this.$.clonationDialog.show();
|
||||||
|
this.createdDate = new Date();
|
||||||
}
|
}
|
||||||
|
|
||||||
cloneSelectedRoutes() {
|
cloneSelectedRoutes() {
|
||||||
const routesIds = [];
|
try {
|
||||||
for (let route of this.checked)
|
if (!this.createdDate)
|
||||||
routesIds.push(route.id);
|
throw new Error(`The date can't be empty`);
|
||||||
|
|
||||||
return this.$http.post('Routes/clone', {ids: routesIds, started: this.startedDate}).then(() => {
|
const routesIds = [];
|
||||||
this.$.model.refresh();
|
for (let route of this.checked)
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
routesIds.push(route.id);
|
||||||
});
|
|
||||||
|
return this.$http.post('Routes/clone', {ids: routesIds, created: this.createdDate}).then(() => {
|
||||||
|
this.$.model.refresh();
|
||||||
|
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
this.vnApp.showError(this.$t(e.message));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onDrop($event) {
|
onDrop($event) {
|
||||||
|
|
|
@ -62,7 +62,7 @@ describe('Component vnRouteIndex', () => {
|
||||||
|
|
||||||
describe('cloneSelectedRoutes()', () => {
|
describe('cloneSelectedRoutes()', () => {
|
||||||
it('should perform an http request to Routes/clone', () => {
|
it('should perform an http request to Routes/clone', () => {
|
||||||
controller.startedDate = new Date();
|
controller.createdDate = new Date();
|
||||||
|
|
||||||
$httpBackend.expect('POST', 'Routes/clone').respond();
|
$httpBackend.expect('POST', 'Routes/clone').respond();
|
||||||
controller.cloneSelectedRoutes();
|
controller.cloneSelectedRoutes();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
Vehicle: Vehículo
|
Vehicle: Vehículo
|
||||||
Download selected routes as PDF: Descargar rutas seleccionadas como PDF
|
Download selected routes as PDF: Descargar rutas seleccionadas como PDF
|
||||||
Clone selected routes: Clonar rutas seleccionadas
|
Clone selected routes: Clonar rutas seleccionadas
|
||||||
Select the starting date: Seleccione fecha de inicio
|
The date can't be empty: La fecha no puede estar vacía
|
||||||
Starting date: Fecha de inicio
|
Starting date: Fecha de inicio
|
|
@ -10,7 +10,7 @@
|
||||||
data="contacts"
|
data="contacts"
|
||||||
form="form">
|
form="form">
|
||||||
</vn-watcher>
|
</vn-watcher>
|
||||||
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
|
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-lg">
|
||||||
<vn-card class="vn-pa-lg">
|
<vn-card class="vn-pa-lg">
|
||||||
<div ng-repeat="contact in contacts" class="contact">
|
<div ng-repeat="contact in contacts" class="contact">
|
||||||
<vn-vertical>
|
<vn-vertical>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
// #2868 Excluded until database export
|
describe('ticket filter()', () => {
|
||||||
xdescribe('ticket filter()', () => {
|
|
||||||
it('should return the tickets matching the filter', async() => {
|
it('should return the tickets matching the filter', async() => {
|
||||||
const ctx = {req: {accessToken: {userId: 9}}, args: {}};
|
const ctx = {req: {accessToken: {userId: 9}}, args: {}};
|
||||||
const filter = {order: 'id DESC'};
|
const filter = {order: 'id DESC'};
|
||||||
|
@ -24,7 +23,7 @@ xdescribe('ticket filter()', () => {
|
||||||
const filter = {};
|
const filter = {};
|
||||||
const result = await app.models.Ticket.filter(ctx, filter);
|
const result = await app.models.Ticket.filter(ctx, filter);
|
||||||
|
|
||||||
expect(result.length).toEqual(4);
|
expect(result.length).toEqual(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return the tickets matching the problems on false', async() => {
|
it('should return the tickets matching the problems on false', async() => {
|
||||||
|
@ -42,7 +41,7 @@ xdescribe('ticket filter()', () => {
|
||||||
const filter = {};
|
const filter = {};
|
||||||
const result = await app.models.Ticket.filter(ctx, filter);
|
const result = await app.models.Ticket.filter(ctx, filter);
|
||||||
|
|
||||||
expect(result.length).toEqual(10);
|
expect(result.length).toEqual(7);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return the tickets matching the problems on null', async() => {
|
it('should return the tickets matching the problems on null', async() => {
|
||||||
|
|
|
@ -9575,13 +9575,13 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"jasmine-reporters": {
|
"jasmine-reporters": {
|
||||||
"version": "2.3.2",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/jasmine-reporters/-/jasmine-reporters-2.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/jasmine-reporters/-/jasmine-reporters-2.4.0.tgz",
|
||||||
"integrity": "sha512-u/7AT9SkuZsUfFBLLzbErohTGNsEUCKaQbsVYnLFW1gEuL2DzmBL4n8v90uZsqIqlWvWUgian8J6yOt5Fyk/+A==",
|
"integrity": "sha512-jxONSrBLN1vz/8zCx5YNWQSS8iyDAlXQ5yk1LuqITe4C6iXCDx5u6Q0jfNtkKhL4qLZPe69fL+AWvXFt9/x38w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"mkdirp": "^0.5.1",
|
"mkdirp": "^0.5.1",
|
||||||
"xmldom": "^0.1.22"
|
"xmldom": "^0.5.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"jasmine-spec-reporter": {
|
"jasmine-spec-reporter": {
|
||||||
|
@ -19907,7 +19907,7 @@
|
||||||
},
|
},
|
||||||
"globby": {
|
"globby": {
|
||||||
"version": "6.1.0",
|
"version": "6.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
|
"resolved": "http://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
|
||||||
"integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
|
"integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -20470,9 +20470,9 @@
|
||||||
"integrity": "sha1-+mv3YqYKQT+z3Y9LA8WyaSONMI8="
|
"integrity": "sha1-+mv3YqYKQT+z3Y9LA8WyaSONMI8="
|
||||||
},
|
},
|
||||||
"xmldom": {
|
"xmldom": {
|
||||||
"version": "0.1.31",
|
"version": "0.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz",
|
"resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.5.0.tgz",
|
||||||
"integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==",
|
"integrity": "sha512-Foaj5FXVzgn7xFzsKeNIde9g6aFBxTPi37iwsno8QvApmtg7KYrr+OPyRHcJF7dud2a5nGRBXK3n0dL62Gf7PA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"xpath": {
|
"xpath": {
|
||||||
|
@ -20568,7 +20568,7 @@
|
||||||
},
|
},
|
||||||
"os-locale": {
|
"os-locale": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
|
"resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
|
||||||
"integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
|
"integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
|
|
@ -76,7 +76,7 @@
|
||||||
"html-webpack-plugin": "^4.0.0-beta.11",
|
"html-webpack-plugin": "^4.0.0-beta.11",
|
||||||
"identity-obj-proxy": "^3.0.0",
|
"identity-obj-proxy": "^3.0.0",
|
||||||
"jasmine": "^3.6.3",
|
"jasmine": "^3.6.3",
|
||||||
"jasmine-reporters": "^2.3.2",
|
"jasmine-reporters": "^2.4.0",
|
||||||
"jasmine-spec-reporter": "^6.0.0",
|
"jasmine-spec-reporter": "^6.0.0",
|
||||||
"jest": "^26.0.1",
|
"jest": "^26.0.1",
|
||||||
"jest-junit": "^8.0.0",
|
"jest-junit": "^8.0.0",
|
||||||
|
|
Loading…
Reference in New Issue