Merge branch 'dev' into 5352-worker.create_swift/bic
gitea/salix/pipeline/head There was a failure building this commit
Details
gitea/salix/pipeline/head There was a failure building this commit
Details
This commit is contained in:
commit
e947672c69
|
@ -14,7 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
-
|
-
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
-
|
- (Clientes -> Listado extendido) Resuelto error al filtrar por clientes inactivos desde la columna "Activo"
|
||||||
|
- (General) Al pasar el ratón por encima del icono de "Borrar" en un campo, se hacía más grande afectando a la interfaz
|
||||||
|
|
||||||
## [2308.01] - 2023-03-09
|
## [2308.01] - 2023-03-09
|
||||||
|
|
||||||
|
|
|
@ -131,7 +131,7 @@ module.exports = Self => {
|
||||||
WHERE u.id = ?`, [userId], options);
|
WHERE u.id = ?`, [userId], options);
|
||||||
|
|
||||||
let roles = [];
|
let roles = [];
|
||||||
for (role of result)
|
for (const role of result)
|
||||||
roles.push(role.name);
|
roles.push(role.name);
|
||||||
|
|
||||||
return roles;
|
return roles;
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
|
||||||
|
VALUES('ClaimBeginning', 'isEditable', 'READ', 'ALLOW', 'ROLE', 'employee');
|
||||||
|
|
||||||
|
DELETE FROM `salix`.`ACL`
|
||||||
|
WHERE model='Claim' AND property='isEditable';
|
||||||
|
|
|
@ -1759,12 +1759,12 @@ INSERT INTO `vn`.`clientSample`(`id`, `clientFk`, `typeFk`, `created`, `workerFk
|
||||||
INSERT INTO `vn`.`claimState`(`id`, `code`, `description`, `roleFk`, `priority`, `hasToNotify`)
|
INSERT INTO `vn`.`claimState`(`id`, `code`, `description`, `roleFk`, `priority`, `hasToNotify`)
|
||||||
VALUES
|
VALUES
|
||||||
( 1, 'pending', 'Pendiente', 1, 1, 0),
|
( 1, 'pending', 'Pendiente', 1, 1, 0),
|
||||||
( 2, 'managed', 'Gestionado', 1, 5, 0),
|
( 2, 'managed', 'Gestionado', 72, 5, 0),
|
||||||
( 3, 'resolved', 'Resuelto', 72, 7, 0),
|
( 3, 'resolved', 'Resuelto', 72, 7, 0),
|
||||||
( 4, 'canceled', 'Anulado', 72, 6, 1),
|
( 4, 'canceled', 'Anulado', 72, 6, 1),
|
||||||
( 5, 'incomplete', 'Incompleta', 72, 3, 1),
|
( 5, 'incomplete', 'Incompleta', 1, 3, 1),
|
||||||
( 6, 'mana', 'Mana', 1, 4, 0),
|
( 6, 'mana', 'Mana', 72, 4, 0),
|
||||||
( 7, 'lack', 'Faltas', 1, 2, 0);
|
( 7, 'lack', 'Faltas', 72, 2, 0);
|
||||||
|
|
||||||
INSERT INTO `vn`.`claim`(`id`, `ticketCreated`, `claimStateFk`, `clientFk`, `workerFk`, `responsibility`, `isChargedToMana`, `created`, `packages`, `rma`)
|
INSERT INTO `vn`.`claim`(`id`, `ticketCreated`, `claimStateFk`, `clientFk`, `workerFk`, `responsibility`, `isChargedToMana`, `created`, `packages`, `rma`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -1828,7 +1828,12 @@ INSERT INTO vn.claimRma (`id`, `code`, `created`, `workerFk`)
|
||||||
(4, '02676A049183', DEFAULT, 1107),
|
(4, '02676A049183', DEFAULT, 1107),
|
||||||
(5, '01837B023653', DEFAULT, 1106);
|
(5, '01837B023653', DEFAULT, 1106);
|
||||||
|
|
||||||
|
INSERT INTO `vn`.`claimLog` (`originFk`, userFk, `action`, changedModel, oldInstance, newInstance, changedModelId, `description`)
|
||||||
|
VALUES
|
||||||
|
(1, 18, 'update', 'Claim', '{"hasToPickUp":false}', '{"hasToPickUp":true}', 1, NULL),
|
||||||
|
(1, 18, 'update', 'ClaimObservation', '{}', '{"claimFk":1,"text":"Waiting for customer"}', 1, NULL),
|
||||||
|
(1, 18, 'insert', 'ClaimBeginning', '{}', '{"claimFk":1,"saleFk":1,"quantity":10}', 1, NULL),
|
||||||
|
(1, 18, 'insert', 'ClaimDms', '{}', '{"claimFk":1,"dmsFk":1}', 1, NULL);
|
||||||
|
|
||||||
INSERT INTO `hedera`.`tpvMerchant`(`id`, `description`, `companyFk`, `bankFk`, `secretKey`)
|
INSERT INTO `hedera`.`tpvMerchant`(`id`, `description`, `companyFk`, `bankFk`, `secretKey`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -2760,7 +2765,6 @@ INSERT INTO `vn`.`ticketLog` (`originFk`, userFk, `action`, changedModel, oldIns
|
||||||
(7, 18, 'update', 'Sale', '{"price":3}', '{"price":5}', 1, NULL),
|
(7, 18, 'update', 'Sale', '{"price":3}', '{"price":5}', 1, NULL),
|
||||||
(7, 18, 'update', NULL, NULL, NULL, NULL, "Cambio cantidad Melee weapon heavy shield 1x0.5m de '5' a '10'");
|
(7, 18, 'update', NULL, NULL, NULL, NULL, "Cambio cantidad Melee weapon heavy shield 1x0.5m de '5' a '10'");
|
||||||
|
|
||||||
|
|
||||||
INSERT INTO `vn`.`osTicketConfig` (`id`, `host`, `user`, `password`, `oldStatus`, `newStatusId`, `day`, `comment`, `hostDb`, `userDb`, `passwordDb`, `portDb`, `responseType`, `fromEmailId`, `replyTo`)
|
INSERT INTO `vn`.`osTicketConfig` (`id`, `host`, `user`, `password`, `oldStatus`, `newStatusId`, `day`, `comment`, `hostDb`, `userDb`, `passwordDb`, `portDb`, `responseType`, `fromEmailId`, `replyTo`)
|
||||||
VALUES
|
VALUES
|
||||||
(0, 'http://localhost:56596/scp', 'ostadmin', 'Admin1', '1,6', 3, 60, 'Este CAU se ha cerrado automáticamente. Si el problema persiste responda a este mensaje.', 'localhost', 'osticket', 'osticket', 40003, 'reply', 1, 'all');
|
(0, 'http://localhost:56596/scp', 'ostadmin', 'Admin1', '1,6', 3, 60, 'Este CAU se ha cerrado automáticamente. Si el problema persiste responda a este mensaje.', 'localhost', 'osticket', 'osticket', 40003, 'reply', 1, 'all');
|
||||||
|
|
10246
db/dump/structure.sql
10246
db/dump/structure.sql
File diff suppressed because it is too large
Load Diff
|
@ -12,6 +12,9 @@ services:
|
||||||
placement:
|
placement:
|
||||||
constraints:
|
constraints:
|
||||||
- node.role == worker
|
- node.role == worker
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 1G
|
||||||
back:
|
back:
|
||||||
image: registry.verdnatura.es/salix-back:${BRANCH_NAME:?}
|
image: registry.verdnatura.es/salix-back:${BRANCH_NAME:?}
|
||||||
build: .
|
build: .
|
||||||
|
@ -38,6 +41,9 @@ services:
|
||||||
placement:
|
placement:
|
||||||
constraints:
|
constraints:
|
||||||
- node.role == worker
|
- node.role == worker
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 4G
|
||||||
configs:
|
configs:
|
||||||
datasources:
|
datasources:
|
||||||
external: true
|
external: true
|
||||||
|
|
|
@ -4,12 +4,17 @@ import getBrowser from '../../helpers/puppeteer';
|
||||||
describe('Ticket Future path', () => {
|
describe('Ticket Future path', () => {
|
||||||
let browser;
|
let browser;
|
||||||
let page;
|
let page;
|
||||||
|
let httpRequest;
|
||||||
|
|
||||||
beforeAll(async() => {
|
beforeAll(async() => {
|
||||||
browser = await getBrowser();
|
browser = await getBrowser();
|
||||||
page = browser.page;
|
page = browser.page;
|
||||||
await page.loginAndModule('employee', 'ticket');
|
await page.loginAndModule('employee', 'ticket');
|
||||||
await page.accessToSection('ticket.future');
|
await page.accessToSection('ticket.future');
|
||||||
|
page.on('request', req => {
|
||||||
|
if (req.url().includes(`Tickets/getTicketsFuture`))
|
||||||
|
httpRequest = req.url();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(async() => {
|
afterAll(async() => {
|
||||||
|
@ -42,114 +47,82 @@ describe('Ticket Future path', () => {
|
||||||
it('should search with the required data', async() => {
|
it('should search with the required data', async() => {
|
||||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||||
await page.waitToClick(selectors.ticketFuture.submit);
|
await page.waitToClick(selectors.ticketFuture.submit);
|
||||||
await page.waitForNumberOfElements(selectors.ticketFuture.table, 4);
|
|
||||||
|
expect(httpRequest).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should search with the origin IPT', async() => {
|
it('should search with the origin IPT', async() => {
|
||||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||||
|
|
||||||
await page.clearInput(selectors.ticketFuture.ipt);
|
|
||||||
await page.clearInput(selectors.ticketFuture.futureIpt);
|
|
||||||
await page.clearInput(selectors.ticketFuture.state);
|
|
||||||
await page.clearInput(selectors.ticketFuture.futureState);
|
|
||||||
|
|
||||||
await page.autocompleteSearch(selectors.ticketFuture.ipt, 'Horizontal');
|
await page.autocompleteSearch(selectors.ticketFuture.ipt, 'Horizontal');
|
||||||
await page.waitToClick(selectors.ticketFuture.submit);
|
await page.waitToClick(selectors.ticketFuture.submit);
|
||||||
await page.waitForNumberOfElements(selectors.ticketFuture.table, 4);
|
|
||||||
|
expect(httpRequest).toContain('ipt=H');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should search with the destination IPT', async() => {
|
it('should search with the destination IPT', async() => {
|
||||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||||
|
|
||||||
await page.clearInput(selectors.ticketFuture.ipt);
|
await page.clearInput(selectors.ticketFuture.ipt);
|
||||||
await page.clearInput(selectors.ticketFuture.futureIpt);
|
|
||||||
await page.clearInput(selectors.ticketFuture.state);
|
|
||||||
await page.clearInput(selectors.ticketFuture.futureState);
|
|
||||||
|
|
||||||
await page.autocompleteSearch(selectors.ticketFuture.futureIpt, 'Horizontal');
|
await page.autocompleteSearch(selectors.ticketFuture.futureIpt, 'Horizontal');
|
||||||
await page.waitToClick(selectors.ticketFuture.submit);
|
await page.waitToClick(selectors.ticketFuture.submit);
|
||||||
await page.waitForNumberOfElements(selectors.ticketFuture.table, 4);
|
|
||||||
|
expect(httpRequest).toContain('futureIpt=H');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should search with the origin grouped state', async() => {
|
it('should search with the origin grouped state', async() => {
|
||||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||||
|
|
||||||
await page.clearInput(selectors.ticketFuture.ipt);
|
|
||||||
await page.clearInput(selectors.ticketFuture.futureIpt);
|
await page.clearInput(selectors.ticketFuture.futureIpt);
|
||||||
await page.clearInput(selectors.ticketFuture.state);
|
|
||||||
await page.clearInput(selectors.ticketFuture.futureState);
|
|
||||||
|
|
||||||
await page.autocompleteSearch(selectors.ticketFuture.state, 'Free');
|
await page.autocompleteSearch(selectors.ticketFuture.state, 'Free');
|
||||||
await page.waitToClick(selectors.ticketFuture.submit);
|
await page.waitToClick(selectors.ticketFuture.submit);
|
||||||
await page.waitForNumberOfElements(selectors.ticketFuture.table, 3);
|
|
||||||
|
expect(httpRequest).toContain('state=FREE');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should search with the destination grouped state', async() => {
|
it('should search with the destination grouped state', async() => {
|
||||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||||
|
|
||||||
await page.clearInput(selectors.ticketFuture.ipt);
|
|
||||||
await page.clearInput(selectors.ticketFuture.futureIpt);
|
|
||||||
await page.clearInput(selectors.ticketFuture.state);
|
await page.clearInput(selectors.ticketFuture.state);
|
||||||
await page.clearInput(selectors.ticketFuture.futureState);
|
|
||||||
|
|
||||||
await page.autocompleteSearch(selectors.ticketFuture.futureState, 'Free');
|
await page.autocompleteSearch(selectors.ticketFuture.futureState, 'Free');
|
||||||
await page.waitToClick(selectors.ticketFuture.submit);
|
await page.waitToClick(selectors.ticketFuture.submit);
|
||||||
await page.waitForNumberOfElements(selectors.ticketFuture.table, 0);
|
|
||||||
|
expect(httpRequest).toContain('futureState=FREE');
|
||||||
|
|
||||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||||
await page.clearInput(selectors.ticketFuture.ipt);
|
|
||||||
await page.clearInput(selectors.ticketFuture.futureIpt);
|
|
||||||
await page.clearInput(selectors.ticketFuture.state);
|
|
||||||
await page.clearInput(selectors.ticketFuture.futureState);
|
await page.clearInput(selectors.ticketFuture.futureState);
|
||||||
|
|
||||||
await page.waitToClick(selectors.ticketFuture.submit);
|
await page.waitToClick(selectors.ticketFuture.submit);
|
||||||
await page.waitForNumberOfElements(selectors.ticketFuture.table, 4);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should search in smart-table with an ID Origin', async() => {
|
it('should search in smart-table with an ID Origin', async() => {
|
||||||
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
|
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
|
||||||
await page.write(selectors.ticketFuture.tableId, '13');
|
await page.write(selectors.ticketFuture.tableId, '1');
|
||||||
await page.keyboard.press('Enter');
|
await page.keyboard.press('Enter');
|
||||||
await page.waitForNumberOfElements(selectors.ticketFuture.table, 2);
|
|
||||||
|
|
||||||
|
expect(httpRequest).toContain('id');
|
||||||
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
|
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
|
||||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
|
||||||
await page.waitToClick(selectors.ticketFuture.submit);
|
|
||||||
await page.waitForNumberOfElements(selectors.ticketFuture.table, 4);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should search in smart-table with an ID Destination', async() => {
|
|
||||||
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
|
|
||||||
await page.write(selectors.ticketFuture.tableFutureId, '12');
|
|
||||||
await page.keyboard.press('Enter');
|
|
||||||
await page.waitForNumberOfElements(selectors.ticketFuture.table, 5);
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
|
|
||||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
|
||||||
await page.waitToClick(selectors.ticketFuture.submit);
|
|
||||||
await page.waitForNumberOfElements(selectors.ticketFuture.table, 4);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should search in smart-table with an IPT Origin', async() => {
|
|
||||||
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
|
|
||||||
await page.autocompleteSearch(selectors.ticketFuture.tableIpt, 'Vertical');
|
|
||||||
await page.waitForNumberOfElements(selectors.ticketFuture.table, 1);
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
|
|
||||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
|
||||||
await page.waitToClick(selectors.ticketFuture.submit);
|
|
||||||
await page.waitForNumberOfElements(selectors.ticketFuture.table, 4);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should search in smart-table with an IPT Destination', async() => {
|
it('should search in smart-table with an IPT Destination', async() => {
|
||||||
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
|
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
|
||||||
await page.autocompleteSearch(selectors.ticketFuture.tableFutureIpt, 'Vertical');
|
await page.autocompleteSearch(selectors.ticketFuture.tableFutureIpt, 'Horizontal');
|
||||||
await page.waitForNumberOfElements(selectors.ticketFuture.table, 1);
|
|
||||||
|
|
||||||
|
expect(httpRequest).toContain('futureIpt');
|
||||||
|
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should search in smart-table with an ID Destination', async() => {
|
||||||
|
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
|
||||||
|
await page.write(selectors.ticketFuture.tableFutureId, '1');
|
||||||
|
await page.keyboard.press('Enter');
|
||||||
|
|
||||||
|
expect(httpRequest).toContain('futureId');
|
||||||
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
|
await page.waitToClick(selectors.ticketFuture.tableButtonSearch);
|
||||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||||
await page.waitToClick(selectors.ticketFuture.submit);
|
await page.waitToClick(selectors.ticketFuture.submit);
|
||||||
await page.waitForNumberOfElements(selectors.ticketFuture.table, 4);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should check the three last tickets and move to the future', async() => {
|
it('should check the three last tickets and move to the future', async() => {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import getBrowser from '../../helpers/puppeteer';
|
||||||
describe('Ticket Advance path', () => {
|
describe('Ticket Advance path', () => {
|
||||||
let browser;
|
let browser;
|
||||||
let page;
|
let page;
|
||||||
const httpRequests = [];
|
let httpRequest;
|
||||||
|
|
||||||
beforeAll(async() => {
|
beforeAll(async() => {
|
||||||
browser = await getBrowser();
|
browser = await getBrowser();
|
||||||
|
@ -13,7 +13,7 @@ describe('Ticket Advance path', () => {
|
||||||
await page.accessToSection('ticket.advance');
|
await page.accessToSection('ticket.advance');
|
||||||
page.on('request', req => {
|
page.on('request', req => {
|
||||||
if (req.url().includes(`Tickets/getTicketsAdvance`))
|
if (req.url().includes(`Tickets/getTicketsAdvance`))
|
||||||
httpRequests.push(req.url());
|
httpRequest = req.url();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ describe('Ticket Advance path', () => {
|
||||||
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
|
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
|
||||||
await page.waitToClick(selectors.ticketAdvance.submit);
|
await page.waitToClick(selectors.ticketAdvance.submit);
|
||||||
|
|
||||||
expect(httpRequests.length).toBeGreaterThan(0);
|
expect(httpRequest).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should search with the origin IPT', async() => {
|
it('should search with the origin IPT', async() => {
|
||||||
|
@ -57,11 +57,7 @@ describe('Ticket Advance path', () => {
|
||||||
await page.autocompleteSearch(selectors.ticketAdvance.futureIpt, 'Horizontal');
|
await page.autocompleteSearch(selectors.ticketAdvance.futureIpt, 'Horizontal');
|
||||||
await page.waitToClick(selectors.ticketAdvance.submit);
|
await page.waitToClick(selectors.ticketAdvance.submit);
|
||||||
|
|
||||||
const request = httpRequests.find(req => req.includes(('futureIpt=H')));
|
expect(httpRequest).toContain('futureIpt=H');
|
||||||
|
|
||||||
expect(request).toBeDefined();
|
|
||||||
|
|
||||||
httpRequests.splice(httpRequests.indexOf(request), 1);
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
|
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
|
||||||
await page.clearInput(selectors.ticketAdvance.futureIpt);
|
await page.clearInput(selectors.ticketAdvance.futureIpt);
|
||||||
|
@ -73,11 +69,7 @@ describe('Ticket Advance path', () => {
|
||||||
await page.autocompleteSearch(selectors.ticketAdvance.ipt, 'Horizontal');
|
await page.autocompleteSearch(selectors.ticketAdvance.ipt, 'Horizontal');
|
||||||
await page.waitToClick(selectors.ticketAdvance.submit);
|
await page.waitToClick(selectors.ticketAdvance.submit);
|
||||||
|
|
||||||
const request = httpRequests.find(req => req.includes(('ipt=H')));
|
expect(httpRequest).toContain('ipt=H');
|
||||||
|
|
||||||
expect(request).toBeDefined();
|
|
||||||
|
|
||||||
httpRequests.splice(httpRequests.indexOf(request), 1);
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
|
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
|
||||||
await page.clearInput(selectors.ticketAdvance.ipt);
|
await page.clearInput(selectors.ticketAdvance.ipt);
|
||||||
|
@ -88,11 +80,7 @@ describe('Ticket Advance path', () => {
|
||||||
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
|
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
|
||||||
await page.autocompleteSearch(selectors.ticketAdvance.tableFutureIpt, 'Vertical');
|
await page.autocompleteSearch(selectors.ticketAdvance.tableFutureIpt, 'Vertical');
|
||||||
|
|
||||||
const request = httpRequests.find(req => req.includes(('futureIpt')));
|
expect(httpRequest).toContain('futureIpt');
|
||||||
|
|
||||||
expect(request).toBeDefined();
|
|
||||||
|
|
||||||
httpRequests.splice(httpRequests.indexOf(request), 1);
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
|
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
|
||||||
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
|
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
|
||||||
|
@ -103,11 +91,7 @@ describe('Ticket Advance path', () => {
|
||||||
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
|
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
|
||||||
await page.autocompleteSearch(selectors.ticketAdvance.tableIpt, 'Vertical');
|
await page.autocompleteSearch(selectors.ticketAdvance.tableIpt, 'Vertical');
|
||||||
|
|
||||||
const request = httpRequests.find(req => req.includes(('ipt')));
|
expect(httpRequest).toContain('ipt');
|
||||||
|
|
||||||
expect(request).toBeDefined();
|
|
||||||
|
|
||||||
httpRequests.splice(httpRequests.indexOf(request), 1);
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
|
await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
|
||||||
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
|
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
|
||||||
|
|
|
@ -40,7 +40,7 @@ export default class Check extends Toggle {
|
||||||
|
|
||||||
set tripleState(value) {
|
set tripleState(value) {
|
||||||
this._tripleState = value;
|
this._tripleState = value;
|
||||||
this.field = this.field;
|
this.field = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
get tripleState() {
|
get tripleState() {
|
||||||
|
|
|
@ -45,8 +45,8 @@ describe('Component vnCheck', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should set value to null and change to true when clicked`, () => {
|
it(`should set value to null and change to true when clicked`, () => {
|
||||||
controller.field = null;
|
|
||||||
controller.tripleState = true;
|
controller.tripleState = true;
|
||||||
|
controller.field = null;
|
||||||
element.click();
|
element.click();
|
||||||
|
|
||||||
expect(controller.field).toEqual(true);
|
expect(controller.field).toEqual(true);
|
||||||
|
|
|
@ -436,6 +436,7 @@ export default class SmartTable extends Component {
|
||||||
|
|
||||||
if (filters && filters.userFilter)
|
if (filters && filters.userFilter)
|
||||||
this.model.userFilter = filters.userFilter;
|
this.model.userFilter = filters.userFilter;
|
||||||
|
|
||||||
this.addFilter(field, this.$inputsScope.searchProps[field]);
|
this.addFilter(field, this.$inputsScope.searchProps[field]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,7 +452,7 @@ export default class SmartTable extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
addFilter(field, value) {
|
addFilter(field, value) {
|
||||||
if (value == '') value = null;
|
if (value === '') value = null;
|
||||||
|
|
||||||
let stateFilter = {tableQ: {}};
|
let stateFilter = {tableQ: {}};
|
||||||
if (this.$params.q) {
|
if (this.$params.q) {
|
||||||
|
@ -462,7 +463,7 @@ export default class SmartTable extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
const whereParams = {[field]: value};
|
const whereParams = {[field]: value};
|
||||||
if (value) {
|
if (value !== '' && value !== null && value !== undefined) {
|
||||||
let where = {[field]: value};
|
let where = {[field]: value};
|
||||||
if (this.exprBuilder) {
|
if (this.exprBuilder) {
|
||||||
where = buildFilter(whereParams, (param, value) =>
|
where = buildFilter(whereParams, (param, value) =>
|
||||||
|
|
|
@ -25,7 +25,8 @@
|
||||||
},
|
},
|
||||||
"node_modules/@uirouter/angularjs": {
|
"node_modules/@uirouter/angularjs": {
|
||||||
"version": "1.0.30",
|
"version": "1.0.30",
|
||||||
"license": "MIT",
|
"resolved": "https://registry.npmjs.org/@uirouter/angularjs/-/angularjs-1.0.30.tgz",
|
||||||
|
"integrity": "sha512-qkc3RFZc91S5K0gc/QVAXc9LGDPXjR04vDgG/11j8+yyZEuQojXxKxdLhKIepiPzqLmGRVqzBmBc27gtqaEeZg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@uirouter/core": "6.0.8"
|
"@uirouter/core": "6.0.8"
|
||||||
},
|
},
|
||||||
|
@ -38,22 +39,28 @@
|
||||||
},
|
},
|
||||||
"node_modules/@uirouter/core": {
|
"node_modules/@uirouter/core": {
|
||||||
"version": "6.0.8",
|
"version": "6.0.8",
|
||||||
"license": "MIT",
|
"resolved": "https://registry.npmjs.org/@uirouter/core/-/core-6.0.8.tgz",
|
||||||
|
"integrity": "sha512-Gc/BAW47i4L54p8dqYCJJZuv2s3tqlXQ0fvl6Zp2xrblELPVfxmjnc0eurx3XwfQdaqm3T6uls6tQKkof/4QMw==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=4.0.0"
|
"node": ">=4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/angular": {
|
"node_modules/angular": {
|
||||||
"version": "1.8.3",
|
"version": "1.8.3",
|
||||||
"license": "MIT"
|
"resolved": "https://registry.npmjs.org/angular/-/angular-1.8.3.tgz",
|
||||||
|
"integrity": "sha512-5qjkWIQQVsHj4Sb5TcEs4WZWpFeVFHXwxEBHUhrny41D8UrBAd6T/6nPPAsLngJCReIOqi95W3mxdveveutpZw==",
|
||||||
|
"deprecated": "For the actively supported Angular, see https://www.npmjs.com/package/@angular/core. AngularJS support has officially ended. For extended AngularJS support options, see https://goo.gle/angularjs-path-forward."
|
||||||
},
|
},
|
||||||
"node_modules/angular-animate": {
|
"node_modules/angular-animate": {
|
||||||
"version": "1.8.2",
|
"version": "1.8.2",
|
||||||
"license": "MIT"
|
"resolved": "https://registry.npmjs.org/angular-animate/-/angular-animate-1.8.2.tgz",
|
||||||
|
"integrity": "sha512-Jbr9+grNMs9Kj57xuBU3Ju3NOPAjS1+g2UAwwDv7su1lt0/PLDy+9zEwDiu8C8xJceoTbmBNKiWGPJGBdCQLlA==",
|
||||||
|
"deprecated": "For the actively supported Angular, see https://www.npmjs.com/package/@angular/core. AngularJS support has officially ended. For extended AngularJS support options, see https://goo.gle/angularjs-path-forward."
|
||||||
},
|
},
|
||||||
"node_modules/angular-moment": {
|
"node_modules/angular-moment": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"license": "MIT",
|
"resolved": "https://registry.npmjs.org/angular-moment/-/angular-moment-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-KG8rvO9MoaBLwtGnxTeUveSyNtrL+RNgGl1zqWN36+HDCCVGk2DGWOzqKWB6o+eTTbO3Opn4hupWKIElc8XETA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"moment": ">=2.8.0 <3.0.0"
|
"moment": ">=2.8.0 <3.0.0"
|
||||||
},
|
},
|
||||||
|
@ -63,7 +70,8 @@
|
||||||
},
|
},
|
||||||
"node_modules/angular-translate": {
|
"node_modules/angular-translate": {
|
||||||
"version": "2.19.0",
|
"version": "2.19.0",
|
||||||
"license": "MIT",
|
"resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.19.0.tgz",
|
||||||
|
"integrity": "sha512-Z/Fip5uUT2N85dPQ0sMEe1JdF5AehcDe4tg/9mWXNDVU531emHCg53ZND9Oe0dyNiGX5rWcJKmsL1Fujus1vGQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"angular": "^1.8.0"
|
"angular": "^1.8.0"
|
||||||
},
|
},
|
||||||
|
@ -73,25 +81,29 @@
|
||||||
},
|
},
|
||||||
"node_modules/angular-translate-loader-partial": {
|
"node_modules/angular-translate-loader-partial": {
|
||||||
"version": "2.19.0",
|
"version": "2.19.0",
|
||||||
"license": "MIT",
|
"resolved": "https://registry.npmjs.org/angular-translate-loader-partial/-/angular-translate-loader-partial-2.19.0.tgz",
|
||||||
|
"integrity": "sha512-NnMw13LMV4bPQmJK7/pZOZAnPxe0M5OtUHchADs5Gye7V7feonuEnrZ8e1CKhBlv9a7IQyWoqcBa4Lnhg8gk5w==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"angular-translate": "~2.19.0"
|
"angular-translate": "~2.19.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/argparse": {
|
"node_modules/argparse": {
|
||||||
"version": "1.0.10",
|
"version": "1.0.10",
|
||||||
"license": "MIT",
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||||
|
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"sprintf-js": "~1.0.2"
|
"sprintf-js": "~1.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/croppie": {
|
"node_modules/croppie": {
|
||||||
"version": "2.6.5",
|
"version": "2.6.5",
|
||||||
"license": "MIT"
|
"resolved": "https://registry.npmjs.org/croppie/-/croppie-2.6.5.tgz",
|
||||||
|
"integrity": "sha512-IlChnVUGG5T3w2gRZIaQgBtlvyuYnlUWs2YZIXXR3H9KrlO1PtBT3j+ykxvy9eZIWhk+V5SpBmhCQz5UXKrEKQ=="
|
||||||
},
|
},
|
||||||
"node_modules/esprima": {
|
"node_modules/esprima": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"license": "BSD-2-Clause",
|
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
||||||
"bin": {
|
"bin": {
|
||||||
"esparse": "bin/esparse.js",
|
"esparse": "bin/esparse.js",
|
||||||
"esvalidate": "bin/esvalidate.js"
|
"esvalidate": "bin/esvalidate.js"
|
||||||
|
@ -102,7 +114,8 @@
|
||||||
},
|
},
|
||||||
"node_modules/js-yaml": {
|
"node_modules/js-yaml": {
|
||||||
"version": "3.14.1",
|
"version": "3.14.1",
|
||||||
"license": "MIT",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
||||||
|
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"argparse": "^1.0.7",
|
"argparse": "^1.0.7",
|
||||||
"esprima": "^4.0.0"
|
"esprima": "^4.0.0"
|
||||||
|
@ -113,36 +126,42 @@
|
||||||
},
|
},
|
||||||
"node_modules/mg-crud": {
|
"node_modules/mg-crud": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"license": "MIT",
|
"resolved": "https://registry.npmjs.org/mg-crud/-/mg-crud-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-mAR6t0aQHKnT0QHKHpLOi0kNPZfO36iMpIoiLjFHxuio6mIJyuveBJ4VNlNXJRxLh32/FLADEb41/sYo7QUKFw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"angular": "^1.6.1"
|
"angular": "^1.6.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/moment": {
|
"node_modules/moment": {
|
||||||
"version": "2.29.4",
|
"version": "2.29.4",
|
||||||
"license": "MIT",
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
|
||||||
|
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/oclazyload": {
|
"node_modules/oclazyload": {
|
||||||
"version": "0.6.3",
|
"version": "0.6.3",
|
||||||
"license": "MIT"
|
"resolved": "https://registry.npmjs.org/oclazyload/-/oclazyload-0.6.3.tgz",
|
||||||
|
"integrity": "sha512-HpOSYUgjtt6sTB/C6+FWsExR+9HCnXKsUA96RWkDXfv11C8Cc9X2DlR0WIZwFIiG6FQU0pwB5dhoYyut8bFAOQ=="
|
||||||
},
|
},
|
||||||
"node_modules/require-yaml": {
|
"node_modules/require-yaml": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"license": "BSD",
|
"resolved": "https://registry.npmjs.org/require-yaml/-/require-yaml-0.0.1.tgz",
|
||||||
|
"integrity": "sha512-M6eVEgLPRbeOhgSCnOTtdrOOEQzbXRchg24Xa13c39dMuraFKdI9emUo97Rih0YEFzSICmSKg8w4RQp+rd9pOQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"js-yaml": ""
|
"js-yaml": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/require-yaml/node_modules/argparse": {
|
"node_modules/require-yaml/node_modules/argparse": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"license": "Python-2.0"
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
|
||||||
},
|
},
|
||||||
"node_modules/require-yaml/node_modules/js-yaml": {
|
"node_modules/require-yaml/node_modules/js-yaml": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"license": "MIT",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"argparse": "^2.0.1"
|
"argparse": "^2.0.1"
|
||||||
},
|
},
|
||||||
|
@ -152,11 +171,13 @@
|
||||||
},
|
},
|
||||||
"node_modules/sprintf-js": {
|
"node_modules/sprintf-js": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"license": "BSD-3-Clause"
|
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
|
||||||
},
|
},
|
||||||
"node_modules/validator": {
|
"node_modules/validator": {
|
||||||
"version": "6.3.0",
|
"version": "6.3.0",
|
||||||
"license": "MIT",
|
"resolved": "https://registry.npmjs.org/validator/-/validator-6.3.0.tgz",
|
||||||
|
"integrity": "sha512-BylxTwhqwjQI5MDJF7amCy/L0ejJO+74DvCsLV52Lq3+3bhVcVMKqNqOiNcQJm2G48u9EAcw4xFERAmFbwXM9Q==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 0.10"
|
"node": ">= 0.10"
|
||||||
}
|
}
|
||||||
|
@ -165,51 +186,73 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@uirouter/angularjs": {
|
"@uirouter/angularjs": {
|
||||||
"version": "1.0.30",
|
"version": "1.0.30",
|
||||||
|
"resolved": "https://registry.npmjs.org/@uirouter/angularjs/-/angularjs-1.0.30.tgz",
|
||||||
|
"integrity": "sha512-qkc3RFZc91S5K0gc/QVAXc9LGDPXjR04vDgG/11j8+yyZEuQojXxKxdLhKIepiPzqLmGRVqzBmBc27gtqaEeZg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@uirouter/core": "6.0.8"
|
"@uirouter/core": "6.0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@uirouter/core": {
|
"@uirouter/core": {
|
||||||
"version": "6.0.8"
|
"version": "6.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@uirouter/core/-/core-6.0.8.tgz",
|
||||||
|
"integrity": "sha512-Gc/BAW47i4L54p8dqYCJJZuv2s3tqlXQ0fvl6Zp2xrblELPVfxmjnc0eurx3XwfQdaqm3T6uls6tQKkof/4QMw=="
|
||||||
},
|
},
|
||||||
"angular": {
|
"angular": {
|
||||||
"version": "1.8.3"
|
"version": "1.8.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/angular/-/angular-1.8.3.tgz",
|
||||||
|
"integrity": "sha512-5qjkWIQQVsHj4Sb5TcEs4WZWpFeVFHXwxEBHUhrny41D8UrBAd6T/6nPPAsLngJCReIOqi95W3mxdveveutpZw=="
|
||||||
},
|
},
|
||||||
"angular-animate": {
|
"angular-animate": {
|
||||||
"version": "1.8.2"
|
"version": "1.8.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/angular-animate/-/angular-animate-1.8.2.tgz",
|
||||||
|
"integrity": "sha512-Jbr9+grNMs9Kj57xuBU3Ju3NOPAjS1+g2UAwwDv7su1lt0/PLDy+9zEwDiu8C8xJceoTbmBNKiWGPJGBdCQLlA=="
|
||||||
},
|
},
|
||||||
"angular-moment": {
|
"angular-moment": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/angular-moment/-/angular-moment-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-KG8rvO9MoaBLwtGnxTeUveSyNtrL+RNgGl1zqWN36+HDCCVGk2DGWOzqKWB6o+eTTbO3Opn4hupWKIElc8XETA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"moment": ">=2.8.0 <3.0.0"
|
"moment": ">=2.8.0 <3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"angular-translate": {
|
"angular-translate": {
|
||||||
"version": "2.19.0",
|
"version": "2.19.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.19.0.tgz",
|
||||||
|
"integrity": "sha512-Z/Fip5uUT2N85dPQ0sMEe1JdF5AehcDe4tg/9mWXNDVU531emHCg53ZND9Oe0dyNiGX5rWcJKmsL1Fujus1vGQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"angular": "^1.8.0"
|
"angular": "^1.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"angular-translate-loader-partial": {
|
"angular-translate-loader-partial": {
|
||||||
"version": "2.19.0",
|
"version": "2.19.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/angular-translate-loader-partial/-/angular-translate-loader-partial-2.19.0.tgz",
|
||||||
|
"integrity": "sha512-NnMw13LMV4bPQmJK7/pZOZAnPxe0M5OtUHchADs5Gye7V7feonuEnrZ8e1CKhBlv9a7IQyWoqcBa4Lnhg8gk5w==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"angular-translate": "~2.19.0"
|
"angular-translate": "~2.19.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"argparse": {
|
"argparse": {
|
||||||
"version": "1.0.10",
|
"version": "1.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||||
|
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"sprintf-js": "~1.0.2"
|
"sprintf-js": "~1.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"croppie": {
|
"croppie": {
|
||||||
"version": "2.6.5"
|
"version": "2.6.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/croppie/-/croppie-2.6.5.tgz",
|
||||||
|
"integrity": "sha512-IlChnVUGG5T3w2gRZIaQgBtlvyuYnlUWs2YZIXXR3H9KrlO1PtBT3j+ykxvy9eZIWhk+V5SpBmhCQz5UXKrEKQ=="
|
||||||
},
|
},
|
||||||
"esprima": {
|
"esprima": {
|
||||||
"version": "4.0.1"
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
|
||||||
},
|
},
|
||||||
"js-yaml": {
|
"js-yaml": {
|
||||||
"version": "3.14.1",
|
"version": "3.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
||||||
|
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"argparse": "^1.0.7",
|
"argparse": "^1.0.7",
|
||||||
"esprima": "^4.0.0"
|
"esprima": "^4.0.0"
|
||||||
|
@ -217,27 +260,39 @@
|
||||||
},
|
},
|
||||||
"mg-crud": {
|
"mg-crud": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/mg-crud/-/mg-crud-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-mAR6t0aQHKnT0QHKHpLOi0kNPZfO36iMpIoiLjFHxuio6mIJyuveBJ4VNlNXJRxLh32/FLADEb41/sYo7QUKFw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"angular": "^1.6.1"
|
"angular": "^1.6.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"moment": {
|
"moment": {
|
||||||
"version": "2.29.4"
|
"version": "2.29.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
|
||||||
|
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
|
||||||
},
|
},
|
||||||
"oclazyload": {
|
"oclazyload": {
|
||||||
"version": "0.6.3"
|
"version": "0.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/oclazyload/-/oclazyload-0.6.3.tgz",
|
||||||
|
"integrity": "sha512-HpOSYUgjtt6sTB/C6+FWsExR+9HCnXKsUA96RWkDXfv11C8Cc9X2DlR0WIZwFIiG6FQU0pwB5dhoYyut8bFAOQ=="
|
||||||
},
|
},
|
||||||
"require-yaml": {
|
"require-yaml": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/require-yaml/-/require-yaml-0.0.1.tgz",
|
||||||
|
"integrity": "sha512-M6eVEgLPRbeOhgSCnOTtdrOOEQzbXRchg24Xa13c39dMuraFKdI9emUo97Rih0YEFzSICmSKg8w4RQp+rd9pOQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"js-yaml": ""
|
"js-yaml": ""
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"argparse": {
|
"argparse": {
|
||||||
"version": "2.0.1"
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
|
||||||
},
|
},
|
||||||
"js-yaml": {
|
"js-yaml": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"argparse": "^2.0.1"
|
"argparse": "^2.0.1"
|
||||||
}
|
}
|
||||||
|
@ -245,10 +300,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sprintf-js": {
|
"sprintf-js": {
|
||||||
"version": "1.0.3"
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
|
||||||
},
|
},
|
||||||
"validator": {
|
"validator": {
|
||||||
"version": "6.3.0"
|
"version": "6.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/validator/-/validator-6.3.0.tgz",
|
||||||
|
"integrity": "sha512-BylxTwhqwjQI5MDJF7amCy/L0ejJO+74DvCsLV52Lq3+3bhVcVMKqNqOiNcQJm2G48u9EAcw4xFERAmFbwXM9Q=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,8 +147,10 @@
|
||||||
"Receipt's bank was not found": "Receipt's bank was not found",
|
"Receipt's bank was not found": "Receipt's bank was not found",
|
||||||
"This receipt was not compensated": "This receipt was not compensated",
|
"This receipt was not compensated": "This receipt was not compensated",
|
||||||
"Client's email was not found": "Client's email was not found",
|
"Client's email was not found": "Client's email was not found",
|
||||||
"Tickets with associated refunds": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº {{id}}",
|
"Tickets with associated refunds": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº {{id}}",
|
||||||
"It is not possible to modify tracked sales": "It is not possible to modify tracked sales",
|
"It is not possible to modify tracked sales": "It is not possible to modify tracked sales",
|
||||||
"It is not possible to modify sales that their articles are from Floramondo": "It is not possible to modify sales that their articles are from Floramondo",
|
"It is not possible to modify sales that their articles are from Floramondo": "It is not possible to modify sales that their articles are from Floramondo",
|
||||||
"It is not possible to modify cloned sales": "It is not possible to modify cloned sales"
|
"It is not possible to modify cloned sales": "It is not possible to modify cloned sales",
|
||||||
}
|
"Valid priorities: 1,2,3": "Valid priorities: 1,2,3",
|
||||||
|
"Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº 2": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº 2"
|
||||||
|
}
|
|
@ -1,12 +1,12 @@
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('isEditable', {
|
Self.remoteMethodCtx('isEditable', {
|
||||||
description: 'Check if a claim is editable',
|
description: 'Check if an state is editable',
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: [{
|
accepts: [{
|
||||||
arg: 'id',
|
arg: 'id',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
required: true,
|
required: true,
|
||||||
description: 'the claim id',
|
description: 'the state id',
|
||||||
http: {source: 'path'}
|
http: {source: 'path'}
|
||||||
}],
|
}],
|
||||||
returns: {
|
returns: {
|
||||||
|
@ -21,25 +21,18 @@ module.exports = Self => {
|
||||||
|
|
||||||
Self.isEditable = async(ctx, id, options) => {
|
Self.isEditable = async(ctx, id, options) => {
|
||||||
const userId = ctx.req.accessToken.userId;
|
const userId = ctx.req.accessToken.userId;
|
||||||
|
const models = Self.app.models;
|
||||||
const myOptions = {};
|
const myOptions = {};
|
||||||
|
|
||||||
if (typeof options == 'object')
|
if (typeof options == 'object')
|
||||||
Object.assign(myOptions, options);
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
const isClaimManager = await Self.app.models.Account.hasRole(userId, 'claimManager', myOptions);
|
const state = await models.ClaimState.findById(id, {
|
||||||
|
include: {
|
||||||
const claim = await Self.app.models.Claim.findById(id, {
|
relation: 'writeRole'
|
||||||
fields: ['claimStateFk'],
|
}
|
||||||
include: [{
|
}, myOptions);
|
||||||
relation: 'claimState'
|
const roleWithGrants = state && state.writeRole().name;
|
||||||
}]
|
return await models.Account.hasRole(userId, roleWithGrants, myOptions);
|
||||||
}, myOptions);
|
|
||||||
|
|
||||||
const isClaimResolved = claim && claim.claimState().code == 'resolved';
|
|
||||||
|
|
||||||
if (!claim || (isClaimResolved && !isClaimManager))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
|
@ -1,16 +1,16 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('claim isEditable()', () => {
|
describe('claimstate isEditable()', () => {
|
||||||
const salesPerdonId = 18;
|
const salesPersonId = 18;
|
||||||
const claimManagerId = 72;
|
const claimManagerId = 72;
|
||||||
it('should return false if the given claim does not exist', async() => {
|
it('should return false if the given state does not exist', async() => {
|
||||||
const tx = await app.models.Claim.beginTransaction({});
|
const tx = await app.models.Claim.beginTransaction({});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
const ctx = {req: {accessToken: {userId: claimManagerId}}};
|
const ctx = {req: {accessToken: {userId: claimManagerId}}};
|
||||||
const result = await app.models.Claim.isEditable(ctx, 99999, options);
|
const result = await app.models.ClaimState.isEditable(ctx, 9999, options);
|
||||||
|
|
||||||
expect(result).toEqual(false);
|
expect(result).toEqual(false);
|
||||||
|
|
||||||
|
@ -27,8 +27,8 @@ describe('claim isEditable()', () => {
|
||||||
try {
|
try {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
const ctx = {req: {accessToken: {userId: salesPerdonId}}};
|
const ctx = {req: {accessToken: {userId: salesPersonId}}};
|
||||||
const result = await app.models.Claim.isEditable(ctx, 4, options);
|
const result = await app.models.ClaimState.isEditable(ctx, 3, options);
|
||||||
|
|
||||||
expect(result).toEqual(false);
|
expect(result).toEqual(false);
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ describe('claim isEditable()', () => {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
const ctx = {req: {accessToken: {userId: claimManagerId}}};
|
const ctx = {req: {accessToken: {userId: claimManagerId}}};
|
||||||
const result = await app.models.Claim.isEditable(ctx, 4, options);
|
const result = await app.models.ClaimState.isEditable(ctx, 3, options);
|
||||||
|
|
||||||
expect(result).toEqual(true);
|
expect(result).toEqual(true);
|
||||||
|
|
||||||
|
@ -63,8 +63,8 @@ describe('claim isEditable()', () => {
|
||||||
try {
|
try {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
const ctx = {req: {accessToken: {userId: salesPerdonId}}};
|
const ctx = {req: {accessToken: {userId: claimManagerId}}};
|
||||||
const result = await app.models.Claim.isEditable(ctx, 1, options);
|
const result = await app.models.ClaimState.isEditable(ctx, 7, options);
|
||||||
|
|
||||||
expect(result).toEqual(true);
|
expect(result).toEqual(true);
|
||||||
|
|
|
@ -65,7 +65,8 @@ module.exports = Self => {
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
promises.push(Self.app.models.Claim.find(filter, myOptions));
|
const models = Self.app.models;
|
||||||
|
promises.push(models.Claim.find(filter, myOptions));
|
||||||
|
|
||||||
// Claim detail
|
// Claim detail
|
||||||
filter = {
|
filter = {
|
||||||
|
@ -82,7 +83,7 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
promises.push(Self.app.models.ClaimBeginning.find(filter, myOptions));
|
promises.push(models.ClaimBeginning.find(filter, myOptions));
|
||||||
|
|
||||||
// Claim observations
|
// Claim observations
|
||||||
filter = {
|
filter = {
|
||||||
|
@ -96,7 +97,7 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
promises.push(Self.app.models.ClaimObservation.find(filter, myOptions));
|
promises.push(models.ClaimObservation.find(filter, myOptions));
|
||||||
|
|
||||||
// Claim developments
|
// Claim developments
|
||||||
filter = {
|
filter = {
|
||||||
|
@ -128,7 +129,7 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
promises.push(Self.app.models.ClaimDevelopment.find(filter, myOptions));
|
promises.push(models.ClaimDevelopment.find(filter, myOptions));
|
||||||
|
|
||||||
// Claim action
|
// Claim action
|
||||||
filter = {
|
filter = {
|
||||||
|
@ -145,11 +146,11 @@ module.exports = Self => {
|
||||||
{relation: 'claimBeggining'}
|
{relation: 'claimBeggining'}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
promises.push(Self.app.models.ClaimEnd.find(filter, myOptions));
|
promises.push(models.ClaimEnd.find(filter, myOptions));
|
||||||
|
|
||||||
const res = await Promise.all(promises);
|
const res = await Promise.all(promises);
|
||||||
|
|
||||||
summary.isEditable = await Self.isEditable(ctx, id, myOptions);
|
summary.isEditable = await models.ClaimState.isEditable(ctx, res[0][0].claimStateFk, myOptions);
|
||||||
[summary.claim] = res[0];
|
[summary.claim] = res[0];
|
||||||
summary.salesClaimed = res[1];
|
summary.salesClaimed = res[1];
|
||||||
summary.observations = res[2];
|
summary.observations = res[2];
|
||||||
|
|
|
@ -0,0 +1,134 @@
|
||||||
|
|
||||||
|
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||||
|
const buildFilter = require('vn-loopback/util/filter').buildFilter;
|
||||||
|
const {mergeFilters, mergeWhere} = require('vn-loopback/util/filter');
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('logs', {
|
||||||
|
description: 'Find all claim logs of the claim entity matched by a filter',
|
||||||
|
accessType: 'READ',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'id',
|
||||||
|
type: 'Number',
|
||||||
|
description: 'The claim id',
|
||||||
|
http: {source: 'path'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'filter',
|
||||||
|
type: 'object',
|
||||||
|
http: {source: 'query'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'search',
|
||||||
|
type: 'string',
|
||||||
|
http: {source: 'query'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'userFk',
|
||||||
|
type: 'number',
|
||||||
|
http: {source: 'query'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'created',
|
||||||
|
type: 'date',
|
||||||
|
http: {source: 'query'}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: ['object'],
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/:id/logs`,
|
||||||
|
verb: 'GET'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.logs = async(ctx, id, filter, options) => {
|
||||||
|
const conn = Self.dataSource.connector;
|
||||||
|
const args = ctx.args;
|
||||||
|
const myOptions = {};
|
||||||
|
let to;
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
let where = buildFilter(args, (param, value) => {
|
||||||
|
switch (param) {
|
||||||
|
case 'search':
|
||||||
|
return {
|
||||||
|
or: [
|
||||||
|
{changedModel: {like: `%${value}%`}},
|
||||||
|
{oldInstance: {like: `%${value}%`}}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
case 'userFk':
|
||||||
|
return {'cl.userFk': value};
|
||||||
|
case 'created':
|
||||||
|
value.setHours(0, 0, 0, 0);
|
||||||
|
to = new Date(value);
|
||||||
|
to.setHours(23, 59, 59, 999);
|
||||||
|
|
||||||
|
return {creationDate: {between: [value, to]}};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
where = mergeWhere(where, {['cl.originFk']: id});
|
||||||
|
filter = mergeFilters(args.filter, {where});
|
||||||
|
|
||||||
|
const stmts = [];
|
||||||
|
|
||||||
|
const stmt = new ParameterizedSQL(
|
||||||
|
`SELECT
|
||||||
|
cl.id,
|
||||||
|
cl.userFk,
|
||||||
|
u.name AS userName,
|
||||||
|
cl.oldInstance,
|
||||||
|
cl.newInstance,
|
||||||
|
cl.changedModel,
|
||||||
|
cl.action,
|
||||||
|
cl.creationDate AS created
|
||||||
|
FROM claimLog cl
|
||||||
|
JOIN account.user u ON u.id = cl.userFk
|
||||||
|
`
|
||||||
|
);
|
||||||
|
|
||||||
|
stmt.merge(conn.makeSuffix(filter));
|
||||||
|
stmts.push(stmt);
|
||||||
|
|
||||||
|
const sql = ParameterizedSQL.join(stmts, ';');
|
||||||
|
const result = await conn.executeStmt(sql, myOptions);
|
||||||
|
|
||||||
|
const logs = [];
|
||||||
|
for (const row of result) {
|
||||||
|
const changes = [];
|
||||||
|
const oldInstance = JSON.parse(row.oldInstance);
|
||||||
|
const newInstance = JSON.parse(row.newInstance);
|
||||||
|
const mergedProperties = [...Object.keys(oldInstance), ...Object.keys(newInstance)];
|
||||||
|
const properties = new Set(mergedProperties);
|
||||||
|
for (const property of properties) {
|
||||||
|
let oldValue = oldInstance[property];
|
||||||
|
let newValue = newInstance[property];
|
||||||
|
|
||||||
|
const change = {
|
||||||
|
property: property,
|
||||||
|
before: oldValue,
|
||||||
|
after: newValue,
|
||||||
|
};
|
||||||
|
|
||||||
|
changes.push(change);
|
||||||
|
}
|
||||||
|
|
||||||
|
logs.push({
|
||||||
|
model: row.changedModel,
|
||||||
|
action: row.action,
|
||||||
|
created: row.created,
|
||||||
|
userFk: row.userFk,
|
||||||
|
userName: row.userName,
|
||||||
|
changes: changes,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return logs;
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,23 @@
|
||||||
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('claim log()', () => {
|
||||||
|
const claimId = 1;
|
||||||
|
const salesPersonId = 18;
|
||||||
|
|
||||||
|
it('should return results filtering by user id', async() => {
|
||||||
|
const result = await app.models.Claim.logs({args: {userFk: salesPersonId}}, claimId);
|
||||||
|
|
||||||
|
const expectedObject = {
|
||||||
|
model: 'Claim',
|
||||||
|
action: 'update',
|
||||||
|
changes: [
|
||||||
|
{property: 'hasToPickUp', before: false, after: true}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
const firstRow = result[0];
|
||||||
|
|
||||||
|
expect(result.length).toBeGreaterThan(0);
|
||||||
|
expect(firstRow).toEqual(jasmine.objectContaining(expectedObject));
|
||||||
|
});
|
||||||
|
});
|
|
@ -2,6 +2,7 @@ const UserError = require('vn-loopback/util/user-error');
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethod('updateClaim', {
|
Self.remoteMethod('updateClaim', {
|
||||||
description: 'Update a claim with privileges',
|
description: 'Update a claim with privileges',
|
||||||
|
accessType: 'WRITE',
|
||||||
accepts: [{
|
accepts: [{
|
||||||
arg: 'ctx',
|
arg: 'ctx',
|
||||||
type: 'object',
|
type: 'object',
|
||||||
|
@ -78,11 +79,11 @@ module.exports = Self => {
|
||||||
|
|
||||||
// Validate when claimState has been changed
|
// Validate when claimState has been changed
|
||||||
if (args.claimStateFk) {
|
if (args.claimStateFk) {
|
||||||
const canUpdate = await canChangeState(ctx, claim.claimStateFk, myOptions);
|
const canEditOldState = await models.ClaimState.isEditable(ctx, claim.claimStateFk, myOptions);
|
||||||
const hasRights = await canChangeState(ctx, args.claimStateFk, myOptions);
|
const canEditNewState = await models.ClaimState.isEditable(ctx, args.claimStateFk, myOptions);
|
||||||
const isClaimManager = await models.Account.hasRole(userId, 'claimManager', myOptions);
|
const isClaimManager = await models.Account.hasRole(userId, 'claimManager', myOptions);
|
||||||
|
|
||||||
if (!canUpdate || !hasRights || changedHasToPickUp && !isClaimManager)
|
if (!canEditOldState || !canEditNewState || changedHasToPickUp && !isClaimManager)
|
||||||
throw new UserError(`You don't have enough privileges to change that field`);
|
throw new UserError(`You don't have enough privileges to change that field`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,21 +114,6 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
async function canChangeState(ctx, id, options) {
|
|
||||||
let models = Self.app.models;
|
|
||||||
let userId = ctx.req.accessToken.userId;
|
|
||||||
|
|
||||||
let state = await models.ClaimState.findById(id, {
|
|
||||||
include: {
|
|
||||||
relation: 'writeRole'
|
|
||||||
}
|
|
||||||
}, options);
|
|
||||||
let stateRole = state.writeRole().name;
|
|
||||||
let canUpdate = await models.Account.hasRole(userId, stateRole, options);
|
|
||||||
|
|
||||||
return canUpdate;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function notifyStateChange(ctx, workerId, claim, state) {
|
async function notifyStateChange(ctx, workerId, claim, state) {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const origin = ctx.req.headers.origin;
|
const origin = ctx.req.headers.origin;
|
||||||
|
|
|
@ -11,7 +11,7 @@ module.exports = Self => {
|
||||||
|
|
||||||
Self.observe('before save', async ctx => {
|
Self.observe('before save', async ctx => {
|
||||||
if (ctx.isNewInstance) return;
|
if (ctx.isNewInstance) return;
|
||||||
await claimIsEditable(ctx);
|
//await claimIsEditable(ctx);
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.observe('before delete', async ctx => {
|
Self.observe('before delete', async ctx => {
|
||||||
|
@ -22,8 +22,28 @@ module.exports = Self => {
|
||||||
async function claimIsEditable(ctx) {
|
async function claimIsEditable(ctx) {
|
||||||
const loopBackContext = LoopBackContext.getCurrentContext();
|
const loopBackContext = LoopBackContext.getCurrentContext();
|
||||||
const httpCtx = {req: loopBackContext.active};
|
const httpCtx = {req: loopBackContext.active};
|
||||||
|
const models = Self.app.models;
|
||||||
|
const myOptions = {};
|
||||||
|
|
||||||
|
if (ctx.options && ctx.options.transaction)
|
||||||
|
myOptions.transaction = ctx.options.transaction;
|
||||||
|
|
||||||
const claimBeginning = await Self.findById(ctx.where.id);
|
const claimBeginning = await Self.findById(ctx.where.id);
|
||||||
const isEditable = await Self.app.models.Claim.isEditable(httpCtx, claimBeginning.claimFk);
|
|
||||||
|
const filter = {
|
||||||
|
where: {id: claimBeginning.claimFk},
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
relation: 'claimState',
|
||||||
|
scope: {
|
||||||
|
fields: ['id', 'code', 'description']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
const [claim] = await models.Claim.find(filter, myOptions);
|
||||||
|
const isEditable = await models.ClaimState.isEditable(httpCtx, claim.claimState().id);
|
||||||
|
|
||||||
if (!isEditable)
|
if (!isEditable)
|
||||||
throw new UserError(`The current claim can't be modified`);
|
throw new UserError(`The current claim can't be modified`);
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
require('../methods/claim-state/isEditable')(Self);
|
||||||
|
};
|
|
@ -6,9 +6,9 @@ module.exports = Self => {
|
||||||
require('../methods/claim/regularizeClaim')(Self);
|
require('../methods/claim/regularizeClaim')(Self);
|
||||||
require('../methods/claim/uploadFile')(Self);
|
require('../methods/claim/uploadFile')(Self);
|
||||||
require('../methods/claim/updateClaimAction')(Self);
|
require('../methods/claim/updateClaimAction')(Self);
|
||||||
require('../methods/claim/isEditable')(Self);
|
|
||||||
require('../methods/claim/updateClaimDestination')(Self);
|
require('../methods/claim/updateClaimDestination')(Self);
|
||||||
require('../methods/claim/downloadFile')(Self);
|
require('../methods/claim/downloadFile')(Self);
|
||||||
require('../methods/claim/claimPickupPdf')(Self);
|
require('../methods/claim/claimPickupPdf')(Self);
|
||||||
require('../methods/claim/claimPickupEmail')(Self);
|
require('../methods/claim/claimPickupEmail')(Self);
|
||||||
|
require('../methods/claim/logs')(Self);
|
||||||
};
|
};
|
||||||
|
|
|
@ -100,8 +100,8 @@ class Controller extends Section {
|
||||||
}
|
}
|
||||||
|
|
||||||
setClaimedQuantity(id, claimedQuantity) {
|
setClaimedQuantity(id, claimedQuantity) {
|
||||||
let params = {id: id, quantity: claimedQuantity};
|
let params = {quantity: claimedQuantity};
|
||||||
let query = `ClaimBeginnings/`;
|
let query = `ClaimBeginnings/${id}`;
|
||||||
this.$http.patch(query, params).then(() => {
|
this.$http.patch(query, params).then(() => {
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||||
this.calculateTotals();
|
this.calculateTotals();
|
||||||
|
@ -151,7 +151,7 @@ class Controller extends Section {
|
||||||
isClaimEditable() {
|
isClaimEditable() {
|
||||||
if (!this.claim) return;
|
if (!this.claim) return;
|
||||||
|
|
||||||
this.$http.get(`Claims/${this.claim.id}/isEditable`).then(res => {
|
this.$http.get(`ClaimStates/${this.claim.id}/isEditable`).then(res => {
|
||||||
this.isRewritable = res.data;
|
this.isRewritable = res.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ describe('claim', () => {
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
$httpBackend.whenGET('Claims/ClaimBeginnings').respond({});
|
$httpBackend.whenGET('Claims/ClaimBeginnings').respond({});
|
||||||
$httpBackend.whenGET(`Tickets/1/isEditable`).respond(true);
|
$httpBackend.whenGET(`Tickets/1/isEditable`).respond(true);
|
||||||
$httpBackend.whenGET(`Claims/2/isEditable`).respond(true);
|
$httpBackend.whenGET(`ClaimStates/2/isEditable`).respond(true);
|
||||||
const $element = angular.element('<vn-claim-detail></vn-claim-detail>');
|
const $element = angular.element('<vn-claim-detail></vn-claim-detail>');
|
||||||
controller = $componentController('vnClaimDetail', {$element, $scope});
|
controller = $componentController('vnClaimDetail', {$element, $scope});
|
||||||
controller.claim = {
|
controller.claim = {
|
||||||
|
@ -89,9 +89,12 @@ describe('claim', () => {
|
||||||
|
|
||||||
describe('setClaimedQuantity(id, claimedQuantity)', () => {
|
describe('setClaimedQuantity(id, claimedQuantity)', () => {
|
||||||
it('should make a patch and call refresh and showSuccess', () => {
|
it('should make a patch and call refresh and showSuccess', () => {
|
||||||
|
const id = 1;
|
||||||
|
const claimedQuantity = 1;
|
||||||
|
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
jest.spyOn(controller.vnApp, 'showSuccess');
|
||||||
$httpBackend.expectPATCH(`ClaimBeginnings/`).respond({});
|
$httpBackend.expectPATCH(`ClaimBeginnings/${id}`).respond({});
|
||||||
controller.setClaimedQuantity(1, 1);
|
controller.setClaimedQuantity(id, claimedQuantity);
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
||||||
|
|
|
@ -32,45 +32,66 @@ module.exports = Self => {
|
||||||
|
|
||||||
Self.confirm = async(signatureVersion, merchantParameters, signature) => {
|
Self.confirm = async(signatureVersion, merchantParameters, signature) => {
|
||||||
const $ = Self.app.models;
|
const $ = Self.app.models;
|
||||||
|
let transaction;
|
||||||
|
|
||||||
const decodedParams = JSON.parse(
|
try {
|
||||||
base64url.decode(merchantParameters, 'utf8'));
|
const decodedParams = JSON.parse(
|
||||||
const params = {};
|
base64url.decode(merchantParameters, 'utf8'));
|
||||||
|
const params = {};
|
||||||
|
|
||||||
for (const param in decodedParams)
|
for (const param in decodedParams)
|
||||||
params[param] = decodeURIComponent(decodedParams[param]);
|
params[param] = decodeURIComponent(decodedParams[param]);
|
||||||
|
|
||||||
const orderId = params['Ds_Order'];
|
const orderId = params['Ds_Order'];
|
||||||
const merchantId = parseInt(params['Ds_MerchantCode']);
|
if (!orderId)
|
||||||
|
throw new UserError('Order id not provided');
|
||||||
|
|
||||||
if (!orderId)
|
transaction = await Self.findById(orderId, {fields: ['id']});
|
||||||
throw new UserError('Order id not found');
|
if (!transaction)
|
||||||
if (!merchantId)
|
throw new UserError('Order not found');
|
||||||
throw new UserError('Mechant id not found');
|
|
||||||
|
|
||||||
const merchant = await $.TpvMerchant.findById(merchantId, {
|
await transaction.updateAttributes({
|
||||||
fields: ['id', 'secretKey']
|
merchantParameters,
|
||||||
});
|
signature,
|
||||||
|
signatureVersion,
|
||||||
|
});
|
||||||
|
|
||||||
const base64hmac = Self.createSignature(
|
const merchantId = parseInt(params['Ds_MerchantCode']);
|
||||||
orderId,
|
if (!merchantId)
|
||||||
merchant.secretKey,
|
throw new UserError('Merchant id not provided');
|
||||||
merchantParameters
|
|
||||||
);
|
|
||||||
|
|
||||||
if (base64hmac !== base64url.toBase64(signature))
|
const merchant = await $.TpvMerchant.findById(merchantId, {
|
||||||
throw new UserError('Invalid signature');
|
fields: ['id', 'secretKey']
|
||||||
|
});
|
||||||
|
if (!merchant)
|
||||||
|
throw new UserError('Merchant not found');
|
||||||
|
|
||||||
await Self.rawSql(
|
const base64hmac = Self.createSignature(
|
||||||
'CALL hedera.tpvTransaction_confirm(?, ?, ?, ?, ?, ?)', [
|
|
||||||
params['Ds_Amount'],
|
|
||||||
orderId,
|
orderId,
|
||||||
merchantId,
|
merchant.secretKey,
|
||||||
params['Ds_Currency'],
|
merchantParameters
|
||||||
params['Ds_Response'],
|
);
|
||||||
params['Ds_ErrorCode']
|
|
||||||
]);
|
|
||||||
|
|
||||||
return true;
|
if (base64hmac !== base64url.toBase64(signature))
|
||||||
|
throw new UserError('Invalid signature');
|
||||||
|
|
||||||
|
await Self.rawSql(
|
||||||
|
'CALL hedera.tpvTransaction_confirm(?, ?, ?, ?, ?, ?)', [
|
||||||
|
params['Ds_Amount'],
|
||||||
|
orderId,
|
||||||
|
merchantId,
|
||||||
|
params['Ds_Currency'],
|
||||||
|
params['Ds_Response'],
|
||||||
|
params['Ds_ErrorCode']
|
||||||
|
]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (err) {
|
||||||
|
if (transaction)
|
||||||
|
await transaction.updateAttribute('responseError', err.message);
|
||||||
|
else
|
||||||
|
console.error(err);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -154,6 +154,11 @@
|
||||||
"model": "Account",
|
"model": "Account",
|
||||||
"foreignKey": "id"
|
"foreignKey": "id"
|
||||||
},
|
},
|
||||||
|
"user": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Account",
|
||||||
|
"foreignKey": "id"
|
||||||
|
},
|
||||||
"payMethod": {
|
"payMethod": {
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "PayMethod",
|
"model": "PayMethod",
|
||||||
|
|
|
@ -35,6 +35,18 @@
|
||||||
},
|
},
|
||||||
"created": {
|
"created": {
|
||||||
"type": "date"
|
"type": "date"
|
||||||
|
},
|
||||||
|
"merchantParameters": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"signature": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"signatureVersion": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"responseError": {
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"relations": {
|
"relations": {
|
||||||
|
@ -45,4 +57,3 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ module.exports = Self => {
|
||||||
try {
|
try {
|
||||||
const invoiceOut = await Self.findById(id, null, myOptions);
|
const invoiceOut = await Self.findById(id, null, myOptions);
|
||||||
const hasInvoicing = await models.Account.hasRole(userId, 'invoicing', myOptions);
|
const hasInvoicing = await models.Account.hasRole(userId, 'invoicing', myOptions);
|
||||||
|
console.log(invoiceOut, !hasInvoicing);
|
||||||
if (invoiceOut.hasPdf && !hasInvoicing)
|
if (invoiceOut.hasPdf && !hasInvoicing)
|
||||||
throw new UserError(`You don't have enough privileges`);
|
throw new UserError(`You don't have enough privileges`);
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ module.exports = Self => {
|
||||||
try {
|
try {
|
||||||
await fs.access(file.path);
|
await fs.access(file.path);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await Self.createPdf(ctx, id);
|
await Self.createPdf(ctx, id, myOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
const stream = fs.createReadStream(file.path);
|
const stream = fs.createReadStream(file.path);
|
||||||
|
|
|
@ -47,6 +47,7 @@ module.exports = Self => {
|
||||||
ids = ids.split(',');
|
ids = ids.split(',');
|
||||||
|
|
||||||
for (let id of ids) {
|
for (let id of ids) {
|
||||||
|
console.log(zipConfig, totalSize, zipConfig ? zipConfig.maxSize : null);
|
||||||
if (zipConfig && totalSize > zipConfig.maxSize) throw new UserError('Files are too large');
|
if (zipConfig && totalSize > zipConfig.maxSize) throw new UserError('Files are too large');
|
||||||
const invoiceOutPdf = await models.InvoiceOut.download(ctx, id, myOptions);
|
const invoiceOutPdf = await models.InvoiceOut.download(ctx, id, myOptions);
|
||||||
const fileName = extractFileName(invoiceOutPdf[2]);
|
const fileName = extractFileName(invoiceOutPdf[2]);
|
||||||
|
|
|
@ -11,7 +11,6 @@ describe('InvoiceOut createPdf()', () => {
|
||||||
const ctx = {req: activeCtx};
|
const ctx = {req: activeCtx};
|
||||||
|
|
||||||
it('should create a new PDF file and set true the hasPdf property', async() => {
|
it('should create a new PDF file and set true the hasPdf property', async() => {
|
||||||
pending('https://redmine.verdnatura.es/issues/5035');
|
|
||||||
const invoiceId = 1;
|
const invoiceId = 1;
|
||||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
active: activeCtx
|
active: activeCtx
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
const models = require('vn-loopback/server/server').models;
|
|
||||||
const UserError = require('vn-loopback/util/user-error');
|
|
||||||
|
|
||||||
describe('InvoiceOut downloadZip()', () => {
|
|
||||||
const userId = 9;
|
|
||||||
const invoiceIds = '1,2';
|
|
||||||
const ctx = {
|
|
||||||
req: {
|
|
||||||
|
|
||||||
accessToken: {userId: userId},
|
|
||||||
headers: {origin: 'http://localhost:5000'},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
it('should return part of link to dowloand the zip', async() => {
|
|
||||||
const tx = await models.InvoiceOut.beginTransaction({});
|
|
||||||
|
|
||||||
try {
|
|
||||||
const options = {transaction: tx};
|
|
||||||
|
|
||||||
const result = await models.InvoiceOut.downloadZip(ctx, invoiceIds, options);
|
|
||||||
|
|
||||||
expect(result).toBeDefined();
|
|
||||||
|
|
||||||
await tx.rollback();
|
|
||||||
} catch (e) {
|
|
||||||
await tx.rollback();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return an error if the size of the files is too large', async() => {
|
|
||||||
pending('https://redmine.verdnatura.es/issues/5035');
|
|
||||||
|
|
||||||
const tx = await models.InvoiceOut.beginTransaction({});
|
|
||||||
|
|
||||||
let error;
|
|
||||||
try {
|
|
||||||
const options = {transaction: tx};
|
|
||||||
const zipConfig = {
|
|
||||||
maxSize: 0
|
|
||||||
};
|
|
||||||
await models.ZipConfig.create(zipConfig, options);
|
|
||||||
|
|
||||||
await models.InvoiceOut.downloadZip(ctx, invoiceIds, options);
|
|
||||||
|
|
||||||
await tx.rollback();
|
|
||||||
} catch (e) {
|
|
||||||
await tx.rollback();
|
|
||||||
error = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(error).toEqual(new UserError(`Files are too large`));
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -65,8 +65,9 @@ describe('InvoiceOut filter()', () => {
|
||||||
await invoiceOut.updateAttribute('hasPdf', true, options);
|
await invoiceOut.updateAttribute('hasPdf', true, options);
|
||||||
|
|
||||||
const result = await models.InvoiceOut.filter(ctx, {id: invoiceOut.id}, options);
|
const result = await models.InvoiceOut.filter(ctx, {id: invoiceOut.id}, options);
|
||||||
|
console.log(result);
|
||||||
|
|
||||||
expect(result.length).toBeGreaterThanOrEqual(1);
|
expect(result.length).toEqual(1);
|
||||||
|
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
description="$ctrl.invoiceOut.ref"
|
description="$ctrl.invoiceOut.ref"
|
||||||
summary="$ctrl.$.summary">
|
summary="$ctrl.$.summary">
|
||||||
<slot-dot-menu>
|
<slot-dot-menu>
|
||||||
<vn-invoice-out-descriptor-menu
|
<vn-invoice-out-descriptor-menu
|
||||||
invoice-out="$ctrl.invoiceOut"
|
invoice-out="$ctrl.invoiceOut"
|
||||||
parent-reload="$ctrl.reload()"
|
parent-reload="$ctrl.reload()"
|
||||||
/>
|
/>
|
||||||
|
@ -11,23 +11,23 @@
|
||||||
<slot-body>
|
<slot-body>
|
||||||
<div class="attributes">
|
<div class="attributes">
|
||||||
<vn-label-value
|
<vn-label-value
|
||||||
label="Date"
|
label="Date"
|
||||||
value="{{$ctrl.invoiceOut.issued | date: 'dd/MM/yyyy'}}">
|
value="{{$ctrl.invoiceOut.issued | date: 'dd/MM/yyyy'}}">
|
||||||
</vn-label-value>
|
</vn-label-value>
|
||||||
<vn-label-value
|
<vn-label-value
|
||||||
label="Import"
|
label="Import"
|
||||||
value="{{$ctrl.invoiceOut.amount | currency: 'EUR': 2}}">
|
value="{{$ctrl.invoiceOut.amount | currency: 'EUR': 2}}">
|
||||||
</vn-label-value>
|
</vn-label-value>
|
||||||
<vn-label-value
|
<vn-label-value
|
||||||
label="Client">
|
label="Client">
|
||||||
<span
|
<span
|
||||||
ng-click="clientDescriptor.show($event, $ctrl.invoiceOut.client.id)"
|
ng-click="clientDescriptor.show($event, $ctrl.invoiceOut.client.id)"
|
||||||
class="link">
|
class="link">
|
||||||
{{$ctrl.invoiceOut.client.name}}
|
{{$ctrl.invoiceOut.client.name}}
|
||||||
</span>
|
</span>
|
||||||
</vn-label-value>
|
</vn-label-value>
|
||||||
<vn-label-value
|
<vn-label-value
|
||||||
label="Company"
|
label="Company"
|
||||||
value="{{$ctrl.invoiceOut.company.code}}">
|
value="{{$ctrl.invoiceOut.company.code}}">
|
||||||
</vn-label-value>
|
</vn-label-value>
|
||||||
</div>
|
</div>
|
||||||
|
@ -53,4 +53,7 @@
|
||||||
</vn-descriptor-content>
|
</vn-descriptor-content>
|
||||||
<vn-popup vn-id="summary">
|
<vn-popup vn-id="summary">
|
||||||
<vn-invoice-out-summary invoice-out="$ctrl.invoiceOut"></vn-invoice-out-summary>
|
<vn-invoice-out-summary invoice-out="$ctrl.invoiceOut"></vn-invoice-out-summary>
|
||||||
</vn-popup>
|
</vn-popup>
|
||||||
|
<vn-client-descriptor-popover
|
||||||
|
vn-id="clientDescriptor">
|
||||||
|
</vn-client-descriptor-popover>
|
||||||
|
|
|
@ -59,17 +59,10 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const writeStream = fs.createWriteStream(filePath);
|
const writeStream = fs.createWriteStream(filePath);
|
||||||
writeStream.on('open', () => {
|
writeStream.on('open', () => response.pipe(writeStream));
|
||||||
response.pipe(writeStream);
|
writeStream.on('error', async error =>
|
||||||
});
|
await errorHandler(image.itemFk, error, filePath));
|
||||||
|
writeStream.on('finish', writeStream.end());
|
||||||
writeStream.on('error', async error => {
|
|
||||||
await errorHandler(image.itemFk, error, filePath);
|
|
||||||
});
|
|
||||||
|
|
||||||
writeStream.on('finish', async function() {
|
|
||||||
writeStream.end();
|
|
||||||
});
|
|
||||||
|
|
||||||
writeStream.on('close', async function() {
|
writeStream.on('close', async function() {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
font-size: .9rem;
|
font-size: .9rem;
|
||||||
width: 30px;
|
height: 28px;
|
||||||
height: 30px;
|
width: 28px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,55 +13,59 @@ module.exports = Self => {
|
||||||
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',
|
{
|
||||||
type: ['Object'],
|
|
||||||
description: 'List of tags to filter with',
|
|
||||||
http: {source: 'query'}
|
|
||||||
}, {
|
|
||||||
arg: 'search',
|
arg: 'search',
|
||||||
type: 'String',
|
type: 'String',
|
||||||
description: `If it's and integer searchs by id, otherwise it searchs by name`,
|
description: `If it's and integer searchs by id, otherwise it searchs by name`,
|
||||||
http: {source: 'query'}
|
http: {source: 'query'}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
arg: 'id',
|
arg: 'id',
|
||||||
type: 'Integer',
|
type: 'Integer',
|
||||||
description: 'The worker id',
|
description: 'The worker id',
|
||||||
http: {source: 'query'}
|
http: {source: 'query'}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
arg: 'userFk',
|
arg: 'userFk',
|
||||||
type: 'Integer',
|
type: 'Integer',
|
||||||
description: 'The user id',
|
description: 'The user id',
|
||||||
http: {source: 'query'}
|
http: {source: 'query'}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
arg: 'fi',
|
arg: 'fi',
|
||||||
type: 'String',
|
type: 'String',
|
||||||
description: 'The worker fi',
|
description: 'The worker fi',
|
||||||
http: {source: 'query'}
|
http: {source: 'query'}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
arg: 'departmentFk',
|
arg: 'departmentFk',
|
||||||
type: 'Integer',
|
type: 'Integer',
|
||||||
description: 'The worker department id',
|
description: 'The worker department id',
|
||||||
http: {source: 'query'}
|
http: {source: 'query'}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
arg: 'extension',
|
arg: 'extension',
|
||||||
type: 'Integer',
|
type: 'Integer',
|
||||||
description: 'The worker extension id',
|
description: 'The worker extension id',
|
||||||
http: {source: 'query'}
|
http: {source: 'query'}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
arg: 'firstName',
|
arg: 'firstName',
|
||||||
type: 'String',
|
type: 'String',
|
||||||
description: 'The worker firstName',
|
description: 'The worker firstName',
|
||||||
http: {source: 'query'}
|
http: {source: 'query'}
|
||||||
}, {
|
},
|
||||||
arg: 'name',
|
{
|
||||||
|
arg: 'lastName',
|
||||||
type: 'String',
|
type: 'String',
|
||||||
description: 'The worker name',
|
description: 'The worker lastName',
|
||||||
http: {source: 'query'}
|
http: {source: 'query'}
|
||||||
}, {
|
},
|
||||||
arg: 'nickname',
|
{
|
||||||
|
arg: 'userName',
|
||||||
type: 'String',
|
type: 'String',
|
||||||
description: 'The worker nickname',
|
description: 'The worker user name',
|
||||||
http: {source: 'query'}
|
http: {source: 'query'}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -93,10 +97,10 @@ module.exports = Self => {
|
||||||
return {'w.id': value};
|
return {'w.id': value};
|
||||||
case 'userFk':
|
case 'userFk':
|
||||||
return {'w.userFk': value};
|
return {'w.userFk': value};
|
||||||
case 'name':
|
|
||||||
return {'w.lastName': {like: `%${value}%`}};
|
|
||||||
case 'firstName':
|
case 'firstName':
|
||||||
return {'w.firstName': {like: `%${value}%`}};
|
return {'w.firstName': {like: `%${value}%`}};
|
||||||
|
case 'lastName':
|
||||||
|
return {'w.lastName': {like: `%${value}%`}};
|
||||||
case 'extension':
|
case 'extension':
|
||||||
return {'p.extension': value};
|
return {'p.extension': value};
|
||||||
case 'fi':
|
case 'fi':
|
||||||
|
|
|
@ -16,7 +16,7 @@ describe('worker filter()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return 2 results filtering by name', async() => {
|
it('should return 2 results filtering by name', async() => {
|
||||||
let result = await app.models.Worker.filter({args: {filter: {}, name: 'agency'}});
|
let result = await app.models.Worker.filter({args: {filter: {}, firstName: 'agency'}});
|
||||||
|
|
||||||
expect(result.length).toEqual(2);
|
expect(result.length).toEqual(2);
|
||||||
expect(result[0].nickname).toEqual('agencyNick');
|
expect(result[0].nickname).toEqual('agencyNick');
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
<vn-textfield
|
<vn-textfield
|
||||||
vn-one
|
vn-one
|
||||||
label="Last name"
|
label="Last name"
|
||||||
ng-model="filter.name">
|
ng-model="filter.lastName">
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -7,37 +7,27 @@ description:
|
||||||
followGuide: Puedes utilizar como guía, el vídeo del montaje del ribon y la cinta
|
followGuide: Puedes utilizar como guía, el vídeo del montaje del ribon y la cinta
|
||||||
<a href='https://www.youtube.com/watch?v=qhb0kgQF3o8' title='Youtube' target='_blank'
|
<a href='https://www.youtube.com/watch?v=qhb0kgQF3o8' title='Youtube' target='_blank'
|
||||||
style='color:#8dba25'>https://www.youtube.com/watch?v=qhb0kgQF3o8</a>. También
|
style='color:#8dba25'>https://www.youtube.com/watch?v=qhb0kgQF3o8</a>. También
|
||||||
necesitarás el QLabel, el programa para imprimir las cintas.
|
necesitarás el GoLabel, el programa para imprimir las cintas.
|
||||||
downloadFrom: Puedes descargarlo desde este enlace <a href='https://cdn.verdnatura.es/public/QLabel_IV_V1.37_Install_en.exe'
|
downloadFrom: Puedes descargarlo desde este enlace <a href='https://godex.s3-accelerate.amazonaws.com/_6f5glRrVhQAEBGhdUsqJA.file?v01'
|
||||||
title='Descargar QLabel' target='_blank' style='color:#8dba25'>https://cdn.verdnatura.es/public/QLabel_IV_V1.37_Install_en.exe</a>
|
title='Descargar GoLabel' target='_blank' style='color:#8dba25'>https://godex.s3-accelerate.amazonaws.com/_6f5glRrVhQAEBGhdUsqJA.file?v01</a>
|
||||||
downloadDriver: En este enlace puedes descargar el driver de la impresora <a href='https://es.seagullscientific.com/support/downloads/drivers/godex/download/'
|
downloadDriver: En este enlace puedes descargar el driver de la impresora <a href='https://es.seagullscientific.com/support/downloads/drivers/godex/download/'
|
||||||
title='Descargar driver' target='_blank' style='color:#8dba25'>https://es.seagullscientific.com/support/downloads/drivers/godex/download/</a>
|
title='Descargar driver' target='_blank' style='color:#8dba25'>https://es.seagullscientific.com/support/downloads/drivers/godex/download/</a>
|
||||||
sections:
|
sections:
|
||||||
QLabel:
|
GoLabel:
|
||||||
title: Utilización de QLabel
|
title: Utilización de GoLabel
|
||||||
description: Para utilizar el programa de impresión de cintas sigue estos pasos
|
description: Para utilizar el programa de impresión de cintas sigue estos pasos
|
||||||
steps:
|
steps:
|
||||||
- Abre el programa QLabel
|
- Abre el programa GoLabel
|
||||||
- Haz clic en el icono de la barra superior con forma de 'carpeta'
|
- Haz clic en el icono de la barra superior con forma de carpeta con una hoja.
|
||||||
- Selecciona el archivo llamado 'model.ezp' adjunto en este correo, y haz clic
|
- Selecciona el archivo llamado 'model.ezp'(que seguramente este en 'Descargas') adjunto en este correo, haz clic en abrir.
|
||||||
en abrir
|
- Una vez abierto el archivo, haz doble click sobre el texto, en el cuadro que nos sale pulse donde esta el texto de ejemplo (En este caso "TUS HERMANOS") y nos saldra en ese mismo recuadro a la parte izquierda para editarlo y escribir lo que quiera.
|
||||||
- Ve a 'File' -> 'Save as' y guárdalo en el escritorio con otro nombre
|
- Cuando ya tenga el texto que desee pulse en el boton 'OK'.
|
||||||
- Cierra el Qlabel y abre el archivo que acabamos de guardar
|
- Ve a 'Archivo' → 'Guardar Como' y guárdelo en el escritorio en el escritorio con otro nombre.
|
||||||
- Haz clic <strong>encima del texto</strong> con el botón secundario del ratón
|
- Luego para imprimir primero deberá configurar la impresora.
|
||||||
- Elige la primera opción 'setup'
|
- Pulse en el octavo icono de la barra de arriba, que en este caso será una impresora con un engranaje naranja.
|
||||||
- Cambia el texto para imprimir
|
- Una vez ahí, pulsaremos en el desplegable de modelo de impresora y elegiremos el modelo que coincida con el nuestro 'G***'.
|
||||||
- Haz clic en el botón 'Ok'
|
- Pulse guardar y ya tendremos nuestra impresora con la configuración guardada.
|
||||||
- Desplázate con el ratón para ver la medida máxima que ocupa el texto
|
- Y por último, para imprimir, haz click en el noveno icono, el cual corresponde a una impresora azul.
|
||||||
- Haz clic <strong>encima del texto</strong> con el botón secundario del ratón
|
|
||||||
- Elige la segunda opción 'Setup printer'
|
|
||||||
- Haz clic en la primera pestaña 'Label Setup'
|
|
||||||
- Modifica la propiedad 'Paper Height' con la medida máxima consultada anteriormente
|
|
||||||
- 'Comprueba el puerto de la impresora, botón de de la derecha ''SETUP PRINTER''
|
|
||||||
y en la parte derecha, igual como la imagen que adjuntamos, seleccionar la que
|
|
||||||
ponga ''USB00x: GODEX'''
|
|
||||||
- Haz clic en el botón 'Ok'
|
|
||||||
- Haz clic sobre el icono de la impresora
|
|
||||||
- Haz clic en 'Print'
|
|
||||||
help:
|
help:
|
||||||
title: "¿Necesitas ayuda?"
|
title: "¿Necesitas ayuda?"
|
||||||
description: Si necesitas ayuda, descárgate nuestro programa de soporte para poder
|
description: Si necesitas ayuda, descárgate nuestro programa de soporte para poder
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
<p v-html="$t('description.downloadFrom')"></p>
|
<p v-html="$t('description.downloadFrom')"></p>
|
||||||
<p v-html="$t('description.downloadDriver')"></p>
|
<p v-html="$t('description.downloadDriver')"></p>
|
||||||
|
|
||||||
<h1>{{$t('sections.QLabel.title')}}</h1>
|
<h1>{{$t('sections.GoLabel.title')}}</h1>
|
||||||
<p>{{$t('sections.QLabel.description')}}:</p>
|
<p>{{$t('sections.GoLabel.description')}}:</p>
|
||||||
<ol>
|
<ol>
|
||||||
<li v-for="step in $t('sections.QLabel.steps')">
|
<li v-for="step in $t('sections.GoLabel.steps')">
|
||||||
<span v-html="step"></span>
|
<span v-html="step"></span>
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
|
@ -22,6 +22,7 @@ module.exports = {
|
||||||
this.labelsData = await this.rawSqlFromDef('labelData', this.id);
|
this.labelsData = await this.rawSqlFromDef('labelData', this.id);
|
||||||
this.username = await this.findOneFromDef('username', this.userFk);
|
this.username = await this.findOneFromDef('username', this.userFk);
|
||||||
this.labelData = this.labelsData[0];
|
this.labelData = this.labelsData[0];
|
||||||
|
this.checkMainEntity(this.labelData);
|
||||||
|
|
||||||
let QRdata = JSON.stringify({
|
let QRdata = JSON.stringify({
|
||||||
company: 'vnl',
|
company: 'vnl',
|
||||||
|
@ -32,7 +33,6 @@ module.exports = {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.QR = await this.getQR(QRdata);
|
this.QR = await this.getQR(QRdata);
|
||||||
this.checkMainEntity(this.labelsData);
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getQR(id) {
|
getQR(id) {
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
SELECT
|
SELECT
|
||||||
io.amount,
|
io2.amount,
|
||||||
io.ref,
|
io2.ref,
|
||||||
io.issued,
|
io2.issued,
|
||||||
ict.description
|
ict.description
|
||||||
FROM invoiceOut io
|
FROM invoiceOut io
|
||||||
JOIN invoiceCorrection ic ON ic.correctingFk = io.id
|
JOIN invoiceCorrection ic ON ic.correctingFk = io.id
|
||||||
JOIN invoiceCorrectionType ict ON ict.id = ic.invoiceCorrectionTypeFk
|
JOIN invoiceOut io2 ON io2.id = ic.correctedFk
|
||||||
LEFT JOIN ticket t ON t.refFk = io.ref
|
LEFT JOIN ticket t ON t.refFk = io.ref
|
||||||
WHERE io.ref = ?
|
JOIN invoiceCorrectionType ict ON ict.id = ic.invoiceCorrectionTypeFk
|
||||||
|
WHERE io.ref = ?
|
||||||
|
|
Loading…
Reference in New Issue