8032-devToTest_2440 #3009
|
@ -9,7 +9,7 @@
|
||||||
},
|
},
|
||||||
"vn": {
|
"vn": {
|
||||||
"view": {
|
"view": {
|
||||||
"expeditionPallet_Print": "ced2b84a114fcb99fce05f0c34f4fc03f3fa387bef92621be1bc306608a84345"
|
"expeditionPallet_Print": "99f75145ac2e7b612a6d71e74b6e55f194a465780fd9875a15eb01e6596b447e"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ BEGIN
|
||||||
t.clientFk,
|
t.clientFk,
|
||||||
t.warehouseFk,
|
t.warehouseFk,
|
||||||
ts.alertLevel,
|
ts.alertLevel,
|
||||||
|
sub2.alertLevel futureAlertLevel,
|
||||||
t.shipped,
|
t.shipped,
|
||||||
t.totalWithVat,
|
t.totalWithVat,
|
||||||
sub2.shipped futureShipped,
|
sub2.shipped futureShipped,
|
||||||
|
@ -47,6 +48,7 @@ BEGIN
|
||||||
t.addressFk,
|
t.addressFk,
|
||||||
t.id,
|
t.id,
|
||||||
t.shipped,
|
t.shipped,
|
||||||
|
ts.alertLevel,
|
||||||
st.name state,
|
st.name state,
|
||||||
st.code,
|
st.code,
|
||||||
st.classColor,
|
st.classColor,
|
||||||
|
|
|
@ -85,7 +85,7 @@ BEGIN
|
||||||
|
|
||||||
IF(vHasDailyInvoice) AND vHasToInvoice THEN
|
IF(vHasDailyInvoice) AND vHasToInvoice THEN
|
||||||
SELECT invoiceSerial(vClientFk, vCompanyFk, 'quick') INTO vSerial;
|
SELECT invoiceSerial(vClientFk, vCompanyFk, 'quick') INTO vSerial;
|
||||||
IF NOT vSerial THEN
|
IF vSerial IS NULL THEN
|
||||||
CALL util.throw('Cannot booking without a serial');
|
CALL util.throw('Cannot booking without a serial');
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
-- Calculamos todos los volumenes de todos los tickets una sola vez
|
-- Calculamos todos los volumenes de todos los tickets una sola vez
|
||||||
|
/* Se ejecutará el dia de test - master manualmente para no hacer lenta la subida
|
||||||
CREATE OR REPLACE TEMPORARY TABLE tmp.tTicketVolume
|
CREATE OR REPLACE TEMPORARY TABLE tmp.tTicketVolume
|
||||||
(PRIMARY KEY (id))
|
(PRIMARY KEY (id))
|
||||||
ENGINE = MEMORY
|
ENGINE = MEMORY
|
||||||
|
@ -14,3 +15,4 @@ UPDATE vn.ticket t
|
||||||
SET t.volume = tv.volume;
|
SET t.volume = tv.volume;
|
||||||
|
|
||||||
DROP TEMPORARY TABLE tmp.tTicketVolume;
|
DROP TEMPORARY TABLE tmp.tTicketVolume;
|
||||||
|
*/
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
-- Place your SQL code here
|
||||||
|
INSERT INTO salix.ACL
|
||||||
|
SET model = 'Ticket',
|
||||||
|
property = 'setWeight',
|
||||||
|
accessType = 'WRITE',
|
||||||
|
permission = 'ALLOW',
|
||||||
|
principalType = 'ROLE',
|
||||||
|
principalId = 'salesPerson';
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
-- Place your SQL code here
|
||||||
|
DELETE FROM salix.ACL WHERE model = 'Province' LIMIT 1;
|
||||||
|
DELETE FROM salix.ACL WHERE model = 'Town' LIMIT 1;
|
||||||
|
|
||||||
|
UPDATE salix.ACL SET accessType = 'READ' WHERE model = 'BankEntity';
|
||||||
|
INSERT INTO salix.ACL
|
||||||
|
SET model = 'BankEntity',
|
||||||
|
property = '*',
|
||||||
|
accessType = 'WRITE',
|
||||||
|
permission = 'ALLOW',
|
||||||
|
principalType = 'ROLE',
|
||||||
|
principalId = 'financial';
|
|
@ -687,8 +687,8 @@ export default {
|
||||||
ticketFuture: {
|
ticketFuture: {
|
||||||
searchResult: 'vn-ticket-future tbody tr',
|
searchResult: 'vn-ticket-future tbody tr',
|
||||||
openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]',
|
openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]',
|
||||||
originDated: 'vn-date-picker[label="Origin date"]',
|
originScopeDays: 'vn-date-picker[label="Origin date"]',
|
||||||
futureDated: 'vn-date-picker[label="Destination date"]',
|
futureScopeDays: 'vn-date-picker[label="Destination date"]',
|
||||||
linesMax: 'vn-textfield[label="Max Lines"]',
|
linesMax: 'vn-textfield[label="Max Lines"]',
|
||||||
litersMax: 'vn-textfield[label="Max Liters"]',
|
litersMax: 'vn-textfield[label="Max Liters"]',
|
||||||
ipt: 'vn-autocomplete[label="Origin IPT"]',
|
ipt: 'vn-autocomplete[label="Origin IPT"]',
|
||||||
|
|
|
@ -35,6 +35,14 @@ describe('Client Edit billing data path', () => {
|
||||||
|
|
||||||
it(`should attempt to edit the billing data without an IBAN but fail`, async() => {
|
it(`should attempt to edit the billing data without an IBAN but fail`, async() => {
|
||||||
await page.autocompleteSearch($.payMethod, 'PayMethod with IBAN');
|
await page.autocompleteSearch($.payMethod, 'PayMethod with IBAN');
|
||||||
|
await page.waitToClick($.saveButton);
|
||||||
|
const message = await page.waitForSnackbar();
|
||||||
|
|
||||||
|
expect(message.text).toContain('That payment method requires an IBAN');
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should edit the billing data and save the form`, async() => {
|
||||||
|
await page.autocompleteSearch($.payMethod, 'PayMethod five');
|
||||||
await page.autocompleteSearch($.swiftBic, 'BBKKESMMMMM');
|
await page.autocompleteSearch($.swiftBic, 'BBKKESMMMMM');
|
||||||
await page.clearInput($.dueDay);
|
await page.clearInput($.dueDay);
|
||||||
await page.write($.dueDay, '60');
|
await page.write($.dueDay, '60');
|
||||||
|
@ -45,10 +53,13 @@ describe('Client Edit billing data path', () => {
|
||||||
await page.waitToClick($.saveButton);
|
await page.waitToClick($.saveButton);
|
||||||
const message = await page.waitForSnackbar();
|
const message = await page.waitForSnackbar();
|
||||||
|
|
||||||
expect(message.text).toContain('That payment method requires an IBAN');
|
expect(message.text).toContain('Notification sent!');
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should create a new BIC code`, async() => {
|
it(`should create a new BIC code`, async() => {
|
||||||
|
await page.loginAndModule('financial', 'client');
|
||||||
|
await page.accessToSearchResult('Bruce Banner');
|
||||||
|
await page.accessToSection('client.card.billingData');
|
||||||
await page.waitToClick($.newBankEntityButton);
|
await page.waitToClick($.newBankEntityButton);
|
||||||
await page.write($.newBankEntityName, 'Gotham City Bank');
|
await page.write($.newBankEntityName, 'Gotham City Bank');
|
||||||
await page.write($.newBankEntityBIC, 'GTHMCT');
|
await page.write($.newBankEntityBIC, 'GTHMCT');
|
||||||
|
@ -66,7 +77,7 @@ describe('Client Edit billing data path', () => {
|
||||||
it(`should confirm the IBAN pay method was sucessfully saved`, async() => {
|
it(`should confirm the IBAN pay method was sucessfully saved`, async() => {
|
||||||
const payMethod = await page.waitToGetProperty($.payMethod, 'value');
|
const payMethod = await page.waitToGetProperty($.payMethod, 'value');
|
||||||
|
|
||||||
expect(payMethod).toEqual('PayMethod with IBAN');
|
expect(payMethod).toEqual('PayMethod five');
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should clear the BIC code field, update the IBAN to see how he BIC code autocompletes`, async() => {
|
it(`should clear the BIC code field, update the IBAN to see how he BIC code autocompletes`, async() => {
|
||||||
|
@ -79,14 +90,6 @@ describe('Client Edit billing data path', () => {
|
||||||
expect(automaticCode).toEqual('CAIXESBB');
|
expect(automaticCode).toEqual('CAIXESBB');
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should save the form with all its new data`, async() => {
|
|
||||||
await page.waitForWatcherData($.watcher);
|
|
||||||
await page.waitToClick($.saveButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Notification sent!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should confirm the billing data have been edited', async() => {
|
it('should confirm the billing data have been edited', async() => {
|
||||||
const dueDate = await page.waitToGetProperty($.dueDay, 'value');
|
const dueDate = await page.waitToGetProperty($.dueDay, 'value');
|
||||||
const IBAN = await page.waitToGetProperty($.IBAN, 'value');
|
const IBAN = await page.waitToGetProperty($.IBAN, 'value');
|
||||||
|
@ -94,7 +97,9 @@ describe('Client Edit billing data path', () => {
|
||||||
const receivedCoreLCR = await page.checkboxState($.receivedCoreLCRCheckbox);
|
const receivedCoreLCR = await page.checkboxState($.receivedCoreLCRCheckbox);
|
||||||
const receivedCoreVNL = await page.checkboxState($.receivedCoreVNLCheckbox);
|
const receivedCoreVNL = await page.checkboxState($.receivedCoreVNLCheckbox);
|
||||||
const receivedB2BVNL = await page.checkboxState($.receivedB2BVNLCheckbox);
|
const receivedB2BVNL = await page.checkboxState($.receivedB2BVNLCheckbox);
|
||||||
|
const payMethod = await page.waitToGetProperty($.payMethod, 'value');
|
||||||
|
|
||||||
|
expect(payMethod).toEqual('PayMethod five');
|
||||||
expect(dueDate).toEqual('60');
|
expect(dueDate).toEqual('60');
|
||||||
expect(IBAN).toEqual('ES9121000418450200051332');
|
expect(IBAN).toEqual('ES9121000418450200051332');
|
||||||
expect(swiftBic).toEqual('CAIXESBB');
|
expect(swiftBic).toEqual('CAIXESBB');
|
||||||
|
|
|
@ -30,18 +30,18 @@ describe('Ticket Future path', () => {
|
||||||
expect(message.text).toContain('warehouseFk is a required argument');
|
expect(message.text).toContain('warehouseFk is a required argument');
|
||||||
|
|
||||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||||
await page.clearInput(selectors.ticketFuture.futureDated);
|
await page.clearInput(selectors.ticketFuture.futureScopeDays);
|
||||||
await page.waitToClick(selectors.ticketFuture.submit);
|
await page.waitToClick(selectors.ticketFuture.submit);
|
||||||
message = await page.waitForSnackbar();
|
message = await page.waitForSnackbar();
|
||||||
|
|
||||||
expect(message.text).toContain('futureDated is a required argument');
|
expect(message.text).toContain('futureScopeDays is a required argument');
|
||||||
|
|
||||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||||
await page.clearInput(selectors.ticketFuture.originDated);
|
await page.clearInput(selectors.ticketFuture.originScopeDays);
|
||||||
await page.waitToClick(selectors.ticketFuture.submit);
|
await page.waitToClick(selectors.ticketFuture.submit);
|
||||||
message = await page.waitForSnackbar();
|
message = await page.waitForSnackbar();
|
||||||
|
|
||||||
expect(message.text).toContain('originDated is a required argument');
|
expect(message.text).toContain('originScopeDays is a required argument');
|
||||||
|
|
||||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||||
await page.waitToClick(selectors.ticketFuture.submit);
|
await page.waitToClick(selectors.ticketFuture.submit);
|
||||||
|
@ -71,7 +71,7 @@ describe('Ticket Future path', () => {
|
||||||
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);
|
||||||
|
|
||||||
expect(httpRequest).toContain('state=FREE');
|
expect(httpRequest).toContain('state=0');
|
||||||
|
|
||||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ describe('Ticket Future path', () => {
|
||||||
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);
|
||||||
|
|
||||||
expect(httpRequest).toContain('futureState=FREE');
|
expect(httpRequest).toContain('futureState=0');
|
||||||
|
|
||||||
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
await page.waitToClick(selectors.ticketFuture.openAdvancedSearchButton);
|
||||||
await page.clearInput(selectors.ticketFuture.state);
|
await page.clearInput(selectors.ticketFuture.state);
|
||||||
|
|
|
@ -372,5 +372,7 @@
|
||||||
"The entry not have stickers": "La entrada no tiene etiquetas",
|
"The entry not have stickers": "La entrada no tiene etiquetas",
|
||||||
"Too many records": "Demasiados registros",
|
"Too many records": "Demasiados registros",
|
||||||
"Original invoice not found": "Factura original no encontrada",
|
"Original invoice not found": "Factura original no encontrada",
|
||||||
"The entry has no lines or does not exist": "La entrada no tiene lineas o no existe"
|
"The entry has no lines or does not exist": "La entrada no tiene lineas o no existe",
|
||||||
|
"Weight already set": "El peso ya está establecido",
|
||||||
|
"This ticket is not allocated to your department": "Este ticket no está asignado a tu departamento"
|
||||||
}
|
}
|
|
@ -320,7 +320,8 @@ module.exports = Self => {
|
||||||
|
|
||||||
// Credit management changes
|
// Credit management changes
|
||||||
|
|
||||||
if (changes?.rating >= 0 || changes?.recommendedCredit >= 0)
|
if ((changes?.rating != null && changes.rating >= 0)
|
||||||
|
|| (changes?.recommendedCredit != null && changes.recommendedCredit >= 0))
|
||||||
await Self.changeCreditManagement(ctx, finalState, changes);
|
await Self.changeCreditManagement(ctx, finalState, changes);
|
||||||
|
|
||||||
const oldInstance = {};
|
const oldInstance = {};
|
||||||
|
|
|
@ -9,13 +9,13 @@ module.exports = Self => {
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: [
|
accepts: [
|
||||||
{
|
{
|
||||||
arg: 'originDated',
|
arg: 'originScopeDays',
|
||||||
type: 'date',
|
type: 'date',
|
||||||
description: 'The date in question',
|
description: 'The date in question',
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
arg: 'futureDated',
|
arg: 'futureScopeDays',
|
||||||
type: 'date',
|
type: 'date',
|
||||||
description: 'The date to probe',
|
description: 'The date to probe',
|
||||||
required: true
|
required: true
|
||||||
|
@ -129,9 +129,9 @@ module.exports = Self => {
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
case 'state':
|
case 'state':
|
||||||
return {'f.stateCode': {like: `%${value}%`}};
|
return {'f.alertLevel': value};
|
||||||
case 'futureState':
|
case 'futureState':
|
||||||
return {'f.futureStateCode': {like: `%${value}%`}};
|
return {'f.futureAlertLevel': value};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ module.exports = Self => {
|
||||||
|
|
||||||
stmt = new ParameterizedSQL(
|
stmt = new ParameterizedSQL(
|
||||||
`CALL vn.ticket_canbePostponed(?,?,?)`,
|
`CALL vn.ticket_canbePostponed(?,?,?)`,
|
||||||
[args.originDated, args.futureDated, args.warehouseFk]);
|
[args.originScopeDays, args.futureScopeDays, args.warehouseFk]);
|
||||||
|
|
||||||
stmts.push(stmt);
|
stmts.push(stmt);
|
||||||
|
|
||||||
|
@ -170,7 +170,7 @@ module.exports = Self => {
|
||||||
LEFT JOIN tmp.ticket_problems tp ON tp.ticketFk = f.id
|
LEFT JOIN tmp.ticket_problems tp ON tp.ticketFk = f.id
|
||||||
`);
|
`);
|
||||||
|
|
||||||
if (args.problems != undefined && (!args.originDated && !args.futureDated))
|
if (args.problems != undefined && (!args.originScopeDays && !args.futureScopeDays))
|
||||||
throw new UserError('Choose a date range or days forward');
|
throw new UserError('Choose a date range or days forward');
|
||||||
|
|
||||||
let condition;
|
let condition;
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('setWeight', {
|
||||||
|
description: 'Sets weight of a ticket',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [{
|
||||||
|
arg: 'id',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
description: 'The ticket id',
|
||||||
|
http: {source: 'path'}
|
||||||
|
}, {
|
||||||
|
arg: 'weight',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
description: 'The weight value',
|
||||||
|
}],
|
||||||
|
returns: {
|
||||||
|
type: 'Array',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/:id/setWeight`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.setWeight = async(ctx, ticketId, weight, options) => {
|
||||||
|
const models = Self.app.models;
|
||||||
|
const userId = ctx.req.accessToken.userId;
|
||||||
|
const myOptions = {userId};
|
||||||
|
let tx;
|
||||||
|
|
||||||
|
if (typeof options == 'object') Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const ticket = await Self.findById(ticketId, null, myOptions);
|
||||||
|
if (ticket.weight) throw new UserError('Weight already set');
|
||||||
|
|
||||||
|
const canEdit = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'updateAttributes');
|
||||||
|
const client = await models.Client.findById(ticket.clientFk, {
|
||||||
|
include: {relation: 'salesPersonUser'}},
|
||||||
|
myOptions);
|
||||||
|
|
||||||
|
if (!canEdit) {
|
||||||
|
const salesPersonUser = client.salesPersonUser();
|
||||||
|
const workerDepartments = await models.WorkerDepartment.find({
|
||||||
|
include: {relation: 'department'},
|
||||||
|
where: {workerFk: {inq: [userId, salesPersonUser.id]}}
|
||||||
|
}, myOptions);
|
||||||
|
|
||||||
|
if (
|
||||||
|
workerDepartments.length == 2 &&
|
||||||
|
workerDepartments[0].departmentFk != workerDepartments[1].departmentFk
|
||||||
|
)
|
||||||
|
throw new UserError('This ticket is not allocated to your department');
|
||||||
|
}
|
||||||
|
|
||||||
|
await ticket.updateAttribute('weight', weight, myOptions);
|
||||||
|
|
||||||
|
const packedState = await models.State.findOne({where: {code: 'PACKED'}}, myOptions);
|
||||||
|
const ticketState = await models.TicketState.findOne({where: {ticketFk: ticketId}}, myOptions);
|
||||||
|
|
||||||
|
const [{taxArea}] = await Self.rawSql('SELECT clientTaxArea(?,?) taxArea',
|
||||||
|
[ticket.clientFk, ticket.warehouseFk], myOptions);
|
||||||
|
|
||||||
|
const isInvoiceable = ticketState.alertLevel >= packedState.alertLevel &&
|
||||||
|
taxArea == 'WORLD' && client.hasDailyInvoice;
|
||||||
|
|
||||||
|
if (tx) await tx.commit();
|
||||||
|
let invoiceIds = [];
|
||||||
|
if (isInvoiceable) invoiceIds = [...await Self.invoiceTicketsAndPdf(ctx, [ticketId])];
|
||||||
|
|
||||||
|
return invoiceIds;
|
||||||
|
} catch (e) {
|
||||||
|
if (tx) await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -12,8 +12,8 @@ describe('ticket getTicketsFuture()', () => {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
const args = {
|
const args = {
|
||||||
originDated: today,
|
originScopeDays: today,
|
||||||
futureDated: today,
|
futureScopeDays: today,
|
||||||
warehouseFk: 1,
|
warehouseFk: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -35,8 +35,8 @@ describe('ticket getTicketsFuture()', () => {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
const args = {
|
const args = {
|
||||||
originDated: today,
|
originScopeDays: today,
|
||||||
futureDated: today,
|
futureScopeDays: today,
|
||||||
warehouseFk: 1,
|
warehouseFk: 1,
|
||||||
problems: true
|
problems: true
|
||||||
};
|
};
|
||||||
|
@ -60,8 +60,8 @@ describe('ticket getTicketsFuture()', () => {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
const args = {
|
const args = {
|
||||||
originDated: today,
|
originScopeDays: today,
|
||||||
futureDated: today,
|
futureScopeDays: today,
|
||||||
warehouseFk: 1,
|
warehouseFk: 1,
|
||||||
problems: false
|
problems: false
|
||||||
};
|
};
|
||||||
|
@ -85,8 +85,8 @@ describe('ticket getTicketsFuture()', () => {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
const args = {
|
const args = {
|
||||||
originDated: today,
|
originScopeDays: today,
|
||||||
futureDated: today,
|
futureScopeDays: today,
|
||||||
warehouseFk: 1,
|
warehouseFk: 1,
|
||||||
problems: null
|
problems: null
|
||||||
};
|
};
|
||||||
|
@ -110,8 +110,8 @@ describe('ticket getTicketsFuture()', () => {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
const args = {
|
const args = {
|
||||||
originDated: today,
|
originScopeDays: today,
|
||||||
futureDated: today,
|
futureScopeDays: today,
|
||||||
warehouseFk: 1,
|
warehouseFk: 1,
|
||||||
state: 'OK'
|
state: 'OK'
|
||||||
};
|
};
|
||||||
|
@ -135,8 +135,8 @@ describe('ticket getTicketsFuture()', () => {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
const args = {
|
const args = {
|
||||||
originDated: today,
|
originScopeDays: today,
|
||||||
futureDated: today,
|
futureScopeDays: today,
|
||||||
warehouseFk: 1,
|
warehouseFk: 1,
|
||||||
futureState: 'OK'
|
futureState: 'OK'
|
||||||
};
|
};
|
||||||
|
@ -160,8 +160,8 @@ describe('ticket getTicketsFuture()', () => {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
const args = {
|
const args = {
|
||||||
originDated: today,
|
originScopeDays: today,
|
||||||
futureDated: today,
|
futureScopeDays: today,
|
||||||
warehouseFk: 1,
|
warehouseFk: 1,
|
||||||
ipt: null
|
ipt: null
|
||||||
};
|
};
|
||||||
|
@ -185,8 +185,8 @@ describe('ticket getTicketsFuture()', () => {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
const args = {
|
const args = {
|
||||||
originDated: today,
|
originScopeDays: today,
|
||||||
futureDated: today,
|
futureScopeDays: today,
|
||||||
warehouseFk: 1,
|
warehouseFk: 1,
|
||||||
ipt: 'H'
|
ipt: 'H'
|
||||||
};
|
};
|
||||||
|
@ -210,8 +210,8 @@ describe('ticket getTicketsFuture()', () => {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
const args = {
|
const args = {
|
||||||
originDated: today,
|
originScopeDays: today,
|
||||||
futureDated: today,
|
futureScopeDays: today,
|
||||||
warehouseFk: 1,
|
warehouseFk: 1,
|
||||||
futureIpt: null
|
futureIpt: null
|
||||||
};
|
};
|
||||||
|
@ -235,8 +235,8 @@ describe('ticket getTicketsFuture()', () => {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
const args = {
|
const args = {
|
||||||
originDated: today,
|
originScopeDays: today,
|
||||||
futureDated: today,
|
futureScopeDays: today,
|
||||||
warehouseFk: 1,
|
warehouseFk: 1,
|
||||||
futureIpt: 'H'
|
futureIpt: 'H'
|
||||||
};
|
};
|
||||||
|
@ -260,8 +260,8 @@ describe('ticket getTicketsFuture()', () => {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
const args = {
|
const args = {
|
||||||
originDated: today,
|
originScopeDays: today,
|
||||||
futureDated: today,
|
futureScopeDays: today,
|
||||||
warehouseFk: 1,
|
warehouseFk: 1,
|
||||||
id: 13
|
id: 13
|
||||||
};
|
};
|
||||||
|
@ -285,8 +285,8 @@ describe('ticket getTicketsFuture()', () => {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
const args = {
|
const args = {
|
||||||
originDated: today,
|
originScopeDays: today,
|
||||||
futureDated: today,
|
futureScopeDays: today,
|
||||||
warehouseFk: 1,
|
warehouseFk: 1,
|
||||||
futureId: 12
|
futureId: 12
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
const {models} = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('ticket setWeight()', () => {
|
||||||
|
const ctx = beforeAll.getCtx();
|
||||||
|
beforeAll.mockLoopBackContext();
|
||||||
|
let opts;
|
||||||
|
let tx;
|
||||||
|
const employeeId = 1;
|
||||||
|
const administrativeId = 5;
|
||||||
|
|
||||||
|
beforeEach(async() => {
|
||||||
|
opts = {transaction: tx};
|
||||||
|
tx = await models.Ticket.beginTransaction({});
|
||||||
|
opts.transaction = tx;
|
||||||
|
ctx.req.accessToken.userId = administrativeId;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async() => await tx.rollback());
|
||||||
|
|
||||||
|
it('should throw an error if the weight is already set', async() => {
|
||||||
|
try {
|
||||||
|
const ticketId = 1;
|
||||||
|
const weight = 10;
|
||||||
|
|
||||||
|
await models.Ticket.setWeight(ctx, ticketId, weight, opts);
|
||||||
|
} catch (e) {
|
||||||
|
expect(e.message).toEqual('Weight already set');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set the weight of a ticket', async() => {
|
||||||
|
const ticketId = 31;
|
||||||
|
const weight = 15;
|
||||||
|
|
||||||
|
await models.Ticket.setWeight(ctx, ticketId, weight, opts);
|
||||||
|
|
||||||
|
const ticket = await models.Ticket.findById(ticketId, null, opts);
|
||||||
|
|
||||||
|
expect(ticket.weight).toEqual(weight);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error if the user is not allocated to the same department', async() => {
|
||||||
|
ctx.req.accessToken.userId = employeeId;
|
||||||
|
try {
|
||||||
|
const ticketId = 10;
|
||||||
|
const weight = 20;
|
||||||
|
|
||||||
|
await models.Ticket.setWeight(ctx, ticketId, weight, opts);
|
||||||
|
} catch (e) {
|
||||||
|
expect(e.message).toEqual('This ticket is not allocated to your department');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call invoiceTicketsAndPdf if the ticket is invoiceable', async() => {
|
||||||
|
const ticketId = 10;
|
||||||
|
const weight = 25;
|
||||||
|
|
||||||
|
spyOn(models.Client, 'findById').and.returnValue({
|
||||||
|
hasDailyInvoice: true,
|
||||||
|
salesPersonUser: () => ({id: 1})
|
||||||
|
});
|
||||||
|
spyOn(models.TicketState, 'findOne').and.returnValue({alertLevel: 3});
|
||||||
|
spyOn(models.Ticket, 'rawSql').and.returnValue([{taxArea: 'WORLD'}]);
|
||||||
|
spyOn(models.Ticket, 'invoiceTicketsAndPdf').and.returnValue([10]);
|
||||||
|
|
||||||
|
const invoiceIds = await models.Ticket.setWeight(ctx, ticketId, weight, opts);
|
||||||
|
|
||||||
|
expect(invoiceIds.length).toBeGreaterThan(0);
|
||||||
|
});
|
||||||
|
});
|
|
@ -46,4 +46,5 @@ module.exports = function(Self) {
|
||||||
require('../methods/ticket/invoiceTicketsAndPdf')(Self);
|
require('../methods/ticket/invoiceTicketsAndPdf')(Self);
|
||||||
require('../methods/ticket/docuwareDownload')(Self);
|
require('../methods/ticket/docuwareDownload')(Self);
|
||||||
require('../methods/ticket/myLastModified')(Self);
|
require('../methods/ticket/myLastModified')(Self);
|
||||||
|
require('../methods/ticket/setWeight')(Self);
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,13 +9,13 @@
|
||||||
<vn-date-picker
|
<vn-date-picker
|
||||||
vn-one
|
vn-one
|
||||||
label="Origin date"
|
label="Origin date"
|
||||||
ng-model="filter.originDated"
|
ng-model="filter.originScopeDays"
|
||||||
required="true">
|
required="true">
|
||||||
</vn-date-picker>
|
</vn-date-picker>
|
||||||
<vn-date-picker
|
<vn-date-picker
|
||||||
vn-one
|
vn-one
|
||||||
label="Destination date"
|
label="Destination date"
|
||||||
ng-model="filter.futureDated"
|
ng-model="filter.futureScopeDays"
|
||||||
required="true">
|
required="true">
|
||||||
</vn-date-picker>
|
</vn-date-picker>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
|
@ -59,7 +59,7 @@
|
||||||
<vn-autocomplete vn-one
|
<vn-autocomplete vn-one
|
||||||
data="$ctrl.groupedStates"
|
data="$ctrl.groupedStates"
|
||||||
label="Origin Grouped State"
|
label="Origin Grouped State"
|
||||||
value-field="code"
|
value-field="id"
|
||||||
show-field="name"
|
show-field="name"
|
||||||
ng-model="filter.state">
|
ng-model="filter.state">
|
||||||
<tpl-item>
|
<tpl-item>
|
||||||
|
@ -69,7 +69,7 @@
|
||||||
<vn-autocomplete vn-one
|
<vn-autocomplete vn-one
|
||||||
data="$ctrl.groupedStates"
|
data="$ctrl.groupedStates"
|
||||||
label="Destination Grouped State"
|
label="Destination Grouped State"
|
||||||
value-field="code"
|
value-field="id"
|
||||||
show-field="name"
|
show-field="name"
|
||||||
ng-model="filter.futureState">
|
ng-model="filter.futureState">
|
||||||
<tpl-item>
|
<tpl-item>
|
||||||
|
|
|
@ -65,8 +65,8 @@ export default class Controller extends Section {
|
||||||
this.$http.get(`UserConfigs/getUserConfig`)
|
this.$http.get(`UserConfigs/getUserConfig`)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
this.filterParams = {
|
this.filterParams = {
|
||||||
originDated: today,
|
originScopeDays: today,
|
||||||
futureDated: today,
|
futureScopeDays: today,
|
||||||
warehouseFk: res.data.warehouseFk
|
warehouseFk: res.data.warehouseFk
|
||||||
};
|
};
|
||||||
this.$.model.applyFilter(null, this.filterParams);
|
this.$.model.applyFilter(null, this.filterParams);
|
||||||
|
|
|
@ -4,3 +4,4 @@ Client phone: Tel. cliente
|
||||||
Client mobile: Móv. cliente
|
Client mobile: Móv. cliente
|
||||||
Go to the ticket: Ir al ticket
|
Go to the ticket: Ir al ticket
|
||||||
Change state: Cambiar estado
|
Change state: Cambiar estado
|
||||||
|
Weight: Peso
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "salix-back",
|
"name": "salix-back",
|
||||||
"version": "24.36.0",
|
"version": "24.40.0",
|
||||||
"author": "Verdnatura Levante SL",
|
"author": "Verdnatura Levante SL",
|
||||||
"description": "Salix backend",
|
"description": "Salix backend",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
|
|
Loading…
Reference in New Issue