hotFix #5194 cambios ticketFutureAdvance #1320

Merged
alexandre merged 11 commits from 5194-cambios-ticketFutureAdvance into master 2023-02-16 14:05:44 +00:00
16 changed files with 297 additions and 163 deletions

View File

@ -0,0 +1,127 @@
DROP PROCEDURE IF EXISTS `vn`.`ticket_canAdvance`;
DELIMITER $$
$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_canAdvance`(vDateFuture DATE, vDateToAdvance DATE, vWarehouseFk INT)
BEGIN
/**
* Devuelve los tickets y la cantidad de lineas de venta que se pueden adelantar.
*
* @param vDateFuture Fecha de los tickets que se quieren adelantar.
* @param vDateToAdvance Fecha a cuando se quiere adelantar.
* @param vWarehouseFk Almacén
*/
DECLARE vDateInventory DATE;
SELECT inventoried INTO vDateInventory FROM config;
DROP TEMPORARY TABLE IF EXISTS tmp.stock;
CREATE TEMPORARY TABLE tmp.stock
(itemFk INT PRIMARY KEY,
amount INT)
ENGINE = MEMORY;
INSERT INTO tmp.stock(itemFk, amount)
SELECT itemFk, SUM(quantity) amount FROM
(
SELECT itemFk, quantity
FROM itemTicketOut
WHERE shipped >= vDateInventory
AND shipped < vDateFuture
AND warehouseFk = vWarehouseFk
UNION ALL
SELECT itemFk, quantity
FROM itemEntryIn
WHERE landed >= vDateInventory
AND landed < vDateFuture
AND isVirtualStock = FALSE
AND warehouseInFk = vWarehouseFk
UNION ALL
SELECT itemFk, quantity
FROM itemEntryOut
WHERE shipped >= vDateInventory
AND shipped < vDateFuture
AND warehouseOutFk = vWarehouseFk
) t
GROUP BY itemFk HAVING amount != 0;
DROP TEMPORARY TABLE IF EXISTS tmp.filter;
CREATE TEMPORARY TABLE tmp.filter
(INDEX (id))
SELECT
origin.ticketFk futureId,
dest.ticketFk id,
dest.state,
origin.futureState,
origin.futureIpt,
dest.ipt,
origin.workerFk,
origin.futureLiters,
origin.futureLines,
dest.shipped,
origin.shipped futureShipped,
dest.totalWithVat,
origin.totalWithVat futureTotalWithVat,
dest.agency,
origin.futureAgency,
dest.lines,
dest.liters,
origin.futureLines - origin.hasStock AS notMovableLines,
(origin.futureLines = origin.hasStock) AS isFullMovable
FROM (
SELECT
s.ticketFk,
t.workerFk,
t.shipped,
t.totalWithVat,
st.name futureState,
t.addressFk,
am.name futureAgency,
count(s.id) futureLines,
GROUP_CONCAT(DISTINCT ipt.code ORDER BY ipt.code) futureIpt,
CAST(SUM(litros) AS DECIMAL(10,0)) futureLiters,
SUM((s.quantity <= IFNULL(st.amount,0))) hasStock
FROM ticket t
JOIN sale s ON s.ticketFk = t.id
JOIN saleVolume sv ON sv.saleFk = s.id
JOIN item i ON i.id = s.itemFk
JOIN ticketState ts ON ts.ticketFk = t.id
JOIN state st ON st.id = ts.stateFk
JOIN agencyMode am ON t.agencyModeFk = am.id
LEFT JOIN itemPackingType ipt ON ipt.code = i.itemPackingTypeFk
LEFT JOIN tmp.stock st ON st.itemFk = i.id
WHERE t.shipped BETWEEN vDateFuture AND util.dayend(vDateFuture)
AND t.warehouseFk = vWarehouseFk
GROUP BY t.id
) origin
JOIN (
SELECT
t.id ticketFk,
t.addressFk,
st.name state,
GROUP_CONCAT(DISTINCT ipt.code ORDER BY ipt.code) ipt,
t.shipped,
t.totalWithVat,
am.name agency,
CAST(SUM(litros) AS DECIMAL(10,0)) liters,
CAST(COUNT(*) AS DECIMAL(10,0)) `lines`
FROM ticket t
JOIN sale s ON s.ticketFk = t.id
JOIN saleVolume sv ON sv.saleFk = s.id
JOIN item i ON i.id = s.itemFk
JOIN ticketState ts ON ts.ticketFk = t.id
JOIN state st ON st.id = ts.stateFk
JOIN agencyMode am ON t.agencyModeFk = am.id
LEFT JOIN itemPackingType ipt ON ipt.code = i.itemPackingTypeFk
WHERE t.shipped BETWEEN vDateToAdvance AND util.dayend(vDateToAdvance)
AND t.warehouseFk = vWarehouseFk
AND st.order <= 5
GROUP BY t.id
) dest ON dest.addressFk = origin.addressFk
WHERE origin.hasStock != 0;
DROP TEMPORARY TABLE tmp.stock;
END$$
DELIMITER ;

View File

@ -691,7 +691,8 @@ INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeF
(28, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()), (28, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()),
(29, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()), (29, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()),
(30, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()), (30, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()),
(31, 1, 8, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL + 2 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()); (31, 1, 8, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL + 2 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()),
(32, 1, 8, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL + 2 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE());
INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `description`) INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `description`)
VALUES VALUES
@ -993,7 +994,9 @@ INSERT INTO `vn`.`sale`(`id`, `itemFk`, `ticketFk`, `concept`, `quantity`, `pric
(34, 4, 28, 'Melee weapon heavy shield 1x0.5m', 20, 1.72, 0, 0, 0, util.VN_CURDATE()), (34, 4, 28, 'Melee weapon heavy shield 1x0.5m', 20, 1.72, 0, 0, 0, util.VN_CURDATE()),
(35, 4, 29, 'Melee weapon heavy shield 1x0.5m', 20, 1.72, 0, 0, 0, util.VN_CURDATE()), (35, 4, 29, 'Melee weapon heavy shield 1x0.5m', 20, 1.72, 0, 0, 0, util.VN_CURDATE()),
(36, 4, 30, 'Melee weapon heavy shield 1x0.5m', 20, 1.72, 0, 0, 0, util.VN_CURDATE()), (36, 4, 30, 'Melee weapon heavy shield 1x0.5m', 20, 1.72, 0, 0, 0, util.VN_CURDATE()),
(37, 4, 31, 'Melee weapon heavy shield 1x0.5m', 20, 1.72, 0, 0, 0, util.VN_CURDATE()); (37, 4, 31, 'Melee weapon heavy shield 1x0.5m', 20, 1.72, 0, 0, 0, util.VN_CURDATE()),
(38, 2, 32, 'Melee weapon combat fist 15cm', 30, 7.07, 0, 0, 0, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH)),
(39, 1, 32, 'Ranged weapon longbow 2m', 2, 103.49, 0, 0, 0, util.VN_CURDATE());
INSERT INTO `vn`.`saleChecked`(`saleFk`, `isChecked`) INSERT INTO `vn`.`saleChecked`(`saleFk`, `isChecked`)
VALUES VALUES

