fixes #4962 Refactor Ticket Tour a Futuro #1212
|
@ -0,0 +1,73 @@
|
|||
DROP PROCEDURE IF EXISTS `vn`.`ticket_canbePostponed`;
|
||||
|
||||
DELIMITER $$
|
||||
$$
|
||||
CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_canbePostponed`(vOriginDated DATE, vFutureDated DATE, vWarehouseFk INT)
|
||||
BEGIN
|
||||
/**
|
||||
* Devuelve un listado de tickets susceptibles de fusionarse con otros tickets en el futuro
|
||||
*
|
||||
* @param vOriginDated Fecha en cuestión
|
||||
* @param vFutureDated Fecha en el futuro a sondear
|
||||
* @param vWarehouseFk Identificador de vn.warehouse
|
||||
*/
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.filter;
|
||||
CREATE TEMPORARY TABLE tmp.filter
|
||||
(INDEX (id))
|
||||
SELECT sv.ticketFk id,
|
||||
GROUP_CONCAT(DISTINCT i.itemPackingTypeFk ORDER BY i.itemPackingTypeFk) ipt,
|
||||
CAST(sum(litros) AS DECIMAL(10,0)) liters,
|
||||
CAST(count(*) AS DECIMAL(10,0)) `lines`,
|
||||
st.name state,
|
||||
sub2.id ticketFuture,
|
||||
sub2.iptd tfIpt,
|
||||
sub2.state tfState,
|
||||
t.clientFk,
|
||||
t.warehouseFk,
|
||||
ts.alertLevel,
|
||||
t.shipped,
|
||||
sub2.shipped tfShipped,
|
||||
t.workerFk,
|
||||
st.code stateCode,
|
||||
sub2.code tfStateCode
|
||||
FROM vn.saleVolume sv
|
||||
JOIN vn.sale s ON s.id = sv.saleFk
|
||||
JOIN vn.item i ON i.id = s.itemFk
|
||||
JOIN vn.ticket t ON t.id = sv.ticketFk
|
||||
JOIN vn.address a ON a.id = t.addressFk
|
||||
JOIN vn.province p ON p.id = a.provinceFk
|
||||
JOIN vn.country c ON c.id = p.countryFk
|
||||
JOIN vn.ticketState ts ON ts.ticketFk = t.id
|
||||
JOIN vn.state st ON st.id = ts.stateFk
|
||||
JOIN vn.alertLevel al ON al.id = ts.alertLevel
|
||||
LEFT JOIN vn.ticketParking tp ON tp.ticketFk = t.id
|
||||
LEFT JOIN (
|
||||
SELECT *
|
||||
FROM (
|
||||
SELECT
|
||||
t.addressFk ,
|
||||
t.id,
|
||||
t.shipped,
|
||||
st.name state,
|
||||
st.code code,
|
||||
GROUP_CONCAT(DISTINCT i.itemPackingTypeFk ORDER BY i.itemPackingTypeFk) iptd
|
||||
FROM vn.ticket t
|
||||
JOIN vn.ticketState ts ON ts.ticketFk = t.id
|
||||
JOIN vn.state st ON st.id = ts.stateFk
|
||||
JOIN vn.sale s ON s.ticketFk = t.id
|
||||
JOIN vn.item i ON i.id = s.itemFk
|
||||
WHERE t.shipped BETWEEN vFutureDated
|
||||
AND util.dayend(vFutureDated)
|
||||
AND t.warehouseFk = vWarehouseFk
|
||||
GROUP BY t.id
|
||||
) sub
|
||||
GROUP BY sub.addressFk
|
||||
) sub2 ON sub2.addressFk = t.addressFk AND t.id != sub2.id
|
||||
WHERE t.shipped BETWEEN vOriginDated AND util.dayend(vOriginDated)
|
||||
AND t.warehouseFk = vWarehouseFk
|
||||
AND al.code = 'FREE'
|
||||
AND tp.ticketFk IS NULL
|
||||
GROUP BY sv.ticketFk
|
||||
HAVING ticketFuture;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -735,10 +735,8 @@ export default {
|
|||
},
|
||||
ticketFuture: {
|
||||
openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]',
|
||||
originDated: 'vn-date-picker[label="Origin ETD"]',
|
||||
futureDated: 'vn-date-picker[label="Destination ETD"]',
|
||||
shipped: 'vn-date-picker[label="Origin date"]',
|
||||
tfShipped: 'vn-date-picker[label="Destination date"]',
|
||||
originDated: 'vn-date-picker[label="Origin date"]',
|
||||
futureDated: 'vn-date-picker[label="Destination date"]',
|
||||
linesMax: 'vn-textfield[label="Max Lines"]',
|
||||
litersMax: 'vn-textfield[label="Max Liters"]',
|
||||
ipt: 'vn-autocomplete[label="Origin IPT"]',
|
||||
|
@ -756,8 +754,8 @@ export default {
|
|||
multiCheck: 'vn-multi-check',
|
||||
tableId: 'vn-textfield[name="id"]',
|
||||
tableTfId: 'vn-textfield[name="ticketFuture"]',
|
||||
tableLiters: 'vn-textfield[name="litersMax"]',
|
||||
tableLines: 'vn-textfield[name="linesMax"]',
|
||||
tableLiters: 'vn-textfield[name="liters"]',
|
||||
|
||||
tableLines: 'vn-textfield[name="lines"]',
|
||||
submit: 'vn-submit[label="Search"]',
|
||||
table: 'tbody > tr:not(.empty-rows)'
|
||||
},
|
||||
|
|
|
@ -16,9 +16,6 @@ describe('Ticket Future path', () => {
|
|||
await browser.close();
|
||||
});
|
||||
|
||||
const now = new Date();
|
||||
const tomorrow = new Date(now.getDate() + 1);
|
||||
|
||||
it('should show errors snackbar because of the required data', async() => {
|
||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||
await page.clearInput(selectors.ticketFuture.warehouseFk);
|
||||
|
@ -27,20 +24,6 @@ describe('Ticket Future path', () => {
|
|||
|
||||
expect(message.text).toContain('warehouseFk is a required argument');
|
||||
|
||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||
await page.clearInput(selectors.ticketFuture.litersMax);
|
||||
await page.waitToClick(selectors.ticketFuture.submit);
|
||||
message = await page.waitForSnackbar();
|
||||
|
||||
expect(message.text).toContain('litersMax is a required argument');
|
||||
|
||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||
await page.clearInput(selectors.ticketFuture.linesMax);
|
||||
await page.waitToClick(selectors.ticketFuture.submit);
|
||||
message = await page.waitForSnackbar();
|
||||
|
||||
expect(message.text).toContain('linesMax is a required argument');
|
||||
|
||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||
await page.clearInput(selectors.ticketFuture.futureDated);
|
||||
await page.waitToClick(selectors.ticketFuture.submit);
|
||||
|
@ -62,40 +45,9 @@ describe('Ticket Future path', () => {
|
|||
await page.waitForNumberOfElements(selectors.ticketFuture.table, 4);
|
||||
});
|
||||
|
||||
it('should search with the origin shipped today', async() => {
|
||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||
await page.pickDate(selectors.ticketFuture.shipped, now);
|
||||
await page.waitToClick(selectors.ticketFuture.submit);
|
||||
await page.waitForNumberOfElements(selectors.ticketFuture.table, 4);
|
||||
});
|
||||
|
||||
it('should search with the origin shipped tomorrow', async() => {
|
||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||
await page.pickDate(selectors.ticketFuture.shipped, tomorrow);
|
||||
await page.waitToClick(selectors.ticketFuture.submit);
|
||||
await page.waitForNumberOfElements(selectors.ticketFuture.table, 0);
|
||||
});
|
||||
|
||||
it('should search with the destination shipped today', async() => {
|
||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||
await page.clearInput(selectors.ticketFuture.shipped);
|
||||
await page.pickDate(selectors.ticketFuture.tfShipped, now);
|
||||
await page.waitToClick(selectors.ticketFuture.submit);
|
||||
await page.waitForNumberOfElements(selectors.ticketFuture.table, 4);
|
||||
});
|
||||
|
||||
it('should search with the destination shipped tomorrow', async() => {
|
||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||
await page.pickDate(selectors.ticketFuture.tfShipped, tomorrow);
|
||||
await page.waitToClick(selectors.ticketFuture.submit);
|
||||
await page.waitForNumberOfElements(selectors.ticketFuture.table, 0);
|
||||
});
|
||||
|
||||
it('should search with the origin IPT', async() => {
|
||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||
|
||||
await page.clearInput(selectors.ticketFuture.shipped);
|
||||
await page.clearInput(selectors.ticketFuture.tfShipped);
|
||||
await page.clearInput(selectors.ticketFuture.ipt);
|
||||
await page.clearInput(selectors.ticketFuture.tfIpt);
|
||||
await page.clearInput(selectors.ticketFuture.state);
|
||||
|
@ -109,8 +61,6 @@ describe('Ticket Future path', () => {
|
|||
it('should search with the destination IPT', async() => {
|
||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||
|
||||
await page.clearInput(selectors.ticketFuture.shipped);
|
||||
await page.clearInput(selectors.ticketFuture.tfShipped);
|
||||
await page.clearInput(selectors.ticketFuture.ipt);
|
||||
await page.clearInput(selectors.ticketFuture.tfIpt);
|
||||
await page.clearInput(selectors.ticketFuture.state);
|
||||
|
@ -124,8 +74,6 @@ describe('Ticket Future path', () => {
|
|||
it('should search with the origin grouped state', async() => {
|
||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||
|
||||
await page.clearInput(selectors.ticketFuture.shipped);
|
||||
await page.clearInput(selectors.ticketFuture.tfShipped);
|
||||
await page.clearInput(selectors.ticketFuture.ipt);
|
||||
await page.clearInput(selectors.ticketFuture.tfIpt);
|
||||
await page.clearInput(selectors.ticketFuture.state);
|
||||
|
@ -139,8 +87,6 @@ describe('Ticket Future path', () => {
|
|||
it('should search with the destination grouped state', async() => {
|
||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||
|
||||
await page.clearInput(selectors.ticketFuture.shipped);
|
||||
await page.clearInput(selectors.ticketFuture.tfShipped);
|
||||
await page.clearInput(selectors.ticketFuture.ipt);
|
||||
await page.clearInput(selectors.ticketFuture.tfIpt);
|
||||
await page.clearInput(selectors.ticketFuture.state);
|
||||
|
@ -151,8 +97,6 @@ describe('Ticket Future path', () => {
|
|||
await page.waitForNumberOfElements(selectors.ticketFuture.table, 0);
|
||||
|
||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||
await page.clearInput(selectors.ticketFuture.shipped);
|
||||
await page.clearInput(selectors.ticketFuture.tfShipped);
|
||||
await page.clearInput(selectors.ticketFuture.ipt);
|
||||
await page.clearInput(selectors.ticketFuture.tfIpt);
|
||||
await page.clearInput(selectors.ticketFuture.state);
|
|
@ -20,3 +20,4 @@ routeFk: route
|
|||
companyFk: company
|
||||
agencyModeFk: agency
|
||||
ticketFk: ticket
|
||||
mergedTicket: merged ticket
|
||||
|
|
|
@ -20,3 +20,4 @@ routeFk: ruta
|
|||
companyFk: empresa
|
||||
agencyModeFk: agencia
|
||||
ticketFk: ticket
|
||||
mergedTicket: ticket fusionado
|
||||
|
|
|
@ -20,18 +20,6 @@ module.exports = Self => {
|
|||
description: 'The date to probe',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
arg: 'litersMax',
|
||||
type: 'number',
|
||||
description: 'Maximum volume of tickets to catapult',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
arg: 'linesMax',
|
||||
type: 'number',
|
||||
description: 'Maximum number of lines of tickets to catapult',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
arg: 'warehouseFk',
|
||||
type: 'number',
|
||||
|
@ -39,15 +27,15 @@ module.exports = Self => {
|
|||
required: true
|
||||
},
|
||||
{
|
||||
arg: 'shipped',
|
||||
type: 'date',
|
||||
description: 'Origin shipped',
|
||||
arg: 'liters',
|
||||
type: 'number',
|
||||
description: 'Maximum volume of tickets to catapult',
|
||||
required: false
|
||||
},
|
||||
{
|
||||
arg: 'tfShipped',
|
||||
type: 'date',
|
||||
description: 'Destination shipped',
|
||||
arg: 'lines',
|
||||
type: 'number',
|
||||
description: 'Maximum number of lines of tickets to catapult',
|
||||
required: false
|
||||
},
|
||||
{
|
||||
|
@ -108,7 +96,7 @@ module.exports = Self => {
|
|||
}
|
||||
});
|
||||
|
||||
Self.getTicketsFuture = async (ctx, options) => {
|
||||
Self.getTicketsFuture = async(ctx, options) => {
|
||||
const args = ctx.args;
|
||||
const conn = Self.dataSource.connector;
|
||||
const myOptions = {};
|
||||
|
@ -118,32 +106,32 @@ module.exports = Self => {
|
|||
|
||||
const where = buildFilter(ctx.args, (param, value) => {
|
||||
switch (param) {
|
||||
case 'id':
|
||||
return { 'f.id': value };
|
||||
case 'tfId':
|
||||
return { 'f.ticketFuture': value };
|
||||
case 'shipped':
|
||||
return { 'f.shipped': value };
|
||||
case 'tfShipped':
|
||||
return { 'f.tfShipped': value };
|
||||
case 'ipt':
|
||||
return { 'f.ipt': value };
|
||||
case 'tfIpt':
|
||||
return { 'f.tfIpt': value };
|
||||
case 'state':
|
||||
return { 'f.code': { like: `%${value}%` } };
|
||||
case 'tfState':
|
||||
return { 'f.tfCode': { like: `%${value}%` } };
|
||||
case 'id':
|
||||
return {'f.id': value};
|
||||
case 'lines':
|
||||
return {'f.lines': {lte: value}};
|
||||
case 'liters':
|
||||
return {'f.liters': {lte: value}};
|
||||
case 'tfId':
|
||||
return {'f.ticketFuture': value};
|
||||
case 'ipt':
|
||||
return {'f.ipt': value};
|
||||
case 'tfIpt':
|
||||
return {'f.tfIpt': value};
|
||||
case 'state':
|
||||
return {'f.stateCode': {like: `%${value}%`}};
|
||||
case 'tfState':
|
||||
return {'f.tfStateCode': {like: `%${value}%`}};
|
||||
}
|
||||
});
|
||||
|
||||
let filter = mergeFilters(ctx.args.filter, { where });
|
||||
let filter = mergeFilters(ctx.args.filter, {where});
|
||||
const stmts = [];
|
||||
let stmt;
|
||||
|
||||
stmt = new ParameterizedSQL(
|
||||
`CALL vn.ticket_canbePostponed(?,?,?,?,?)`,
|
||||
[args.originDated, args.futureDated, args.litersMax, args.linesMax, args.warehouseFk]);
|
||||
`CALL vn.ticket_canbePostponed(?,?,?)`,
|
||||
[args.originDated, args.futureDated, args.warehouseFk]);
|
||||
|
||||
stmts.push(stmt);
|
||||
|
||||
|
@ -153,7 +141,7 @@ module.exports = Self => {
|
|||
CREATE TEMPORARY TABLE tmp.sale_getProblems
|
||||
(INDEX (ticketFk))
|
||||
ENGINE = MEMORY
|
||||
SELECT f.id ticketFk, f.clientFk, f.warehouseFk, f.shipped
|
||||
SELECT f.id ticketFk, f.clientFk, f.warehouseFk, f.shipped, f.lines, f.liters
|
||||
FROM tmp.filter f
|
||||
LEFT JOIN alertLevel al ON al.id = f.alertLevel
|
||||
WHERE (al.code = 'FREE' OR f.alertLevel IS NULL)`);
|
||||
|
@ -174,35 +162,34 @@ module.exports = Self => {
|
|||
let range;
|
||||
let hasWhere;
|
||||
switch (args.problems) {
|
||||
case true:
|
||||
condition = `or`;
|
||||
hasProblem = true;
|
||||
range = { neq: null };
|
||||
hasWhere = true;
|
||||
break;
|
||||
case true:
|
||||
condition = `or`;
|
||||
hasProblem = true;
|
||||
range = {neq: null};
|
||||
hasWhere = true;
|
||||
break;
|
||||
|
||||
case false:
|
||||
condition = `and`;
|
||||
hasProblem = null;
|
||||
range = null;
|
||||
hasWhere = true;
|
||||
break;
|
||||
case false:
|
||||
condition = `and`;
|
||||
hasProblem = null;
|
||||
range = null;
|
||||
hasWhere = true;
|
||||
break;
|
||||
}
|
||||
|
||||
const problems = {
|
||||
[condition]: [
|
||||
{ 'tp.isFreezed': hasProblem },
|
||||
{ 'tp.risk': hasProblem },
|
||||
{ 'tp.hasTicketRequest': hasProblem },
|
||||
{ 'tp.itemShortage': range },
|
||||
{ 'tp.hasComponentLack': hasProblem },
|
||||
{ 'tp.isTooLittle': hasProblem }
|
||||
{'tp.isFreezed': hasProblem},
|
||||
{'tp.risk': hasProblem},
|
||||
{'tp.hasTicketRequest': hasProblem},
|
||||
{'tp.itemShortage': range},
|
||||
{'tp.hasComponentLack': hasProblem},
|
||||
{'tp.isTooLittle': hasProblem}
|
||||
]
|
||||
};
|
||||
|
||||
if (hasWhere) {
|
||||
filter = mergeFilters(filter, { where: problems });
|
||||
}
|
||||
if (hasWhere)
|
||||
filter = mergeFilters(filter, {where: problems});
|
||||
|
||||
stmt.merge(conn.makeWhere(filter.where));
|
||||
stmt.merge(conn.makeOrderBy(filter.order));
|
||||
|
|
|
@ -5,11 +5,11 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
today.setHours(0, 0, 0, 0);
|
||||
const tomorrow = new Date(today.getDate() + 1);
|
||||
|
||||
it('should return the tickets passing the required data', async () => {
|
||||
it('should return the tickets passing the required data', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = { transaction: tx };
|
||||
const options = {transaction: tx};
|
||||
|
||||
const args = {
|
||||
originDated: today,
|
||||
|
@ -19,7 +19,7 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
warehouseFk: 1,
|
||||
};
|
||||
|
||||
const ctx = { req: { accessToken: { userId: 9 } }, args };
|
||||
const ctx = {req: {accessToken: {userId: 9}}, args};
|
||||
const result = await models.Ticket.getTicketsFuture(ctx, options);
|
||||
|
||||
expect(result.length).toEqual(4);
|
||||
|
@ -30,11 +30,11 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should return the tickets matching the problems on true', async () => {
|
||||
it('should return the tickets matching the problems on true', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = { transaction: tx };
|
||||
const options = {transaction: tx};
|
||||
|
||||
const args = {
|
||||
originDated: today,
|
||||
|
@ -45,7 +45,7 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
problems: true
|
||||
};
|
||||
|
||||
const ctx = { req: { accessToken: { userId: 9 } }, args };
|
||||
const ctx = {req: {accessToken: {userId: 9}}, args};
|
||||
const result = await models.Ticket.getTicketsFuture(ctx, options);
|
||||
|
||||
expect(result.length).toEqual(4);
|
||||
|
@ -57,11 +57,11 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should return the tickets matching the problems on false', async () => {
|
||||
it('should return the tickets matching the problems on false', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = { transaction: tx };
|
||||
const options = {transaction: tx};
|
||||
|
||||
const args = {
|
||||
originDated: today,
|
||||
|
@ -72,7 +72,7 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
problems: false
|
||||
};
|
||||
|
||||
const ctx = { req: { accessToken: { userId: 9 } }, args };
|
||||
const ctx = {req: {accessToken: {userId: 9}}, args};
|
||||
const result = await models.Ticket.getTicketsFuture(ctx, options);
|
||||
|
||||
expect(result.length).toEqual(0);
|
||||
|
@ -84,11 +84,11 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should return the tickets matching the problems on null', async () => {
|
||||
it('should return the tickets matching the problems on null', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = { transaction: tx };
|
||||
const options = {transaction: tx};
|
||||
|
||||
const args = {
|
||||
originDated: today,
|
||||
|
@ -99,7 +99,7 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
problems: null
|
||||
};
|
||||
|
||||
const ctx = { req: { accessToken: { userId: 9 } }, args };
|
||||
const ctx = {req: {accessToken: {userId: 9}}, args};
|
||||
const result = await models.Ticket.getTicketsFuture(ctx, options);
|
||||
|
||||
expect(result.length).toEqual(4);
|
||||
|
@ -111,11 +111,11 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should return the tickets matching the correct origin shipped', async () => {
|
||||
it('should return the tickets matching the OK State in origin date', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = { transaction: tx };
|
||||
const options = {transaction: tx};
|
||||
|
||||
const args = {
|
||||
originDated: today,
|
||||
|
@ -123,118 +123,10 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
litersMax: 9999,
|
||||
linesMax: 9999,
|
||||
warehouseFk: 1,
|
||||
shipped: today
|
||||
state: 'OK'
|
||||
};
|
||||
|
||||
const ctx = { req: { accessToken: { userId: 9 } }, args };
|
||||
const result = await models.Ticket.getTicketsFuture(ctx, options);
|
||||
|
||||
expect(result.length).toEqual(4);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should return the tickets matching the an incorrect origin shipped', async () => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = { transaction: tx };
|
||||
|
||||
const args = {
|
||||
originDated: today,
|
||||
futureDated: today,
|
||||
litersMax: 9999,
|
||||
linesMax: 9999,
|
||||
warehouseFk: 1,
|
||||
shipped: tomorrow
|
||||
};
|
||||
|
||||
const ctx = { req: { accessToken: { userId: 9 } }, args };
|
||||
const result = await models.Ticket.getTicketsFuture(ctx, options);
|
||||
|
||||
expect(result.length).toEqual(0);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should return the tickets matching the correct destination shipped', async () => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = { transaction: tx };
|
||||
|
||||
const args = {
|
||||
originDated: today,
|
||||
futureDated: today,
|
||||
litersMax: 9999,
|
||||
linesMax: 9999,
|
||||
warehouseFk: 1,
|
||||
tfShipped: today
|
||||
};
|
||||
|
||||
const ctx = { req: { accessToken: { userId: 9 } }, args };
|
||||
const result = await models.Ticket.getTicketsFuture(ctx, options);
|
||||
|
||||
expect(result.length).toEqual(4);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should return the tickets matching the an incorrect destination shipped', async () => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = { transaction: tx };
|
||||
|
||||
const args = {
|
||||
originDated: today,
|
||||
futureDated: today,
|
||||
litersMax: 9999,
|
||||
linesMax: 9999,
|
||||
warehouseFk: 1,
|
||||
tfShipped: tomorrow
|
||||
};
|
||||
|
||||
const ctx = { req: { accessToken: { userId: 9 } }, args };
|
||||
const result = await models.Ticket.getTicketsFuture(ctx, options);
|
||||
|
||||
expect(result.length).toEqual(0);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should return the tickets matching the OK State in origin date', async () => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = { transaction: tx };
|
||||
|
||||
const args = {
|
||||
originDated: today,
|
||||
futureDated: today,
|
||||
litersMax: 9999,
|
||||
linesMax: 9999,
|
||||
warehouseFk: 1,
|
||||
state: "OK"
|
||||
};
|
||||
|
||||
const ctx = { req: { accessToken: { userId: 9 } }, args };
|
||||
const ctx = {req: {accessToken: {userId: 9}}, args};
|
||||
const result = await models.Ticket.getTicketsFuture(ctx, options);
|
||||
|
||||
expect(result.length).toEqual(1);
|
||||
|
@ -246,11 +138,11 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should return the tickets matching the OK State in destination date', async () => {
|
||||
it('should return the tickets matching the OK State in destination date', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = { transaction: tx };
|
||||
const options = {transaction: tx};
|
||||
|
||||
const args = {
|
||||
originDated: today,
|
||||
|
@ -258,10 +150,10 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
litersMax: 9999,
|
||||
linesMax: 9999,
|
||||
warehouseFk: 1,
|
||||
tfState: "OK"
|
||||
tfState: 'OK'
|
||||
};
|
||||
|
||||
const ctx = { req: { accessToken: { userId: 9 } }, args };
|
||||
const ctx = {req: {accessToken: {userId: 9}}, args};
|
||||
const result = await models.Ticket.getTicketsFuture(ctx, options);
|
||||
|
||||
expect(result.length).toEqual(4);
|
||||
|
@ -273,11 +165,11 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should return the tickets matching the correct IPT in origin date', async () => {
|
||||
it('should return the tickets matching the correct IPT in origin date', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = { transaction: tx };
|
||||
const options = {transaction: tx};
|
||||
|
||||
const args = {
|
||||
originDated: today,
|
||||
|
@ -288,7 +180,7 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
ipt: null
|
||||
};
|
||||
|
||||
const ctx = { req: { accessToken: { userId: 9 } }, args };
|
||||
const ctx = {req: {accessToken: {userId: 9}}, args};
|
||||
const result = await models.Ticket.getTicketsFuture(ctx, options);
|
||||
|
||||
expect(result.length).toEqual(4);
|
||||
|
@ -300,11 +192,11 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should return the tickets matching the incorrect IPT in origin date', async () => {
|
||||
it('should return the tickets matching the incorrect IPT in origin date', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = { transaction: tx };
|
||||
const options = {transaction: tx};
|
||||
|
||||
const args = {
|
||||
originDated: today,
|
||||
|
@ -315,7 +207,7 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
ipt: 0
|
||||
};
|
||||
|
||||
const ctx = { req: { accessToken: { userId: 9 } }, args };
|
||||
const ctx = {req: {accessToken: {userId: 9}}, args};
|
||||
const result = await models.Ticket.getTicketsFuture(ctx, options);
|
||||
|
||||
expect(result.length).toEqual(0);
|
||||
|
@ -327,11 +219,11 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should return the tickets matching the correct IPT in destination date', async () => {
|
||||
it('should return the tickets matching the correct IPT in destination date', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = { transaction: tx };
|
||||
const options = {transaction: tx};
|
||||
|
||||
const args = {
|
||||
originDated: today,
|
||||
|
@ -342,7 +234,7 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
tfIpt: null
|
||||
};
|
||||
|
||||
const ctx = { req: { accessToken: { userId: 9 } }, args };
|
||||
const ctx = {req: {accessToken: {userId: 9}}, args};
|
||||
const result = await models.Ticket.getTicketsFuture(ctx, options);
|
||||
|
||||
expect(result.length).toEqual(4);
|
||||
|
@ -354,11 +246,11 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should return the tickets matching the incorrect IPT in destination date', async () => {
|
||||
it('should return the tickets matching the incorrect IPT in destination date', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = { transaction: tx };
|
||||
const options = {transaction: tx};
|
||||
|
||||
const args = {
|
||||
originDated: today,
|
||||
|
@ -369,7 +261,7 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
tfIpt: 0
|
||||
};
|
||||
|
||||
const ctx = { req: { accessToken: { userId: 9 } }, args };
|
||||
const ctx = {req: {accessToken: {userId: 9}}, args};
|
||||
const result = await models.Ticket.getTicketsFuture(ctx, options);
|
||||
|
||||
expect(result.length).toEqual(0);
|
||||
|
@ -381,11 +273,11 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should return the tickets matching the ID in origin date', async () => {
|
||||
it('should return the tickets matching the ID in origin date', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = { transaction: tx };
|
||||
const options = {transaction: tx};
|
||||
|
||||
const args = {
|
||||
originDated: today,
|
||||
|
@ -396,7 +288,7 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
id: 13
|
||||
};
|
||||
|
||||
const ctx = { req: { accessToken: { userId: 9 } }, args };
|
||||
const ctx = {req: {accessToken: {userId: 9}}, args};
|
||||
const result = await models.Ticket.getTicketsFuture(ctx, options);
|
||||
|
||||
expect(result.length).toEqual(1);
|
||||
|
@ -408,11 +300,11 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should return the tickets matching the ID in destination date', async () => {
|
||||
it('should return the tickets matching the ID in destination date', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = { transaction: tx };
|
||||
const options = {transaction: tx};
|
||||
|
||||
const args = {
|
||||
originDated: today,
|
||||
|
@ -423,7 +315,7 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
tfId: 12
|
||||
};
|
||||
|
||||
const ctx = { req: { accessToken: { userId: 9 } }, args };
|
||||
const ctx = {req: {accessToken: {userId: 9}}, args};
|
||||
const result = await models.Ticket.getTicketsFuture(ctx, options);
|
||||
|
||||
expect(result.length).toEqual(4);
|
||||
|
@ -434,5 +326,4 @@ describe('TicketFuture getTicketsFuture()', () => {
|
|||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -43,14 +43,27 @@ module.exports = Self => {
|
|||
const fullPath = `${origin}/#!/ticket/${ticket.id}/summary`;
|
||||
const fullPathFuture = `${origin}/#!/ticket/${ticket.ticketFuture}/summary`;
|
||||
const message = $t('Ticket merged', {
|
||||
originDated: dateUtil.toString(new Date(ticket.originETD)),
|
||||
futureDated: dateUtil.toString(new Date(ticket.destETD)),
|
||||
originDated: dateUtil.toString(new Date(ticket.shipped)),
|
||||
futureDated: dateUtil.toString(new Date(ticket.tfShipped)),
|
||||
id: ticket.id,
|
||||
tfId: ticket.ticketFuture,
|
||||
fullPath,
|
||||
fullPathFuture
|
||||
});
|
||||
if (!ticket.id || !ticket.ticketFuture) continue;
|
||||
|
||||
const ticketFutureLogRecord = {
|
||||
originFk: ticket.ticketFuture,
|
||||
userFk: ctx.req.accessToken.userId,
|
||||
action: 'update',
|
||||
changedModel: 'Ticket',
|
||||
changedModelId: ticket.ticketFuture,
|
||||
changedModelValue: ticket.ticketFuture,
|
||||
oldInstance: {},
|
||||
newInstance: {mergedTicket: ticket.id}
|
||||
};
|
||||
|
||||
await models.TicketLog.create(ticketFutureLogRecord, myOptions);
|
||||
await models.Sale.updateAll({ticketFk: ticket.id}, {ticketFk: ticket.ticketFuture}, myOptions);
|
||||
await models.Ticket.setDeleted(ctx, ticket.id, myOptions);
|
||||
await models.Chat.sendCheckingPresence(ctx, ticket.workerFk, message);
|
||||
|
|
|
@ -4,43 +4,26 @@
|
|||
<vn-date-picker
|
||||
vn-one
|
||||
label="Origin date"
|
||||
ng-model="filter.shipped"
|
||||
on-change="$ctrl.from = value">
|
||||
ng-model="filter.originDated"
|
||||
required="true">
|
||||
</vn-date-picker>
|
||||
<vn-date-picker
|
||||
vn-one
|
||||
label="Destination date"
|
||||
ng-model="filter.tfShipped">
|
||||
</vn-date-picker>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal class="vn-px-lg">
|
||||
<vn-date-picker
|
||||
vn-one
|
||||
label="Origin ETD"
|
||||
ng-model="filter.originDated"
|
||||
required="true"
|
||||
info="ETD">
|
||||
</vn-date-picker>
|
||||
<vn-date-picker
|
||||
vn-one
|
||||
label="Destination ETD"
|
||||
ng-model="filter.futureDated"
|
||||
required="true"
|
||||
info="ETD">
|
||||
required="true">
|
||||
</vn-date-picker>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal class="vn-px-lg">
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Max Lines"
|
||||
ng-model="filter.linesMax"
|
||||
required="true">
|
||||
ng-model="filter.lines">
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Max Liters"
|
||||
ng-model="filter.litersMax"
|
||||
required="true">
|
||||
ng-model="filter.liters">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal class="vn-px-lg">
|
||||
|
@ -48,22 +31,22 @@
|
|||
data="$ctrl.itemPackingTypes"
|
||||
label="Origin IPT"
|
||||
value-field="code"
|
||||
show-field="name"
|
||||
show-field="description"
|
||||
ng-model="filter.ipt"
|
||||
info="IPT">
|
||||
<tpl-item>
|
||||
{{name}}
|
||||
{{description}}
|
||||
</tpl-item>
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete vn-one
|
||||
data="$ctrl.itemPackingTypes"
|
||||
label="Destination IPT"
|
||||
value-field="code"
|
||||
show-field="name"
|
||||
show-field="description"
|
||||
ng-model="filter.tfIpt"
|
||||
info="IPT">
|
||||
<tpl-item>
|
||||
{{name}}
|
||||
{{description}}
|
||||
</tpl-item>
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
|
|
|
@ -28,9 +28,8 @@ class Controller extends SearchPanel {
|
|||
this.$http.get('ItemPackingTypes').then(res => {
|
||||
for (let ipt of res.data) {
|
||||
itemPackingTypes.push({
|
||||
id: ipt.id,
|
||||
description: this.$t(ipt.description),
|
||||
code: ipt.code,
|
||||
name: this.$t(ipt.code)
|
||||
});
|
||||
}
|
||||
this.itemPackingTypes = itemPackingTypes;
|
||||
|
|
|
@ -1,9 +1 @@
|
|||
Future tickets: Tickets a futuro
|
||||
FREE: Free
|
||||
DELIVERED: Delivered
|
||||
ON_PREPARATION: On preparation
|
||||
PACKED: Packed
|
||||
F: Fruits and vegetables
|
||||
V: Vertical
|
||||
H: Horizontal
|
||||
P: Feed
|
||||
|
|
|
@ -11,13 +11,4 @@ With problems: Con problemas
|
|||
Warehouse: Almacén
|
||||
Origin Grouped State: Estado agrupado origen
|
||||
Destination Grouped State: Estado agrupado destino
|
||||
FREE: Libre
|
||||
DELIVERED: Servido
|
||||
ON_PREPARATION: En preparacion
|
||||
PACKED: Encajado
|
||||
F: Frutas y verduras
|
||||
V: Vertical
|
||||
H: Horizontal
|
||||
P: Pienso
|
||||
ETD: Tiempo estimado de entrega
|
||||
IPT: Encajado
|
||||
|
|
|
@ -44,31 +44,31 @@
|
|||
<th field="id">
|
||||
<span translate>Origin ID</span>
|
||||
</th>
|
||||
<th field="originETD">
|
||||
<span translate>Origin ETD</span>
|
||||
<th field="shipped">
|
||||
<span translate>Origin Date</span>
|
||||
</th>
|
||||
<th field="state">
|
||||
<span translate>Origin State</span>
|
||||
</th>
|
||||
<th field="ipt">
|
||||
<th field="ipt" title="Item Packing Type">
|
||||
<span>IPT</span>
|
||||
</th>
|
||||
<th field="litersMax">
|
||||
<th field="liters">
|
||||
<span translate>Liters</span>
|
||||
</th>
|
||||
<th field="linesMax">
|
||||
<th field="lines">
|
||||
<span translate>Available Lines</span>
|
||||
</th>
|
||||
<th field="ticketFuture">
|
||||
<span translate>Destination ID</span>
|
||||
</th>
|
||||
<th field="destETD">
|
||||
<span translate>Destination ETD</span>
|
||||
<th field="tfShipped">
|
||||
<span translate>Destination Date</span>
|
||||
</th>
|
||||
<th field="tfState">
|
||||
<span translate>Destination State</span>
|
||||
</th>
|
||||
<th field="tfIpt">
|
||||
<th field="tfIpt" title="Item Packing Type">
|
||||
<span>IPT</span>
|
||||
</th>
|
||||
</tr>
|
||||
|
@ -125,8 +125,8 @@
|
|||
{{::ticket.id}}
|
||||
</span></td>
|
||||
<td shrink-date>
|
||||
<span class="chip {{$ctrl.compareDate(ticket.originETD)}}">
|
||||
{{::ticket.originETD | date: 'dd/MM/yyyy'}}
|
||||
<span class="chip {{$ctrl.compareDate(ticket.shipped)}}">
|
||||
{{::ticket.shipped | date: 'dd/MM/yyyy'}}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
|
@ -146,8 +146,8 @@
|
|||
</span>
|
||||
</td>
|
||||
<td shrink-date>
|
||||
<span class="chip {{$ctrl.compareDate(ticket.destETD)}}">
|
||||
{{::ticket.destETD | date: 'dd/MM/yyyy'}}
|
||||
<span class="chip {{$ctrl.compareDate(ticket.tfShipped)}}">
|
||||
{{::ticket.tfShipped | date: 'dd/MM/yyyy'}}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
|
|
|
@ -15,11 +15,11 @@ export default class Controller extends Section {
|
|||
searchable: false
|
||||
},
|
||||
{
|
||||
field: 'originETD',
|
||||
field: 'shipped',
|
||||
searchable: false
|
||||
},
|
||||
{
|
||||
field: 'destETD',
|
||||
field: 'tfShipped',
|
||||
searchable: false
|
||||
},
|
||||
{
|
||||
|
@ -35,7 +35,7 @@ export default class Controller extends Section {
|
|||
autocomplete: {
|
||||
url: 'ItemPackingTypes',
|
||||
showField: 'description',
|
||||
valueField: 'code'
|
||||
valueField: 'description'
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -43,7 +43,7 @@ export default class Controller extends Section {
|
|||
autocomplete: {
|
||||
url: 'ItemPackingTypes',
|
||||
showField: 'description',
|
||||
valueField: 'code'
|
||||
valueField: 'description'
|
||||
}
|
||||
},
|
||||
]
|
||||
|
@ -57,9 +57,7 @@ export default class Controller extends Section {
|
|||
this.filterParams = {
|
||||
originDated: today,
|
||||
futureDated: today,
|
||||
linesMax: '9999',
|
||||
litersMax: '9999',
|
||||
warehouseFk: 1
|
||||
warehouseFk: this.vnConfig.warehouseFk
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -113,7 +111,7 @@ export default class Controller extends Section {
|
|||
}
|
||||
|
||||
moveTicketsFuture() {
|
||||
let params = { tickets: this.checked };
|
||||
let params = {tickets: this.checked};
|
||||
return this.$http.post('Tickets/merge', params)
|
||||
.then(() => {
|
||||
this.$.model.refresh();
|
||||
|
@ -123,18 +121,18 @@ export default class Controller extends Section {
|
|||
|
||||
exprBuilder(param, value) {
|
||||
switch (param) {
|
||||
case 'id':
|
||||
return { 'id': value };
|
||||
case 'ticketFuture':
|
||||
return { 'ticketFuture': value };
|
||||
case 'litersMax':
|
||||
return { 'liters': value };
|
||||
case 'linesMax':
|
||||
return { 'lines': value };
|
||||
case 'ipt':
|
||||
return { 'ipt': value };
|
||||
case 'tfIpt':
|
||||
return { 'tfIpt': value };
|
||||
case 'id':
|
||||
return {'id': value};
|
||||
case 'ticketFuture':
|
||||
return {'ticketFuture': value};
|
||||
case 'liters':
|
||||
return {'liters': value};
|
||||
case 'lines':
|
||||
return {'lines': value};
|
||||
case 'ipt':
|
||||
return {'ipt': value};
|
||||
case 'tfIpt':
|
||||
return {'tfIpt': value};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,16 +13,16 @@ describe('Component vnTicketFuture', () => {
|
|||
$httpBackend = _$httpBackend_;
|
||||
$window = _$window_;
|
||||
const $element = angular.element('<vn-ticket-future></vn-ticket-future>');
|
||||
controller = $componentController('vnTicketFuture', { $element });
|
||||
controller = $componentController('vnTicketFuture', {$element});
|
||||
controller.$.model = crudModel;
|
||||
controller.$.model.data = [{
|
||||
id: 1,
|
||||
checked: true,
|
||||
state: "OK"
|
||||
state: 'OK'
|
||||
}, {
|
||||
id: 2,
|
||||
checked: true,
|
||||
state: "Libre"
|
||||
state: 'Libre'
|
||||
}];
|
||||
}));
|
||||
|
||||
|
@ -67,6 +67,7 @@ describe('Component vnTicketFuture', () => {
|
|||
it('should return success to the OK tickets', () => {
|
||||
const ok = controller.stateColor(controller.$.model.data[0].state);
|
||||
const notOk = controller.stateColor(controller.$.model.data[1].state);
|
||||
|
||||
expect(ok).toEqual('success');
|
||||
expect(notOk).not.toEqual('success');
|
||||
});
|
||||
|
@ -74,6 +75,7 @@ describe('Component vnTicketFuture', () => {
|
|||
it('should return success to the FREE tickets', () => {
|
||||
const notFree = controller.stateColor(controller.$.model.data[0].state);
|
||||
const free = controller.stateColor(controller.$.model.data[1].state);
|
||||
|
||||
expect(free).toEqual('notice');
|
||||
expect(notFree).not.toEqual('notice');
|
||||
});
|
||||
|
|
|
@ -1,6 +1,2 @@
|
|||
Move confirmation: Do you want to move {{checked}} tickets to the future?
|
||||
FREE: Free
|
||||
DELIVERED: Delivered
|
||||
ON_PREPARATION: On preparation
|
||||
PACKED: Packed
|
||||
Success: Tickets moved successfully!
|
||||
|
|
|
@ -3,20 +3,14 @@ Search tickets: Buscar tickets
|
|||
Search future tickets by date: Buscar tickets por fecha
|
||||
Problems: Problemas
|
||||
Origin ID: ID origen
|
||||
Closing: Cierre
|
||||
Origin State: Estado origen
|
||||
Destination State: Estado destino
|
||||
Liters: Litros
|
||||
Available Lines: Líneas disponibles
|
||||
Destination ID: ID destino
|
||||
Destination ETD: ETD Destino
|
||||
Origin ETD: ETD Origen
|
||||
Move tickets: Mover tickets
|
||||
Move confirmation: ¿Desea mover {{checked}} tickets hacia el futuro?
|
||||
Success: Tickets movidos correctamente
|
||||
ETD: Tiempo estimado de entrega
|
||||
IPT: Encajado
|
||||
FREE: Libre
|
||||
DELIVERED: Servido
|
||||
ON_PREPARATION: En preparacion
|
||||
PACKED: Encajado
|
||||
Origin Date: Fecha origen
|
||||
Destination Date: Fecha destino
|
||||
|
|
Loading…
Reference in New Issue
perque canvies el nom? l'anterior a mi em pareixia correcte, no son litros exactes, sino litros màxims
Ho he tingut que posar aixina perque com en el procediment se diu 'lines' i 'liters' al ordenar me donava error. En veritat no passa res perque en el buscador ja apareix que son litres i linies màximes.