Merge branch 'dev' into 2873-create-supplier-beneficiary
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
This commit is contained in:
commit
67f822ebdc
|
@ -20,17 +20,37 @@ module.exports = Self => {
|
|||
}
|
||||
});
|
||||
|
||||
Self.removeFile = async(ctx, id) => {
|
||||
const models = Self.app.models;
|
||||
const dms = await models.Dms.findById(id);
|
||||
const trashDmsType = await models.DmsType.findOne({
|
||||
where: {code: 'trash'}
|
||||
});
|
||||
Self.removeFile = async(ctx, id, options) => {
|
||||
let tx;
|
||||
let myOptions = {};
|
||||
|
||||
const hasWriteRole = await models.DmsType.hasWriteRole(ctx, dms.dmsTypeFk);
|
||||
if (!hasWriteRole)
|
||||
throw new UserError(`You don't have enough privileges`);
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
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": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "The id"
|
||||
},
|
||||
"name": {
|
||||
"type": "String",
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"collectionFk": {
|
||||
"type": "String",
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"updated": {
|
||||
"type": "Number"
|
||||
"type": "number"
|
||||
},
|
||||
"nRefs": {
|
||||
"type": "Number",
|
||||
"required": true,
|
||||
"default": 1
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"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)),
|
||||
(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`)
|
||||
VALUES
|
||||
(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'),
|
||||
(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
|
||||
(1, 'CRI', 'Crisantemo', 2, 31, 35, 0),
|
||||
(2, 'ITG', 'Anthurium', 1, 31, 35, 0),
|
||||
(3, 'WPN', 'Paniculata', 2, 31, 35, 0),
|
||||
(4, 'PRT', 'Delivery ports', 3, NULL, 35, 1),
|
||||
(5, 'CON', 'Container', 3, NULL, 35, 1),
|
||||
(6, 'ALS', 'Alstroemeria', 1, 31, 35, 0);
|
||||
(1, 'CRI', 'Crisantemo', 2, 1, 31, 35, 0),
|
||||
(2, 'ITG', 'Anthurium', 1, 1, 31, 35, 0),
|
||||
(3, 'WPN', 'Paniculata', 2, 1, 31, 35, 0),
|
||||
(4, 'PRT', 'Delivery ports', 3, 1, NULL, 35, 1),
|
||||
(5, 'CON', 'Container', 3, 1, NULL, 35, 1),
|
||||
(6, 'ALS', 'Alstroemeria', 1, 1, 31, 35, 0);
|
||||
|
||||
INSERT INTO `vn`.`ink`(`id`, `name`, `picture`, `showOrder`, `hex`)
|
||||
VALUES
|
||||
|
@ -2254,7 +2258,10 @@ INSERT INTO `vn`.`duaInvoiceIn`(`id`, `duaFk`, `invoiceInFk`)
|
|||
(10, 10, 10);
|
||||
|
||||
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`();
|
||||
|
||||
|
|
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.workerTeam__
|
||||
--ignore-table=vn.XDiario__
|
||||
--ignore-table=sage.movConta
|
||||
--ignore-table=sage.movContaCopia
|
||||
)
|
||||
mysqldump \
|
||||
--defaults-file=config.production.ini \
|
||||
|
|
|
@ -2,7 +2,7 @@ const app = require('vn-loopback/server/server');
|
|||
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||
|
||||
describe('item_getBalance()', () => {
|
||||
it(`should return the item balance`, async() => {
|
||||
it(`should return the item balance ordered by alert level`, async() => {
|
||||
let stmts = [];
|
||||
|
||||
let params = {
|
||||
|
@ -21,12 +21,11 @@ describe('item_getBalance()', () => {
|
|||
let result = await conn.executeStmt(sql);
|
||||
let itemBalance = result[0];
|
||||
|
||||
expect(itemBalance[0].alertLevel >= itemBalance[1].alertLevel).toBeTruthy();
|
||||
expect(itemBalance[1].alertLevel >= itemBalance[2].alertLevel).toBeTruthy();
|
||||
expect(itemBalance[2].alertLevel >= itemBalance[3].alertLevel).toBeTruthy();
|
||||
expect(itemBalance[3].alertLevel >= itemBalance[4].alertLevel).toBeTruthy();
|
||||
expect(itemBalance[4].alertLevel >= itemBalance[5].alertLevel).toBeTruthy();
|
||||
expect(itemBalance[5].alertLevel >= itemBalance[6].alertLevel).toBeTruthy();
|
||||
|
||||
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');
|
||||
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');
|
||||
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',
|
||||
accessType: 'READ',
|
||||
returns: {
|
||||
type: ['Object'],
|
||||
type: ['object'],
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
|
|
|
@ -4,12 +4,12 @@ module.exports = Self => {
|
|||
accessType: 'WRITE',
|
||||
accepts: {
|
||||
arg: 'id',
|
||||
type: 'Number',
|
||||
type: 'number',
|
||||
description: 'The document id',
|
||||
http: {source: 'path'}
|
||||
},
|
||||
returns: {
|
||||
type: 'Object',
|
||||
type: 'object',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
|
@ -18,16 +18,36 @@ module.exports = Self => {
|
|||
}
|
||||
});
|
||||
|
||||
Self.removeFile = async(ctx, id) => {
|
||||
const models = Self.app.models;
|
||||
const targetClaimDms = await models.ClaimDms.findById(id);
|
||||
const targetDms = await models.Dms.findById(targetClaimDms.dmsFk);
|
||||
const trashDmsType = await models.DmsType.findOne({where: {code: 'trash'}});
|
||||
Self.removeFile = async(ctx, id, options) => {
|
||||
let tx;
|
||||
let myOptions = {};
|
||||
|
||||
await models.Dms.removeFile(ctx, targetClaimDms.dmsFk);
|
||||
await targetClaimDms.destroy();
|
||||
if (typeof options == 'object')
|
||||
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 userId = ctx.req.accessToken.userId;
|
||||
let worker = await models.Worker.findOne({where: {userFk: userId}});
|
||||
|
||||
let ticketSales = await models.Sale.find({
|
||||
where: {ticketFk: params.ticketFk}
|
||||
});
|
||||
let tx;
|
||||
let myOptions = {};
|
||||
|
||||
let claimEnds = [];
|
||||
ticketSales.forEach(sale => {
|
||||
claimEnds.push({
|
||||
saleFk: sale.id,
|
||||
claimFk: params.claimFk,
|
||||
workerFk: worker.id
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
if (!myOptions.transaction) {
|
||||
tx = await Self.beginTransaction({});
|
||||
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');
|
||||
|
||||
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() => {
|
||||
let ctx = {req: {accessToken: {userId: 5}}};
|
||||
claimEnds = await app.models.ClaimEnd.importTicketSales(ctx, {
|
||||
claimFk: 1,
|
||||
ticketFk: 1
|
||||
});
|
||||
const ctx = {req: {accessToken: {userId: 5}}};
|
||||
|
||||
expect(claimEnds.length).toEqual(4);
|
||||
expect(claimEnds[0].saleFk).toEqual(1);
|
||||
expect(claimEnds[2].saleFk).toEqual(3);
|
||||
const tx = await app.models.Entry.beginTransaction({});
|
||||
try {
|
||||
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 userId = ctx.req.accessToken.userId;
|
||||
const tx = await Self.beginTransaction({});
|
||||
|
||||
try {
|
||||
let options = {transaction: tx};
|
||||
|
||||
const ticket = await models.Ticket.findById(ticketId, null, options);
|
||||
const ticket = await models.Ticket.findById(ticketId, null, myOptions);
|
||||
if (ticket.isDeleted)
|
||||
throw new UserError(`You can't create a claim for a removed ticket`);
|
||||
|
||||
|
@ -41,7 +48,7 @@ module.exports = Self => {
|
|||
clientFk: ticket.clientFk,
|
||||
ticketCreated: ticket.shipped,
|
||||
workerFk: userId
|
||||
}, options);
|
||||
}, myOptions);
|
||||
const promises = [];
|
||||
|
||||
for (const sale of sales) {
|
||||
|
@ -49,17 +56,18 @@ module.exports = Self => {
|
|||
saleFk: sale.id,
|
||||
claimFk: newClaim.id,
|
||||
quantity: sale.quantity
|
||||
}, options);
|
||||
}, myOptions);
|
||||
|
||||
promises.push(newClaimBeginning);
|
||||
}
|
||||
|
||||
await Promise.all(promises);
|
||||
|
||||
await tx.commit();
|
||||
if (tx) await tx.commit();
|
||||
|
||||
return newClaim;
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
if (tx) await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -10,58 +10,67 @@ module.exports = Self => {
|
|||
accepts: [
|
||||
{
|
||||
arg: 'filter',
|
||||
type: 'Object',
|
||||
type: 'object',
|
||||
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'tags',
|
||||
type: ['Object'],
|
||||
type: ['object'],
|
||||
description: 'List of tags to filter with',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'search',
|
||||
type: 'String',
|
||||
type: 'string',
|
||||
description: `If it's and integer searchs by id, otherwise it searchs by client name`,
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'client',
|
||||
type: 'String',
|
||||
type: 'string',
|
||||
description: 'The worker name',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'id',
|
||||
type: 'Integer',
|
||||
type: 'integer',
|
||||
description: 'The claim id',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'clientFk',
|
||||
type: 'Integer',
|
||||
type: 'integer',
|
||||
description: 'The client id',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'claimStateFk',
|
||||
type: 'Integer',
|
||||
type: 'integer',
|
||||
description: 'The claim state id',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'salesPersonFk',
|
||||
type: 'Integer',
|
||||
type: 'integer',
|
||||
description: 'The salesPerson id',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'attenderFk',
|
||||
type: 'Integer',
|
||||
type: 'integer',
|
||||
description: 'The attender worker id',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'created',
|
||||
type: 'Date',
|
||||
type: 'date',
|
||||
description: 'The to date filter',
|
||||
http: {source: 'query'}
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: ['Object'],
|
||||
type: ['object'],
|
||||
root: true
|
||||
},
|
||||
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 $t = ctx.req.__; // $translate
|
||||
const resolvedState = 3;
|
||||
|
||||
let tx = await Self.beginTransaction({});
|
||||
try {
|
||||
let options = {transaction: tx};
|
||||
let tx;
|
||||
let myOptions = {};
|
||||
|
||||
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({
|
||||
include: {
|
||||
relation: 'claimDestination',
|
||||
fields: ['addressFk']
|
||||
},
|
||||
where: {claimFk: claimFk}
|
||||
}, options);
|
||||
}, myOptions);
|
||||
|
||||
for (let i = 0; i < claimEnds.length; i++) {
|
||||
const claimEnd = claimEnds[i];
|
||||
for (let claimEnd of claimEnds) {
|
||||
const destination = claimEnd.claimDestination();
|
||||
const sale = await getSale(claimEnd.saleFk, options);
|
||||
const sale = await getSale(claimEnd.saleFk, myOptions);
|
||||
const addressId = destination && destination.addressFk;
|
||||
|
||||
let address;
|
||||
if (addressId)
|
||||
address = await models.Address.findById(addressId, null, options);
|
||||
address = await models.Address.findById(addressId, null, myOptions);
|
||||
|
||||
const salesPerson = sale.ticket().client().salesPersonUser();
|
||||
if (salesPerson) {
|
||||
|
@ -67,7 +74,7 @@ module.exports = Self => {
|
|||
addressFk: addressId,
|
||||
companyFk: sale.ticket().companyFk,
|
||||
warehouseFk: sale.ticket().warehouseFk
|
||||
}, options);
|
||||
}, myOptions);
|
||||
|
||||
if (!ticketFk) {
|
||||
ticketFk = await createTicket(ctx, {
|
||||
|
@ -75,7 +82,7 @@ module.exports = Self => {
|
|||
warehouseId: sale.ticket().warehouseFk,
|
||||
companyId: sale.ticket().companyFk,
|
||||
addressId: addressId
|
||||
}, options);
|
||||
}, myOptions);
|
||||
}
|
||||
|
||||
await models.Sale.create({
|
||||
|
@ -85,19 +92,19 @@ module.exports = Self => {
|
|||
quantity: -sale.quantity,
|
||||
price: sale.price,
|
||||
discount: 100
|
||||
}, options);
|
||||
}, myOptions);
|
||||
}
|
||||
|
||||
let claim = await Self.findById(claimFk, null, options);
|
||||
let claim = await Self.findById(claimFk, null, myOptions);
|
||||
claim = await claim.updateAttributes({
|
||||
claimStateFk: resolvedState
|
||||
}, options);
|
||||
}, myOptions);
|
||||
|
||||
await tx.commit();
|
||||
if (tx) await tx.commit();
|
||||
|
||||
return claim;
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
if (tx) await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -10,36 +10,45 @@ describe('Claim createFromSales()', () => {
|
|||
const ctx = {req: {accessToken: {userId: 1}}};
|
||||
|
||||
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(claimBeginning.quantity).toEqual(newSale[0].quantity);
|
||||
expect(claim.ticketFk).toEqual(ticketId);
|
||||
|
||||
const createdClaimId = claim.id;
|
||||
let claimBeginning = await app.models.ClaimBeginning.findOne({where: {claimFk: claim.id}}, options);
|
||||
|
||||
// restores
|
||||
await app.models.Claim.destroyById(createdClaimId);
|
||||
expect(claimBeginning.saleFk).toEqual(newSale[0].id);
|
||||
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() => {
|
||||
let claim = await app.models.Claim.createFromSales(ctx, ticketId, newSale);
|
||||
const createdClaimId = claim.id;
|
||||
const tx = await app.models.Claim.beginTransaction({});
|
||||
|
||||
let error;
|
||||
|
||||
await app.models.Claim.createFromSales(ctx, ticketId, newSale)
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
.catch(e => {
|
||||
error = e;
|
||||
});
|
||||
await app.models.Claim.createFromSales(ctx, ticketId, newSale, options);
|
||||
|
||||
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`);
|
||||
|
||||
// restores
|
||||
await app.models.Claim.destroyById(createdClaimId);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -21,81 +21,94 @@ describe('regularizeClaim()', () => {
|
|||
let claimEnds = [];
|
||||
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 {
|
||||
let claim = await app.models.Claim.findById(claimFk);
|
||||
await claim.updateAttributes({
|
||||
claimStateFk: pendentState,
|
||||
hasToPickUp: false
|
||||
});
|
||||
const options = {transaction: tx};
|
||||
|
||||
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
|
||||
|
||||
claimEnds = await app.models.ClaimEnd.importTicketSales(ctx, {
|
||||
claimFk: claimFk,
|
||||
ticketFk: 1
|
||||
}, options);
|
||||
|
||||
for (claimEnd of claimEnds)
|
||||
await claimEnd.destroy();
|
||||
await claimEnd.updateAttributes({claimDestinationFk: trashDestination}, options);
|
||||
|
||||
if (trashTicket)
|
||||
await app.models.Ticket.destroyById(trashTicket.id);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
let claimBefore = await app.models.Claim.findById(claimFk, null, options);
|
||||
await app.models.Claim.regularizeClaim(ctx, claimFk, options);
|
||||
let claimAfter = await app.models.Claim.findById(claimFk, null, options);
|
||||
|
||||
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() => {
|
||||
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
|
||||
const tx = await app.models.Claim.beginTransaction({});
|
||||
|
||||
claimEnds = await app.models.ClaimEnd.importTicketSales(ctx, {
|
||||
claimFk: claimFk,
|
||||
ticketFk: 1
|
||||
});
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
for (claimEnd of claimEnds)
|
||||
await claimEnd.updateAttributes({claimDestinationFk: okDestination});
|
||||
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
|
||||
|
||||
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');
|
||||
expect(chatModel.sendCheckingPresence).toHaveBeenCalledTimes(4);
|
||||
for (claimEnd of claimEnds)
|
||||
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() => {
|
||||
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
|
||||
const tx = await app.models.Claim.beginTransaction({});
|
||||
|
||||
claimEnds = await app.models.ClaimEnd.importTicketSales(ctx, {
|
||||
claimFk: claimFk,
|
||||
ticketFk: 1
|
||||
});
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
for (claimEnd of claimEnds)
|
||||
await claimEnd.updateAttributes({claimDestinationFk: okDestination});
|
||||
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
|
||||
|
||||
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');
|
||||
expect(chatModel.sendCheckingPresence).toHaveBeenCalledTimes(4);
|
||||
for (claimEnd of claimEnds)
|
||||
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');
|
||||
|
||||
describe('Update Claim', () => {
|
||||
let newDate = new Date();
|
||||
const newDate = new Date();
|
||||
const originalData = {
|
||||
ticketFk: 3,
|
||||
clientFk: 101,
|
||||
|
@ -14,89 +14,114 @@ describe('Update Claim', () => {
|
|||
};
|
||||
|
||||
it(`should throw an error as the user doesn't have rights`, async() => {
|
||||
let newClaim = await app.models.Claim.create(originalData);
|
||||
const forbiddenState = 3;
|
||||
const salesPersonId = 18;
|
||||
const ctx = {
|
||||
req: {
|
||||
accessToken: {
|
||||
userId: salesPersonId
|
||||
const tx = await app.models.Claim.beginTransaction({});
|
||||
|
||||
let error;
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
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: {
|
||||
claimStateFk: forbiddenState,
|
||||
observation: 'valid observation'
|
||||
}
|
||||
};
|
||||
await app.models.Claim.updateClaim(ctx, newClaim.id)
|
||||
.catch(e => {
|
||||
error = e;
|
||||
});
|
||||
};
|
||||
await app.models.Claim.updateClaim(ctx, newClaim.id, options);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
error = e;
|
||||
await tx.rollback();
|
||||
}
|
||||
|
||||
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() => {
|
||||
let newClaim = await app.models.Claim.create(originalData);
|
||||
const tx = await app.models.Claim.beginTransaction({});
|
||||
|
||||
const canceledState = 4;
|
||||
const claimManagerId = 72;
|
||||
const ctx = {
|
||||
req: {
|
||||
accessToken: {
|
||||
userId: claimManagerId
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const newClaim = await app.models.Claim.create(originalData, options);
|
||||
|
||||
const canceledState = 4;
|
||||
const claimManagerId = 72;
|
||||
const ctx = {
|
||||
req: {
|
||||
accessToken: {
|
||||
userId: claimManagerId
|
||||
}
|
||||
},
|
||||
args: {
|
||||
observation: 'valid observation',
|
||||
claimStateFk: canceledState,
|
||||
hasToPickUp: false
|
||||
}
|
||||
},
|
||||
args: {
|
||||
observation: 'valid observation',
|
||||
claimStateFk: canceledState,
|
||||
hasToPickUp: false
|
||||
}
|
||||
};
|
||||
await app.models.Claim.updateClaim(ctx, newClaim.id);
|
||||
};
|
||||
await app.models.Claim.updateClaim(ctx, newClaim.id, options);
|
||||
|
||||
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 app.models.Claim.destroyById(newClaim.id);
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should change some sensible fields as claimManager', async() => {
|
||||
let newClaim = await app.models.Claim.create(originalData);
|
||||
const chatModel = app.models.Chat;
|
||||
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
|
||||
const tx = await app.models.Claim.beginTransaction({});
|
||||
|
||||
const claimManagerId = 72;
|
||||
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);
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
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);
|
||||
expect(updatedClaim.claimStateFk).toEqual(ctx.args.claimStateFk);
|
||||
expect(updatedClaim.workerFk).toEqual(ctx.args.workerFk);
|
||||
expect(chatModel.sendCheckingPresence).toHaveBeenCalled();
|
||||
const chatModel = app.models.Chat;
|
||||
spyOn(chatModel, 'sendCheckingPresence').and.callThrough();
|
||||
|
||||
// restores
|
||||
await app.models.Claim.destroyById(newClaim.id);
|
||||
const claimManagerId = 72;
|
||||
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');
|
||||
|
||||
describe('Update Claim', () => {
|
||||
let newDate = new Date();
|
||||
let newInstance;
|
||||
let original = {
|
||||
const newDate = new Date();
|
||||
const original = {
|
||||
ticketFk: 3,
|
||||
clientFk: 101,
|
||||
ticketCreated: newDate,
|
||||
|
@ -14,30 +13,43 @@ describe('Update Claim', () => {
|
|||
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() => {
|
||||
const ctx = {args: {isChargedToMana: false}};
|
||||
const result = await app.models.Claim.updateClaimAction(ctx, newInstance.id);
|
||||
const tx = await app.models.Claim.beginTransaction({});
|
||||
|
||||
expect(result.id).toEqual(newInstance.id);
|
||||
expect(result.isChargedToMana).toBeFalsy();
|
||||
try {
|
||||
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() => {
|
||||
const ctx = {args: {responsibility: 2}};
|
||||
const result = await app.models.Claim.updateClaimAction(ctx, newInstance.id);
|
||||
const tx = await app.models.Claim.beginTransaction({});
|
||||
|
||||
expect(result.id).toEqual(newInstance.id);
|
||||
expect(result.responsibility).toEqual(2);
|
||||
try {
|
||||
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',
|
||||
accepts: [{
|
||||
arg: 'ctx',
|
||||
type: 'Object',
|
||||
type: 'object',
|
||||
http: {source: 'context'}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'id',
|
||||
type: 'Number',
|
||||
type: 'number',
|
||||
description: 'Claim id',
|
||||
http: {source: 'path'}
|
||||
},
|
||||
{
|
||||
arg: 'workerFk',
|
||||
type: 'Number'
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
arg: 'claimStateFk',
|
||||
type: 'Number'
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
arg: 'observation',
|
||||
type: 'String'
|
||||
type: 'string'
|
||||
},
|
||||
{
|
||||
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 userId = ctx.req.accessToken.userId;
|
||||
const args = ctx.args;
|
||||
const $t = ctx.req.__; // $translate
|
||||
const claim = await models.Claim.findById(id, {
|
||||
include: {
|
||||
relation: 'client',
|
||||
scope: {
|
||||
include: {
|
||||
relation: 'salesPersonUser'
|
||||
let tx;
|
||||
let myOptions = {};
|
||||
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
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) {
|
||||
const canUpdate = await canChangeState(ctx, claim.claimStateFk);
|
||||
const hasRights = await canChangeState(ctx, args.claimStateFk);
|
||||
const isClaimManager = await models.Account.hasRole(userId, 'claimManager');
|
||||
if (tx) await tx.commit();
|
||||
|
||||
if (!canUpdate || !hasRights || changedHasToPickUp && !isClaimManager)
|
||||
throw new UserError(`You don't have enough privileges to change that field`);
|
||||
return updatedClaim;
|
||||
} 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 userId = ctx.req.accessToken.userId;
|
||||
|
||||
|
@ -90,9 +109,9 @@ module.exports = Self => {
|
|||
include: {
|
||||
relation: 'writeRole'
|
||||
}
|
||||
});
|
||||
}, options);
|
||||
let stateRole = state.writeRole().name;
|
||||
let canUpdate = await models.Account.hasRole(userId, stateRole);
|
||||
let canUpdate = await models.Account.hasRole(userId, stateRole, options);
|
||||
|
||||
return canUpdate;
|
||||
}
|
||||
|
|
|
@ -28,12 +28,32 @@ module.exports = Self => {
|
|||
}
|
||||
});
|
||||
|
||||
Self.updateClaimAction = async(ctx, id) => {
|
||||
const models = Self.app.models;
|
||||
const claim = await models.Claim.findById(id);
|
||||
const args = ctx.args;
|
||||
delete args.ctx;
|
||||
Self.updateClaimAction = async(ctx, id, options) => {
|
||||
let tx;
|
||||
let myOptions = {};
|
||||
|
||||
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',
|
||||
accepts: [{
|
||||
arg: 'id',
|
||||
type: 'Number',
|
||||
type: 'number',
|
||||
description: 'The claim id',
|
||||
http: {source: 'path'}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'warehouseId',
|
||||
type: 'Number',
|
||||
type: 'number',
|
||||
description: 'The warehouse id',
|
||||
required: true
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'companyId',
|
||||
type: 'Number',
|
||||
type: 'number',
|
||||
description: 'The company id',
|
||||
required: true
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'dmsTypeId',
|
||||
type: 'Number',
|
||||
type: 'number',
|
||||
description: 'The dms type id',
|
||||
required: true
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'reference',
|
||||
type: 'String',
|
||||
type: 'string',
|
||||
required: true
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'description',
|
||||
type: 'String',
|
||||
type: 'string',
|
||||
required: true
|
||||
}, {
|
||||
},
|
||||
{
|
||||
arg: 'hasFile',
|
||||
type: 'Boolean',
|
||||
type: 'boolean',
|
||||
description: 'True if has an attached file',
|
||||
required: true
|
||||
}],
|
||||
returns: {
|
||||
type: 'Object',
|
||||
type: 'object',
|
||||
root: true
|
||||
},
|
||||
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 promises = [];
|
||||
const tx = await Self.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const uploadedFiles = await models.Dms.uploadFile(ctx, options);
|
||||
const uploadedFiles = await models.Dms.uploadFile(ctx, myOptions);
|
||||
uploadedFiles.forEach(dms => {
|
||||
const newClaimDms = models.ClaimDms.create({
|
||||
claimFk: id,
|
||||
dmsFk: dms.id
|
||||
}, options);
|
||||
}, myOptions);
|
||||
|
||||
promises.push(newClaimDms);
|
||||
});
|
||||
const resolvedPromises = await Promise.all(promises);
|
||||
|
||||
await tx.commit();
|
||||
if (tx) await tx.commit();
|
||||
|
||||
return resolvedPromises;
|
||||
} catch (err) {
|
||||
await tx.rollback();
|
||||
throw err;
|
||||
} catch (e) {
|
||||
if (tx) await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -10,10 +10,10 @@ module.exports = Self => {
|
|||
description: 'The routes ids to clone'
|
||||
},
|
||||
{
|
||||
arg: 'started',
|
||||
arg: 'created',
|
||||
type: 'date',
|
||||
required: true,
|
||||
description: 'The started date for all routes'
|
||||
description: 'The created date for all routes'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
|
@ -26,7 +26,7 @@ module.exports = Self => {
|
|||
}
|
||||
});
|
||||
|
||||
Self.clone = async(ids, started) => {
|
||||
Self.clone = async(ids, created) => {
|
||||
const tx = await Self.beginTransaction({});
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
@ -39,8 +39,7 @@ module.exports = Self => {
|
|||
throw new Error(`The amount of routes found don't match`);
|
||||
|
||||
const routes = originalRoutes.map(route => {
|
||||
route.started = started;
|
||||
route.created = new Date();
|
||||
route.created = created;
|
||||
return route;
|
||||
});
|
||||
|
||||
|
|
|
@ -38,10 +38,10 @@ module.exports = Self => {
|
|||
for (let zoneAgencyMode of zoneAgencyModes)
|
||||
zoneIds.push(zoneAgencyMode.zoneFk);
|
||||
|
||||
const minDate = new Date(route.finished);
|
||||
const minDate = new Date(route.created);
|
||||
minDate.setHours(0, 0, 0, 0);
|
||||
|
||||
const maxDate = new Date(route.finished);
|
||||
const maxDate = new Date(route.created);
|
||||
maxDate.setHours(23, 59, 59, 59);
|
||||
|
||||
let tickets = await Self.app.models.Ticket.find({
|
||||
|
@ -49,7 +49,7 @@ module.exports = Self => {
|
|||
agencyModeFk: route.agencyModeFk,
|
||||
zoneFk: {inq: zoneIds},
|
||||
id: {nin: idsToExclude},
|
||||
landed: {between: [minDate, maxDate]}
|
||||
created: {between: [minDate, maxDate]}
|
||||
},
|
||||
include: [
|
||||
{
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
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() => {
|
||||
const ids = [996, 997, 998, 999];
|
||||
|
||||
let error;
|
||||
|
||||
try {
|
||||
await app.models.Route.clone(ids, startDate);
|
||||
await app.models.Route.clone(ids, createdDate);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ describe('route clone()', () => {
|
|||
it('should clone two routes', async() => {
|
||||
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);
|
||||
|
||||
|
|
|
@ -104,9 +104,8 @@
|
|||
<tpl-body>
|
||||
<vn-horizontal>
|
||||
<vn-date-picker
|
||||
label="Starting date"
|
||||
ng-model="$ctrl.startedDate"
|
||||
required="true">
|
||||
label="Starting date"
|
||||
ng-model="$ctrl.createdDate">
|
||||
</vn-date-picker>
|
||||
</vn-horizontal>
|
||||
</tpl-body>
|
||||
|
|
|
@ -41,19 +41,26 @@ export default class Controller extends Section {
|
|||
}
|
||||
|
||||
openClonationDialog() {
|
||||
this.startedDate = new Date();
|
||||
this.$.clonationDialog.show();
|
||||
this.createdDate = new Date();
|
||||
}
|
||||
|
||||
cloneSelectedRoutes() {
|
||||
const routesIds = [];
|
||||
for (let route of this.checked)
|
||||
routesIds.push(route.id);
|
||||
try {
|
||||
if (!this.createdDate)
|
||||
throw new Error(`The date can't be empty`);
|
||||
|
||||
return this.$http.post('Routes/clone', {ids: routesIds, started: this.startedDate}).then(() => {
|
||||
this.$.model.refresh();
|
||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||
});
|
||||
const routesIds = [];
|
||||
for (let route of this.checked)
|
||||
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) {
|
||||
|
|
|
@ -62,7 +62,7 @@ describe('Component vnRouteIndex', () => {
|
|||
|
||||
describe('cloneSelectedRoutes()', () => {
|
||||
it('should perform an http request to Routes/clone', () => {
|
||||
controller.startedDate = new Date();
|
||||
controller.createdDate = new Date();
|
||||
|
||||
$httpBackend.expect('POST', 'Routes/clone').respond();
|
||||
controller.cloneSelectedRoutes();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
Vehicle: Vehículo
|
||||
Download selected routes as PDF: Descargar rutas seleccionadas como PDF
|
||||
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
|
|
@ -10,7 +10,7 @@
|
|||
data="contacts"
|
||||
form="form">
|
||||
</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">
|
||||
<div ng-repeat="contact in contacts" class="contact">
|
||||
<vn-vertical>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
// #2868 Excluded until database export
|
||||
xdescribe('ticket filter()', () => {
|
||||
describe('ticket filter()', () => {
|
||||
it('should return the tickets matching the filter', async() => {
|
||||
const ctx = {req: {accessToken: {userId: 9}}, args: {}};
|
||||
const filter = {order: 'id DESC'};
|
||||
|
@ -24,7 +23,7 @@ xdescribe('ticket filter()', () => {
|
|||
const 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() => {
|
||||
|
@ -42,7 +41,7 @@ xdescribe('ticket filter()', () => {
|
|||
const 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() => {
|
||||
|
|
Loading…
Reference in New Issue