View File

@ -778,18 +778,16 @@ export default {
ipt: 'vn-autocomplete[label="Destination IPT"]', ipt: 'vn-autocomplete[label="Destination IPT"]',
tableIpt: 'vn-autocomplete[name="ipt"]', tableIpt: 'vn-autocomplete[name="ipt"]',
tableFutureIpt: 'vn-autocomplete[name="futureIpt"]', tableFutureIpt: 'vn-autocomplete[name="futureIpt"]',
futureState: 'vn-check[label="Pending Origin"]', isFullMovable: 'vn-check[ng-model="filter.isFullMovable"]',
state: 'vn-check[label="Pending Destination"]',
warehouseFk: 'vn-autocomplete[label="Warehouse"]', warehouseFk: 'vn-autocomplete[label="Warehouse"]',
tableButtonSearch: 'vn-button[vn-tooltip="Search"]', tableButtonSearch: 'vn-button[vn-tooltip="Search"]',
moveButton: 'vn-button[vn-tooltip="Advance tickets"]', moveButton: 'vn-button[vn-tooltip="Advance tickets"]',
acceptButton: '.vn-confirm.shown button[response="accept"]', acceptButton: '.vn-confirm.shown button[response="accept"]',
multiCheck: 'vn-multi-check', firstCheck: 'tbody > tr:nth-child(1) > td > vn-check',
tableId: 'vn-textfield[name="id"]', tableId: 'vn-textfield[name="id"]',
tableFutureId: 'vn-textfield[name="futureId"]', tableFutureId: 'vn-textfield[name="futureId"]',
tableLiters: 'vn-textfield[name="liters"]', tableLiters: 'vn-textfield[name="liters"]',
tableLines: 'vn-textfield[name="lines"]', tableLines: 'vn-textfield[name="lines"]',
tableStock: 'vn-textfield[name="hasStock"]',
submit: 'vn-submit[label="Search"]', submit: 'vn-submit[label="Search"]',
table: 'tbody > tr:not(.empty-rows)' table: 'tbody > tr:not(.empty-rows)'
}, },

View File

@ -4,12 +4,17 @@ import getBrowser from '../../helpers/puppeteer';
describe('Ticket Advance path', () => { describe('Ticket Advance path', () => {
let browser; let browser;
let page; let page;
const httpRequests = [];
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.advance'); await page.accessToSection('ticket.advance');
page.on('request', req => {
if (req.url().includes(`Tickets/getTicketsAdvance`))
httpRequests.push(req.url());
});
}); });
afterAll(async() => { afterAll(async() => {
@ -43,91 +48,74 @@ describe('Ticket Advance path', () => {
it('should search with the required data', async() => { it('should search with the required data', async() => {
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.waitToClick(selectors.ticketAdvance.submit); await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
expect(httpRequests.length).toBeGreaterThan(0);
}); });
it('should search with the origin IPT', async() => { it('should search with the origin IPT', async() => {
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.autocompleteSearch(selectors.ticketAdvance.ipt, 'Horizontal');
await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.clearInput(selectors.ticketAdvance.ipt);
await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
});
it('should search with the destination IPT', async() => {
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
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);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
const request = httpRequests.find(req => req.includes(('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);
await page.waitToClick(selectors.ticketAdvance.submit); await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
}); });
it('should search with the origin pending state', async() => { it('should search with the destination IPT', async() => {
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.waitToClick(selectors.ticketAdvance.futureState); await page.autocompleteSearch(selectors.ticketAdvance.ipt, 'Horizontal');
await page.waitToClick(selectors.ticketAdvance.submit); await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
const request = httpRequests.find(req => req.includes(('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.waitToClick(selectors.ticketAdvance.futureState); await page.clearInput(selectors.ticketAdvance.ipt);
await page.waitToClick(selectors.ticketAdvance.submit); await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 0);
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.waitToClick(selectors.ticketAdvance.futureState);
await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
});
it('should search with the destination grouped state', async() => {
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.waitToClick(selectors.ticketAdvance.state);
await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 0);
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.waitToClick(selectors.ticketAdvance.state);
await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton);
await page.waitToClick(selectors.ticketAdvance.state);
await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
}); });
it('should search in smart-table with an IPT Origin', async() => { it('should search in smart-table with an IPT Origin', async() => {
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');
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
const request = httpRequests.find(req => req.includes(('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);
await page.waitToClick(selectors.ticketAdvance.submit); await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
}); });
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.ticketAdvance.tableButtonSearch); await page.waitToClick(selectors.ticketAdvance.tableButtonSearch);
await page.autocompleteSearch(selectors.ticketAdvance.tableIpt, 'Vertical'); await page.autocompleteSearch(selectors.ticketAdvance.tableIpt, 'Vertical');
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
const request = httpRequests.find(req => req.includes(('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);
await page.waitToClick(selectors.ticketAdvance.submit); await page.waitToClick(selectors.ticketAdvance.submit);
await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1);
}); });
it('should check the one ticket and move to the present', async() => { it('should check the first ticket and move to the present', async() => {
await page.waitToClick(selectors.ticketAdvance.multiCheck); await page.waitToClick(selectors.ticketAdvance.firstCheck);
await page.waitToClick(selectors.ticketAdvance.moveButton); await page.waitToClick(selectors.ticketAdvance.moveButton);
await page.waitToClick(selectors.ticketAdvance.acceptButton); await page.waitToClick(selectors.ticketAdvance.acceptButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();

View File

@ -12,7 +12,7 @@ describe('item getVisibleAvailable()', () => {
const result = await models.Item.getVisibleAvailable(itemFk, warehouseFk, dated, options); const result = await models.Item.getVisibleAvailable(itemFk, warehouseFk, dated, options);
expect(result.available).toEqual(187); expect(result.available).toEqual(185);
expect(result.visible).toEqual(92); expect(result.visible).toEqual(92);
await tx.rollback(); await tx.rollback();

View File

@ -11,6 +11,8 @@
<vn-card class="vn-w-md vn-pa-md"> <vn-card class="vn-w-md vn-pa-md">
<vn-horizontal> <vn-horizontal>
<vn-date-picker class="vn-pa-xs" <vn-date-picker class="vn-pa-xs"
vn-one
label="Since"
vn-one vn-one
label="Since" label="Since"
ng-model="$ctrl.dateFrom"> ng-model="$ctrl.dateFrom">
@ -35,7 +37,7 @@
<vn-th field="warehouseFk">Warehouse</vn-th> <vn-th field="warehouseFk">Warehouse</vn-th>
<vn-th field="landed">Landed</vn-th> <vn-th field="landed">Landed</vn-th>
<vn-th number>Entry</vn-th> <vn-th number>Entry</vn-th>
<vn-th vn-tooltip="Grouping / Packing">PVP</vn-th> <vn-th vn-tooltip="Grouping / Packing" expand>PVP</vn-th>
<vn-th number class="expendable">Label</vn-th> <vn-th number class="expendable">Label</vn-th>
<vn-th number>Packing</vn-th> <vn-th number>Packing</vn-th>
<vn-th number>Grouping</vn-th> <vn-th number>Grouping</vn-th>
@ -64,7 +66,7 @@
{{::entry.entryFk | dashIfEmpty}} {{::entry.entryFk | dashIfEmpty}}
</span> </span>
</vn-td> </vn-td>
<vn-td title="{{::entry.price2 | currency: 'EUR':2 | dashIfEmpty}} / {{::entry.price3 | currency: 'EUR':2 | dashIfEmpty}}"> <vn-td title="Grouping / Packing">
{{::entry.price2 | currency: 'EUR':2 | dashIfEmpty}} / {{::entry.price3 | currency: 'EUR':2 | dashIfEmpty}} {{::entry.price2 | currency: 'EUR':2 | dashIfEmpty}} / {{::entry.price3 | currency: 'EUR':2 | dashIfEmpty}}
</vn-td> </vn-td>
<vn-td number class="expendable">{{entry.stickers | dashIfEmpty}}</vn-td> <vn-td number class="expendable">{{entry.stickers | dashIfEmpty}}</vn-td>

View File

@ -50,15 +50,9 @@ module.exports = Self => {
required: false required: false
}, },
{ {
arg: 'isNotValidated', arg: 'isFullMovable',
type: 'boolean', type: 'boolean',
description: 'Origin state', description: 'True when lines and stock of origin are equal',
required: false
},
{
arg: 'futureIsNotValidated',
type: 'boolean',
description: 'Destination state',
required: false required: false
}, },
{ {
@ -105,10 +99,8 @@ module.exports = Self => {
{'f.futureIpt': null} {'f.futureIpt': null}
] ]
}; };
case 'isNotValidated': case 'isFullMovable':
return {'f.isNotValidated': value}; return {'f.isFullMovable': value};
case 'futureIsNotValidated':
return {'f.futureIsNotValidated': value};
} }
}); });

View File

@ -1,6 +1,6 @@
const models = require('vn-loopback/server/server').models; const models = require('vn-loopback/server/server').models;
describe('TicketFuture getTicketsAdvance()', () => { describe('ticket getTicketsAdvance()', () => {
const today = new Date(); const today = new Date();
today.setHours(0, 0, 0, 0); today.setHours(0, 0, 0, 0);
let tomorrow = new Date(); let tomorrow = new Date();
@ -29,7 +29,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
} }
}); });
it('should return the tickets matching the origin pending state', async() => { it('should return the tickets matching the fullMovable true', async() => {
const tx = await models.Ticket.beginTransaction({}); const tx = await models.Ticket.beginTransaction({});
try { try {
@ -39,7 +39,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
dateFuture: tomorrow, dateFuture: tomorrow,
dateToAdvance: today, dateToAdvance: today,
warehouseFk: 1, warehouseFk: 1,
futureIsNotValidated: true isFullMovable: true
}; };
const ctx = {req: {accessToken: {userId: 9}}, args}; const ctx = {req: {accessToken: {userId: 9}}, args};
@ -54,7 +54,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
} }
}); });
it('should return the tickets matching the destination pending state', async() => { it('should return the tickets matching the fullMovable false', async() => {
const tx = await models.Ticket.beginTransaction({}); const tx = await models.Ticket.beginTransaction({});
try { try {
@ -64,7 +64,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
dateFuture: tomorrow, dateFuture: tomorrow,
dateToAdvance: today, dateToAdvance: today,
warehouseFk: 1, warehouseFk: 1,
isNotValidated: true isFullMovable: false
}; };
const ctx = {req: {accessToken: {userId: 9}}, args}; const ctx = {req: {accessToken: {userId: 9}}, args};
@ -95,7 +95,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
const ctx = {req: {accessToken: {userId: 9}}, args}; const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsAdvance(ctx, options); const result = await models.Ticket.getTicketsAdvance(ctx, options);
expect(result.length).toBeLessThan(5); expect(result.length).toBeGreaterThan(5);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
@ -120,7 +120,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
const ctx = {req: {accessToken: {userId: 9}}, args}; const ctx = {req: {accessToken: {userId: 9}}, args};
const result = await models.Ticket.getTicketsAdvance(ctx, options); const result = await models.Ticket.getTicketsAdvance(ctx, options);
expect(result.length).toBeLessThan(5); expect(result.length).toBeGreaterThan(5);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {

View File

@ -86,7 +86,7 @@ describe('sale priceDifference()', () => {
const firstItem = result.items[0]; const firstItem = result.items[0];
const secondtItem = result.items[1]; const secondtItem = result.items[1];
expect(firstItem.movable).toEqual(410); expect(firstItem.movable).toEqual(380);
expect(secondtItem.movable).toEqual(1790); expect(secondtItem.movable).toEqual(1790);
await tx.rollback(); await tx.rollback();

View File

@ -41,18 +41,10 @@
<vn-horizontal class="vn-px-lg"> <vn-horizontal class="vn-px-lg">
<vn-check <vn-check
vn-one vn-one
label="Pending Origin" label="100% movable"
ng-model="filter.futureIsNotValidated" ng-model="filter.isFullMovable"
triple-state="true"> triple-state="true">
</vn-check> </vn-check>
<vn-check
vn-one
label="Pending Destination"
ng-model="filter.isNotValidated"
triple-state="true">
</vn-check>
</vn-horizontal>
<vn-horizontal class="vn-px-lg">
<vn-autocomplete <vn-autocomplete
vn-one vn-one
label="Warehouse" label="Warehouse"

View File

@ -1,3 +1,2 @@
Advance tickets: Adelantar tickets Advance tickets: Adelantar tickets
Pending Origin: Pendiente origen 100% movable: 100% movible
Pending Destination: Pendiente destino

View File

@ -32,8 +32,8 @@
<thead> <thead>
<tr second-header> <tr second-header>
<td></td> <td></td>
<th colspan="9" translate>Origin</th>
<th colspan="7" translate>Destination</th> <th colspan="7" translate>Destination</th>
<th colspan="9" translate>Origin</th>
</tr> </tr>
<tr> <tr>
<th shrink> <th shrink>
@ -45,31 +45,7 @@
</th> </th>
<th shrink> <th shrink>
</th> </th>
<th field="futureId"> <th field="id">
<span translate>ID</span>
</th>
<th field="futureShipped">
<span translate>Date</span>
</th>
<th field="futureIpt" title="{{'Item Packing Type' | translate}}">
<span>IPT</span>
</th>
<th field="futureState">
<span translate>State</span>
</th>
<th field="futureLiters">
<span translate>Liters</span>
</th>
<th field="hasStock">
<span>Stock</span>
</th>
<th field="futureLines">
<span translate>Lines</span>
</th>
<th field="futureTotalWithVat">
<span translate>Import</span>
</th>
<th separator field="id">
<span translate>ID</span> <span translate>ID</span>
</th> </th>
<th field="shipped"> <th field="shipped">
@ -90,6 +66,30 @@
<th field="totalWithVat"> <th field="totalWithVat">
<span translate>Import</span> <span translate>Import</span>
</th> </th>
<th separator field="futureId">
<span translate>ID</span>
</th>
<th field="futureShipped">
<span translate>Date</span>
</th>
<th field="futureIpt" title="{{'Item Packing Type' | translate}}">
<span>IPT</span>
</th>
<th field="futureState">
<span translate>State</span>
</th>
<th field="futureLiters">
<span translate>Liters</span>
</th>
<th field="notMovableLines">
<span translate>Not Movable</span>
</th>
<th field="futureLines">
<span translate>Lines</span>
</th>
<th field="futureTotalWithVat">
<span translate>Import</span>
</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -104,36 +104,9 @@
<vn-icon <vn-icon
ng-show="ticket.futureAgency !== ticket.agency" ng-show="ticket.futureAgency !== ticket.agency"
icon="icon-agency-term" icon="icon-agency-term"
vn-tooltip="{{$ctrl.agencies(ticket.futureAgency, ticket.agency)}}"> title="{{$ctrl.agencies(ticket.futureAgency, ticket.agency)}}">
</vn-icon> </vn-icon>
</td> </td>
<td>
<span
ng-click="ticketDescriptor.show($event, ticket.futureId)"
class="link">
{{::ticket.futureId | dashIfEmpty}}
</span>
</td>
<td shrink-date>
<span class="chip {{$ctrl.compareDate(ticket.futureShipped)}}">
{{::ticket.futureShipped | date: 'dd/MM/yyyy'}}
</span>
</td>
<td>{{::ticket.futureIpt | dashIfEmpty}}</td>
<td>
<span
class="chip {{$ctrl.stateColor(ticket.futureState)}}">
{{::ticket.futureState | dashIfEmpty}}
</span>
</td>
<td>{{::ticket.futureLiters | dashIfEmpty}}</td>
<td>{{::ticket.hasStock | dashIfEmpty}}</td>
<td>{{::ticket.futureLines | dashIfEmpty}}</td>
<td>
<span class="chip {{$ctrl.totalPriceColor(ticket.futureTotalWithVat)}}">
{{::(ticket.futureTotalWithVat ? ticket.futureTotalWithVat : 0) | currency: 'EUR': 2}}
</span>
</td>
<td> <td>
<span <span
ng-click="ticketDescriptor.show($event, ticket.id)" ng-click="ticketDescriptor.show($event, ticket.id)"
@ -156,10 +129,42 @@
<td>{{::ticket.liters | dashIfEmpty}}</td> <td>{{::ticket.liters | dashIfEmpty}}</td>
<td>{{::ticket.lines | dashIfEmpty}}</td> <td>{{::ticket.lines | dashIfEmpty}}</td>
<td> <td>
<span class="chip {{$ctrl.totalPriceColor(ticket.totalWithVat)}}"> <span
class="chip {{$ctrl.totalPriceColor(ticket.totalWithVat)}}"
title="{{$ctrl.totalPriceTitle(ticket.totalWithVat) | translate}}">
{{::(ticket.totalWithVat ? ticket.totalWithVat : 0) | currency: 'EUR': 2}} {{::(ticket.totalWithVat ? ticket.totalWithVat : 0) | currency: 'EUR': 2}}
</span> </span>
</td> </td>
<td separator>
<span
ng-click="ticketDescriptor.show($event, ticket.futureId)"
class="link">
{{::ticket.futureId | dashIfEmpty}}
</span>
</td>
<td shrink-date>
<span class="chip {{$ctrl.compareDate(ticket.futureShipped)}}">
{{::ticket.futureShipped | date: 'dd/MM/yyyy'}}
</span>
</td>
<td>{{::ticket.futureIpt | dashIfEmpty}}</td>
<td>
<span
class="chip {{$ctrl.stateColor(ticket.futureState)}}">
{{::ticket.futureState | dashIfEmpty}}
</span>
</td>
<td>{{::ticket.futureLiters | dashIfEmpty}}</td>
<td>{{::ticket.notMovableLines | dashIfEmpty}}</td>
<td>{{::ticket.futureLines | dashIfEmpty}}</td>
<td>
<span
class="chip {{$ctrl.totalPriceColor(ticket.futureTotalWithVat)}}"
title="{{$ctrl.totalPriceTitle(ticket.futureTotalWithVat) | translate}}">
{{::(ticket.futureTotalWithVat ? ticket.futureTotalWithVat : 0) | currency: 'EUR': 2}}
</span>
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

View File

@ -119,9 +119,15 @@ export default class Controller extends Section {
} }
totalPriceColor(totalWithVat) { totalPriceColor(totalWithVat) {
const total = parseInt(totalWithVat); return this.isLessThan50(totalWithVat) ? 'warning' : '';
if (total > 0 && total < 50) }
return 'warning';
totalPriceTitle(totalWithVat) {
return this.isLessThan50(totalWithVat) ? 'Less than 50€' : '';
}
isLessThan50(totalWithVat) {
return (parseInt(totalWithVat) > 0 && parseInt(totalWithVat) < 50);
} }
get confirmationMessage() { get confirmationMessage() {
@ -134,7 +140,7 @@ export default class Controller extends Section {
agencies(futureAgency, agency) { agencies(futureAgency, agency) {
return this.$t(`Origin agency`, {agency: futureAgency}) + return this.$t(`Origin agency`, {agency: futureAgency}) +
'<br/>' + this.$t(`Destination agency`, {agency: agency}); '\n' + this.$t(`Destination agency`, {agency: agency});
} }
moveTicketsAdvance() { moveTicketsAdvance() {
@ -171,15 +177,25 @@ export default class Controller extends Section {
case 'futureLines': case 'futureLines':
return {'futureLines': value}; return {'futureLines': value};
case 'ipt': case 'ipt':
return {'ipt': value}; return {or:
[
{'ipt': {like: `%${value}%`}},
{'ipt': null}
]
};
case 'futureIpt': case 'futureIpt':
return {'futureIpt': value}; return {or:
[
{'futureIpt': {like: `%${value}%`}},
{'futureIpt': null}
]
};
case 'totalWithVat': case 'totalWithVat':
return {'totalWithVat': value}; return {'totalWithVat': value};
case 'futureTotalWithVat': case 'futureTotalWithVat':
return {'futureTotalWithVat': value}; return {'futureTotalWithVat': value};
case 'hasStock': case 'notMovableLines':
return {'hasStock': value}; return {'notMovableLines': value};
} }
} }
} }

View File

@ -7,3 +7,5 @@ Liters: Litros
Item Packing Type: Encajado Item Packing Type: Encajado
Origin agency: "Agencia origen: {{agency}}" Origin agency: "Agencia origen: {{agency}}"
Destination agency: "Agencia destino: {{agency}}" Destination agency: "Agencia destino: {{agency}}"
Less than 50€: Menor a 50€
Not Movable: No movibles

View File

@ -143,7 +143,7 @@
</td> </td>
<td>{{::ticket.liters}}</td> <td>{{::ticket.liters}}</td>
<td>{{::ticket.lines}}</td> <td>{{::ticket.lines}}</td>
<td> <td separator>
<span <span
ng-click="ticketDescriptor.show($event, ticket.futureId)" ng-click="ticketDescriptor.show($event, ticket.futureId)"
class="link"> class="link">

View File

@ -149,9 +149,19 @@ export default class Controller extends Section {
case 'lines': case 'lines':
return {'lines': value}; return {'lines': value};
case 'ipt': case 'ipt':
return {'ipt': value}; return {or:
[
{'ipt': {like: `%${value}%`}},
{'ipt': null}
]
};
case 'futureIpt': case 'futureIpt':
return {'futureIpt': value}; return {or:
[
{'futureIpt': {like: `%${value}%`}},
{'futureIpt': null}
]
};
} }
} }
} }