added transactions to several endpoints

This commit is contained in:
Carlos Jimenez Ruiz 2021-05-14 19:21:04 +02:00
parent 61fb997717
commit 1e8ab4d348
12 changed files with 522 additions and 365 deletions

View File

@ -24,11 +24,16 @@ module.exports = Self => {
} }
}); });
Self.sendCheckingPresence = async(ctx, recipientId, message) => { Self.sendCheckingPresence = async(ctx, recipientId, message, options) => {
if (!recipientId) return false; if (!recipientId) return false;
let myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const models = Self.app.models; const models = Self.app.models;
const account = await models.Account.findById(recipientId); const account = await models.Account.findById(recipientId, null, myOptions);
const userId = ctx.req.accessToken.userId; const userId = ctx.req.accessToken.userId;
if (recipientId == userId) return false; if (recipientId == userId) return false;
@ -37,14 +42,14 @@ module.exports = Self => {
throw new Error(`Could not send message "${message}" to worker id ${recipientId} from user ${userId}`); throw new Error(`Could not send message "${message}" to worker id ${recipientId} from user ${userId}`);
const query = `SELECT worker_isWorking(?) isWorking`; const query = `SELECT worker_isWorking(?) isWorking`;
const [result] = await Self.rawSql(query, [recipientId]); const [result] = await Self.rawSql(query, [recipientId], myOptions);
if (!result.isWorking) { if (!result.isWorking) {
const workerDepartment = await models.WorkerDepartment.findById(recipientId, { const workerDepartment = await models.WorkerDepartment.findById(recipientId, {
include: { include: {
relation: 'department' relation: 'department'
} }
}); }, myOptions);
const department = workerDepartment && workerDepartment.department(); const department = workerDepartment && workerDepartment.department();
const channelName = department && department.chatName; const channelName = department && department.chatName;

View File

@ -26,6 +26,10 @@ module.exports = Self => {
Self.getTickets = async(filter, options) => { Self.getTickets = async(filter, options) => {
const conn = Self.dataSource.connector; const conn = Self.dataSource.connector;
let myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const stmt = new ParameterizedSQL( const stmt = new ParameterizedSQL(
`SELECT `SELECT
t.id, t.id,
@ -66,7 +70,9 @@ module.exports = Self => {
stmt.merge(conn.makeSuffix(filter)); stmt.merge(conn.makeSuffix(filter));
const tickets = await conn.executeStmt(stmt, options); const tickets = await conn.executeStmt(stmt, myOptions);
if (tickets.length === 1 && !tickets[0].id) return;
return tickets; return tickets;
}; };

View File

@ -113,7 +113,7 @@
<vn-confirm <vn-confirm
vn-id="confirm" vn-id="confirm"
question="Delete ticket from route?" question="Delete ticket from route?"
on-accept="$ctrl.removeTicketFromRoute()"> on-accept="$ctrl.removeTicketFromRoute($index)">
</vn-confirm> </vn-confirm>
<vn-crud-model <vn-crud-model
vn-id="possibleTicketsModel" vn-id="possibleTicketsModel"

View File

@ -66,7 +66,7 @@ class Controller extends Section {
let url = 'http://gps.buscalia.com/usuario/localizar.aspx?bmi=true&addr='; let url = 'http://gps.buscalia.com/usuario/localizar.aspx?bmi=true&addr=';
lines.forEach(line => { lines.forEach(line => {
addresses = addresses + '+to:' + line.address.postalCode + ' ' + line.address.city + ' ' + line.address.street; addresses = addresses + '+to:' + line.postalCode + ' ' + line.city + ' ' + line.street;
}); });
window.open(url + addresses, '_blank'); window.open(url + addresses, '_blank');
@ -78,10 +78,11 @@ class Controller extends Section {
this.$.confirm.show(); this.$.confirm.show();
} }
removeTicketFromRoute() { removeTicketFromRoute($index) {
let params = {routeFk: null}; let params = {routeFk: null};
let query = `Tickets/${this.selectedTicket}/`; let query = `Tickets/${this.selectedTicket}/`;
this.$http.patch(query, params).then(() => { this.$http.patch(query, params).then(() => {
this.$.model.remove($index);
this.vnApp.showSuccess(this.$t('Ticket removed from route')); this.vnApp.showSuccess(this.$t('Ticket removed from route'));
this.updateVolume(); this.updateVolume();
}); });

View File

@ -9,48 +9,57 @@ module.exports = Self => {
accepts: [ accepts: [
{ {
arg: 'ctx', arg: 'ctx',
type: 'Object', type: 'object',
http: {source: 'context'} http: {source: 'context'}
}, { },
{
arg: 'filter', arg: 'filter',
type: 'Object', type: 'object',
description: `Filter defining where, order, offset, and limit - must be a JSON-encoded string` description: `Filter defining where, order, offset, and limit - must be a JSON-encoded string`
}, { },
{
arg: 'search', arg: 'search',
type: 'String', type: 'string',
description: `If it's and integer searchs by id, otherwise it searchs by nickname` description: `If it's and integer searchs by id, otherwise it searchs by nickname`
}, { },
{
arg: 'ticketFk', arg: 'ticketFk',
type: 'Number', type: 'number',
description: `Searchs by ticketFk` description: `Searchs by ticketFk`
}, { },
{
arg: 'warehouseFk', arg: 'warehouseFk',
type: 'Number', type: 'number',
description: `Search by warehouse` description: `Search by warehouse`
}, { },
{
arg: 'attenderFk', arg: 'attenderFk',
type: 'Number', type: 'number',
description: `Search requests attended by a given worker id` description: `Search requests attended by a given worker id`
}, { },
{
arg: 'mine', arg: 'mine',
type: 'Boolean', type: 'boolean',
description: `Search requests attended by the current user` description: `Search requests attended by the current user`
}, { },
{
arg: 'from', arg: 'from',
type: 'Date', type: 'date',
description: `Date from` description: `Date from`
}, { },
{
arg: 'to', arg: 'to',
type: 'Date', type: 'date',
description: `Date to` description: `Date to`
}, { },
{
arg: 'state', arg: 'state',
type: 'String', type: 'string',
description: `Search request by request state` description: `Search request by request state`
} }
], ],
returns: { returns: {
type: ['Object'], type: ['object'],
root: true root: true
}, },
http: { http: {

View File

@ -5,65 +5,76 @@ module.exports = Self => {
Self.remoteMethodCtx('componentUpdate', { Self.remoteMethodCtx('componentUpdate', {
description: 'Save ticket sale components', description: 'Save ticket sale components',
accessType: 'WRITE', accessType: 'WRITE',
accepts: [{ accepts: [
arg: 'id', {
type: 'Number', arg: 'id',
required: true, type: 'number',
description: 'The ticket id', required: true,
http: {source: 'path'} description: 'The ticket id',
}, { http: {source: 'path'}
arg: 'clientFk', },
type: 'Number', {
description: 'The client id', arg: 'clientFk',
required: true type: 'number',
}, { description: 'The client id',
arg: 'agencyModeFk', required: true
type: 'Number', },
description: 'The agencyMode id', {
required: true arg: 'agencyModeFk',
}, { type: 'number',
arg: 'addressFk', description: 'The agencyMode id',
type: 'Number', required: true
description: 'The address id', },
required: true {
}, { arg: 'addressFk',
arg: 'zoneFk', type: 'number',
type: 'Number', description: 'The address id',
description: 'The zone id', required: true
required: true },
}, { {
arg: 'warehouseFk', arg: 'zoneFk',
type: 'Number', type: 'number',
description: 'The warehouse id', description: 'The zone id',
required: true required: true
}, { },
arg: 'companyFk', {
type: 'Number', arg: 'warehouseFk',
description: 'The company id', type: 'number',
required: true description: 'The warehouse id',
}, { required: true
arg: 'shipped', },
type: 'Date', {
description: 'The shipped date', arg: 'companyFk',
required: true type: 'number',
}, { description: 'The company id',
arg: 'landed', required: true
type: 'Date', },
description: 'The landing date', {
required: true arg: 'shipped',
}, { type: 'date',
arg: 'isDeleted', description: 'The shipped date',
type: 'Boolean', required: true
description: 'Ticket is deleted', },
required: true {
}, { arg: 'landed',
arg: 'option', type: 'date',
type: 'Number', description: 'The landing date',
description: 'Action id', required: true
required: true },
}], {
arg: 'isDeleted',
type: 'boolean',
description: 'Ticket is deleted',
required: true
},
{
arg: 'option',
type: 'number',
description: 'Action id',
required: true
}],
returns: { returns: {
type: ['Object'], type: ['object'],
root: true root: true
}, },
http: { http: {
@ -72,128 +83,156 @@ module.exports = Self => {
} }
}); });
Self.componentUpdate = async(ctx, id, clientFk, agencyModeFk, addressFk, zoneFk, warehouseFk, Self.componentUpdate = async(ctx, options) => {
companyFk, shipped, landed, isDeleted, option) => { const args = ctx.args;
const userId = ctx.req.accessToken.userId; let tx;
const models = Self.app.models; let myOptions = {};
const $t = ctx.req.__; // $translate
const isEditable = await models.Ticket.isEditable(ctx, id);
if (!isEditable) if (typeof options == 'object')
throw new UserError(`The sales of this ticket can't be modified`); Object.assign(myOptions, options);
const isProductionBoss = await models.Account.hasRole(userId, 'productionBoss'); if (!myOptions.transaction) {
if (!isProductionBoss) { tx = await Self.beginTransaction({});
const zoneShipped = await models.Agency.getShipped(landed, addressFk, agencyModeFk, warehouseFk); myOptions.transaction = tx;
if (!zoneShipped || zoneShipped.zoneFk != zoneFk)
throw new UserError(`You don't have privileges to change the zone`);
} }
const observationTypeDelivery = await models.ObservationType.findOne({
where: {code: 'delivery'}
});
const originalTicket = await models.Ticket.findOne({ try {
where: {id: id}, const userId = ctx.req.accessToken.userId;
fields: ['id', 'clientFk', 'agencyModeFk', 'addressFk', 'zoneFk', const models = Self.app.models;
'warehouseFk', 'companyFk', 'shipped', 'landed', 'isDeleted'], const $t = ctx.req.__; // $translate
include: [ const isEditable = await models.Ticket.isEditable(ctx, args.id, myOptions);
{
relation: 'client',
scope: {
fields: 'salesPersonFk'
}
}]
});
const updatedTicket = Object.assign({}, ctx.args);
delete updatedTicket.ctx;
delete updatedTicket.option;
// Force to unroute ticket if (!isEditable)
const hasToBeUnrouted = true; throw new UserError(`The sales of this ticket can't be modified`);
const query = 'CALL vn.ticket_componentMakeUpdate(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
const res = await Self.rawSql(query, [
id,
clientFk,
agencyModeFk,
addressFk,
zoneFk,
warehouseFk,
companyFk,
shipped,
landed,
isDeleted,
hasToBeUnrouted,
option
]);
if (originalTicket.addressFk != updatedTicket.addressFk) { const isProductionBoss = await models.Account.hasRole(userId, 'productionBoss', myOptions);
const ticketObservation = await models.TicketObservation.findOne({ if (!isProductionBoss) {
where: { const zoneShipped = await models.Agency.getShipped(args.landed, args.addressFk, args.agencyModeFk, args.warehouseFk, myOptions);
ticketFk: id,
observationTypeFk: observationTypeDelivery.id}
});
if (ticketObservation) if (!zoneShipped || zoneShipped.zoneFk != args.zoneFk)
await ticketObservation.destroy(); throw new UserError(`You don't have privileges to change the zone`);
}
const observationTypeDelivery = await models.ObservationType.findOne({
where: {code: 'delivery'}
}, myOptions);
const address = await models.Address.findOne({ const originalTicket = await models.Ticket.findOne({
where: {id: addressFk}, where: {id: args.id},
include: { fields: [
relation: 'observations', 'id',
scope: { 'clientFk',
where: {observationTypeFk: observationTypeDelivery.id}, 'agencyModeFk',
include: { 'addressFk',
relation: 'observationType' 'zoneFk',
'warehouseFk',
'companyFk',
'shipped',
'landed',
'isDeleted'
],
include: [
{
relation: 'client',
scope: {
fields: 'salesPersonFk'
}
}]
}, myOptions);
const updatedTicket = Object.assign({}, args);
delete updatedTicket.ctx;
delete updatedTicket.option;
// Force to unroute ticket
const hasToBeUnrouted = true;
const query = 'CALL vn.ticket_componentMakeUpdate(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
const res = await Self.rawSql(query, [
args.id,
args.clientFk,
args.agencyModeFk,
args.addressFk,
args.zoneFk,
args.warehouseFk,
args.companyFk,
args.shipped,
args.landed,
args.isDeleted,
hasToBeUnrouted,
args.option
], myOptions);
if (originalTicket.addressFk != updatedTicket.addressFk) {
const ticketObservation = await models.TicketObservation.findOne({
where: {
ticketFk: args.id,
observationTypeFk: observationTypeDelivery.id}
}, myOptions);
if (ticketObservation)
await ticketObservation.destroy(myOptions);
const address = await models.Address.findOne({
where: {id: args.addressFk},
include: {
relation: 'observations',
scope: {
where: {observationTypeFk: observationTypeDelivery.id},
include: {
relation: 'observationType'
}
} }
} }
}, myOptions);
const [observation] = address.observations();
if (observation) {
await models.TicketObservation.create({
ticketFk: args.id,
observationTypeFk: observation.observationTypeFk,
description: observation.description
}, myOptions);
} }
}); }
const [observation] = address.observations();
if (observation) { const changes = loggable.getChanges(originalTicket, updatedTicket);
await models.TicketObservation.create({ const oldProperties = await loggable.translateValues(Self, changes.old);
ticketFk: id, const newProperties = await loggable.translateValues(Self, changes.new);
observationTypeFk: observation.observationTypeFk,
description: observation.description await models.TicketLog.create({
originFk: args.id,
userFk: userId,
action: 'update',
changedModel: 'Ticket',
changedModelId: args.id,
oldInstance: oldProperties,
newInstance: newProperties
}, myOptions);
const salesPersonId = originalTicket.client().salesPersonFk;
if (salesPersonId) {
const origin = ctx.req.headers.origin;
let changesMade = '';
for (let change in newProperties) {
let value = newProperties[change];
let oldValue = oldProperties[change];
changesMade += `\r\n~${$t(change)}: ${oldValue}~ ➔ *${$t(change)}: ${value}*`;
}
const message = $t('Changed this data from the ticket', {
ticketId: args.id,
ticketUrl: `${origin}/#!/ticket/${args.id}/summary`,
changes: changesMade
}); });
} await models.Chat.sendCheckingPresence(ctx, salesPersonId, message, myOptions);
}
const changes = loggable.getChanges(originalTicket, updatedTicket);
const oldProperties = await loggable.translateValues(Self, changes.old);
const newProperties = await loggable.translateValues(Self, changes.new);
await models.TicketLog.create({
originFk: id,
userFk: userId,
action: 'update',
changedModel: 'Ticket',
changedModelId: id,
oldInstance: oldProperties,
newInstance: newProperties
});
const salesPersonId = originalTicket.client().salesPersonFk;
if (salesPersonId) {
const origin = ctx.req.headers.origin;
let changesMade = '';
for (let change in newProperties) {
let value = newProperties[change];
let oldValue = oldProperties[change];
changesMade += `\r\n~${$t(change)}: ${oldValue}~ ➔ *${$t(change)}: ${value}*`;
} }
const message = $t('Changed this data from the ticket', { if (tx) await tx.commit();
ticketId: id,
ticketUrl: `${origin}/#!/ticket/${id}/summary`,
changes: changesMade
});
await models.Chat.sendCheckingPresence(ctx, salesPersonId, message);
}
return res; return res;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
}; };
}; };

View File

@ -19,15 +19,19 @@ module.exports = Self => {
} }
}); });
Self.isEditable = async(ctx, id) => { Self.isEditable = async(ctx, id, options) => {
const userId = ctx.req.accessToken.userId; const userId = ctx.req.accessToken.userId;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
let state = await Self.app.models.TicketState.findOne({ let state = await Self.app.models.TicketState.findOne({
where: {ticketFk: id} where: {ticketFk: id}
}); }, myOptions);
const isSalesAssistant = await Self.app.models.Account.hasRole(userId, 'salesAssistant'); const isSalesAssistant = await Self.app.models.Account.hasRole(userId, 'salesAssistant', myOptions);
const isProductionBoss = await Self.app.models.Account.hasRole(userId, 'productionBoss'); const isProductionBoss = await Self.app.models.Account.hasRole(userId, 'productionBoss', myOptions);
const isValidRole = isSalesAssistant || isProductionBoss; const isValidRole = isSalesAssistant || isProductionBoss;
let alertLevel = state ? state.alertLevel : null; let alertLevel = state ? state.alertLevel : null;
@ -41,8 +45,8 @@ module.exports = Self => {
} }
} }
}] }]
}); }, myOptions);
const isLocked = await Self.app.models.Ticket.isLocked(id); const isLocked = await Self.app.models.Ticket.isLocked(id, myOptions);
const alertLevelGreaterThanZero = (alertLevel && alertLevel > 0); const alertLevelGreaterThanZero = (alertLevel && alertLevel > 0);
const isNormalClient = ticket && ticket.client().type().code == 'normal'; const isNormalClient = ticket && ticket.client().type().code == 'normal';

View File

@ -19,10 +19,15 @@ module.exports = Self => {
} }
}); });
Self.isLocked = async id => { Self.isLocked = async(id, options) => {
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const ticket = await Self.app.models.Ticket.findById(id, { const ticket = await Self.app.models.Ticket.findById(id, {
fields: ['isDeleted', 'refFk'] fields: ['isDeleted', 'refFk']
}); }, myOptions);
const isDeleted = ticket && ticket.isDeleted; const isDeleted = ticket && ticket.isDeleted;
const isInvoiced = ticket && ticket.refFk; const isInvoiced = ticket && ticket.refFk;

View File

@ -13,147 +13,125 @@ describe('ticket componentUpdate()', () => {
let secondvalueBeforeChange; let secondvalueBeforeChange;
let componentOfSaleSeven; let componentOfSaleSeven;
let componentOfSaleEight; let componentOfSaleEight;
let componentValue;
beforeAll(async() => {
const deliveryComponenet = await app.models.Component.findOne({where: {code: 'delivery'}});
deliveryComponentId = deliveryComponenet.id;
componentOfSaleSeven = `SELECT value FROM vn.saleComponent WHERE saleFk = 7 AND componentFk = ${deliveryComponentId}`;
componentOfSaleEight = `SELECT value FROM vn.saleComponent WHERE saleFk = 8 AND componentFk = ${deliveryComponentId}`;
[componentValue] = await app.models.SaleComponent.rawSql(componentOfSaleSeven);
firstvalueBeforeChange = componentValue.value;
[componentValue] = await app.models.SaleComponent.rawSql(componentOfSaleEight);
secondvalueBeforeChange = componentValue.value;
});
it('should change the agencyMode to modify the sale components value', async() => {
const tx = await app.models.SaleComponent.beginTransaction({});
beforeAll(async done => {
try { try {
let deliveryComponenet = await app.models.Component.findOne({where: {code: 'delivery'}}); const options = {transaction: tx};
deliveryComponentId = deliveryComponenet.id;
componentOfSaleSeven = `SELECT value FROM vn.saleComponent WHERE saleFk = 7 AND componentFk = ${deliveryComponentId}`;
componentOfSaleEight = `SELECT value FROM vn.saleComponent WHERE saleFk = 8 AND componentFk = ${deliveryComponentId}`;
[componentValue] = await app.models.SaleComponent.rawSql(componentOfSaleSeven); const args = {
firstvalueBeforeChange = componentValue.value; id: ticketID,
clientFk: 102,
agencyModeFk: 8,
addressFk: 122,
zoneFk: 5,
warehouseFk: 1,
companyFk: 442,
shipped: today,
landed: tomorrow,
isDeleted: false,
option: 1
};
[componentValue] = await app.models.SaleComponent.rawSql(componentOfSaleEight); let ctx = {
secondvalueBeforeChange = componentValue.value; args: args,
} catch (error) { req: {
console.error(error); accessToken: {userId: userID},
headers: {origin: 'http://localhost'},
__: value => {
return value;
}
}
};
await app.models.Ticket.componentUpdate(ctx, options);
[componentValue] = await app.models.SaleComponent.rawSql(componentOfSaleSeven, null, options);
let firstvalueAfterChange = componentValue.value;
[componentValue] = await app.models.SaleComponent.rawSql(componentOfSaleEight, null, options);
let secondvalueAfterChange = componentValue.value;
expect(firstvalueBeforeChange).not.toEqual(firstvalueAfterChange);
expect(secondvalueBeforeChange).not.toEqual(secondvalueAfterChange);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
} }
done();
}); });
it('should change the agencyMode to modify the sale components value and then undo the changes', async() => { it('should change the addressFk and check that delivery observations have been changed', async() => {
const clientID = 102; const tx = await app.models.SaleComponent.beginTransaction({});
const addressID = 122;
const agencyModeID = 8;
const warehouseID = 1;
const zoneID = 5;
const shipped = today;
const companyID = 442;
const isDeleted = false;
const landed = tomorrow;
const option = 1;
let ctx = { try {
args: {clientFk: clientID, const options = {transaction: tx};
agencyModeFk: agencyModeID},
req: { const args = {
accessToken: {userId: userID}, id: ticketID,
headers: {origin: 'http://localhost'}, clientFk: 102,
__: value => { agencyModeFk: 8,
return value; addressFk: 2,
zoneFk: 5,
warehouseFk: 1,
companyFk: 442,
shipped: today,
landed: tomorrow,
isDeleted: false,
option: 1
};
const ctx = {
args: args,
req: {
accessToken: {userId: userID},
headers: {origin: 'http://localhost'},
__: value => {
return value;
}
} }
} };
}; const observationTypeDelivery = await app.models.ObservationType.findOne({
where: {code: 'delivery'}
}, options);
const originalTicketObservation = await app.models.TicketObservation.findOne({
where: {
ticketFk: args.id,
observationTypeFk: observationTypeDelivery.id}
}, options);
await app.models.Ticket.componentUpdate(ctx, ticketID, clientID, agencyModeID, addressID, expect(originalTicketObservation).toBeDefined();
zoneID, warehouseID, companyID, shipped, landed, isDeleted, option);
[componentValue] = await app.models.SaleComponent.rawSql(componentOfSaleSeven); await app.models.Ticket.componentUpdate(ctx, options);
let firstvalueAfterChange = componentValue.value;
[componentValue] = await app.models.SaleComponent.rawSql(componentOfSaleEight); const removedTicketObservation = await app.models.TicketObservation.findOne({
let secondvalueAfterChange = componentValue.value; where: {
ticketFk: ticketID,
observationTypeFk: observationTypeDelivery.id}
}, options);
expect(firstvalueBeforeChange).not.toEqual(firstvalueAfterChange); expect(removedTicketObservation).toBeNull();
expect(secondvalueBeforeChange).not.toEqual(secondvalueAfterChange);
// restores await tx.rollback();
const restores = { } catch (e) {
clientID: 102, await tx.rollback();
addressID: 122, throw e;
agencyModeID: 7, }
warehouseID: 1,
zoneID: 3,
shipped: today,
companyID: 442,
isDeleted: false,
landed: tomorrow,
option: 1,
};
ctx.clientFk = restores.clientID;
ctx.agencyModeFk = restores.agencyModeID;
await app.models.Ticket.componentUpdate(ctx, ticketID, restores.clientID, restores.agencyModeID, restores.addressID,
restores.zoneID, restores.warehouseID, restores.companyID, restores.shipped, restores.landed, restores.isDeleted, restores.option);
[componentValue] = await app.models.SaleComponent.rawSql(componentOfSaleSeven);
firstvalueAfterChange = componentValue.value;
[componentValue] = await app.models.SaleComponent.rawSql(componentOfSaleEight);
secondvalueAfterChange = componentValue.value;
expect(firstvalueBeforeChange).toEqual(firstvalueAfterChange);
expect(secondvalueBeforeChange).toEqual(secondvalueAfterChange);
});
it('should change the addressFk and check that delivery observations have been changed and then undo the changes', async() => {
const clientID = 102;
const addressID = 122;
const newAddressID = 2;
const agencyModeID = 8;
const warehouseID = 1;
const zoneID = 5;
const shipped = today;
const companyID = 442;
const isDeleted = false;
const landed = tomorrow;
const option = 1;
const ctx = {
args: {clientFk: clientID,
agencyModeFk: agencyModeID},
req: {
accessToken: {userId: userID},
headers: {origin: 'http://localhost'},
__: value => {
return value;
}
}
};
const observationTypeDelivery = await app.models.ObservationType.findOne({
where: {code: 'delivery'}
});
const originalTicketObservation = await app.models.TicketObservation.findOne({
where: {
ticketFk: ticketID,
observationTypeFk: observationTypeDelivery.id}
});
expect(originalTicketObservation).toBeDefined();
await app.models.Ticket.componentUpdate(ctx, ticketID, clientID, agencyModeID, newAddressID,
zoneID, warehouseID, companyID, shipped, landed, isDeleted, option);
const removedTicketObservation = await app.models.TicketObservation.findOne({
where: {
ticketFk: ticketID,
observationTypeFk: observationTypeDelivery.id}
});
expect(removedTicketObservation).toBeNull();
// restores
await app.models.Ticket.componentUpdate(ctx, ticketID, clientID, agencyModeID, addressID,
zoneID, warehouseID, companyID, shipped, landed, isDeleted, option);
const restoredTicketObservation = await app.models.TicketObservation.findOne({
where: {
ticketFk: ticketID,
observationTypeFk: observationTypeDelivery.id}
});
expect(restoredTicketObservation.description).toEqual(originalTicketObservation.description);
}); });
}); });

View File

@ -2,52 +2,135 @@ const app = require('vn-loopback/server/server');
describe('ticket isEditable()', () => { describe('ticket isEditable()', () => {
it('should return false if the given ticket does not exist', async() => { it('should return false if the given ticket does not exist', async() => {
let ctx = {req: {accessToken: {userId: 9}}}; const tx = await app.models.Ticket.beginTransaction({});
let result = await app.models.Ticket.isEditable(ctx, 99999); let result;
try {
const options = {transaction: tx};
const ctx = {
req: {accessToken: {userId: 9}}
};
result = await app.models.Ticket.isEditable(ctx, 9999, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
expect(result).toEqual(false); expect(result).toEqual(false);
}); });
it(`should return false if the given ticket isn't invoiced but isDeleted`, async() => { it(`should return false if the given ticket isn't invoiced but isDeleted`, async() => {
let ctx = {req: {accessToken: {userId: 9}}}; const tx = await app.models.Ticket.beginTransaction({});
let deletedTicket = await app.models.Ticket.findOne({ let result;
where: {
invoiceOut: null,
isDeleted: true
},
fields: ['id']
});
let result = await app.models.Ticket.isEditable(ctx, deletedTicket.id); try {
const options = {transaction: tx};
const deletedTicket = await app.models.Ticket.findOne({
where: {
invoiceOut: null,
isDeleted: true
},
fields: ['id']
});
const ctx = {
req: {accessToken: {userId: 9}}
};
result = await app.models.Ticket.isEditable(ctx, deletedTicket.id, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
expect(result).toEqual(false); expect(result).toEqual(false);
}); });
it('should return true if the given ticket is editable', async() => { it('should return true if the given ticket is editable', async() => {
let ctx = {req: {accessToken: {userId: 9}}}; const tx = await app.models.Ticket.beginTransaction({});
let result;
let result = await app.models.Ticket.isEditable(ctx, 16); try {
const options = {transaction: tx};
const ctx = {
req: {accessToken: {userId: 9}}
};
result = await app.models.Ticket.isEditable(ctx, 16, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
expect(result).toEqual(true); expect(result).toEqual(true);
}); });
it('should not be able to edit a deleted or invoiced ticket even for salesAssistant', async() => { it('should not be able to edit a deleted or invoiced ticket even for salesAssistant', async() => {
let ctx = {req: {accessToken: {userId: 21}}}; const tx = await app.models.Ticket.beginTransaction({});
let result = await app.models.Ticket.isEditable(ctx, 19); let result;
try {
const options = {transaction: tx};
const ctx = {
req: {accessToken: {userId: 21}}
};
result = await app.models.Ticket.isEditable(ctx, 19, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
expect(result).toEqual(false); expect(result).toEqual(false);
}); });
it('should not be able to edit a deleted or invoiced ticket even for productionBoss', async() => { it('should not be able to edit a deleted or invoiced ticket even for productionBoss', async() => {
let ctx = {req: {accessToken: {userId: 50}}}; const tx = await app.models.Ticket.beginTransaction({});
let result = await app.models.Ticket.isEditable(ctx, 19); let result;
try {
const options = {transaction: tx};
const ctx = {
req: {accessToken: {userId: 50}}
};
result = await app.models.Ticket.isEditable(ctx, 19, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
expect(result).toEqual(false); expect(result).toEqual(false);
}); });
it('should not be able to edit a deleted or invoiced ticket even for salesPerson', async() => { it('should not be able to edit a deleted or invoiced ticket even for salesPerson', async() => {
let ctx = {req: {accessToken: {userId: 18}}}; const tx = await app.models.Ticket.beginTransaction({});
let result = await app.models.Ticket.isEditable(ctx, 19); let result;
try {
const options = {transaction: tx};
const ctx = {
req: {accessToken: {userId: 18}}
};
result = await app.models.Ticket.isEditable(ctx, 19, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
expect(result).toEqual(false); expect(result).toEqual(false);
}); });

View File

@ -34,7 +34,12 @@ module.exports = Self => {
} }
}); });
Self.getShipped = async(landed, addressFk, agencyModeFk, warehouseFk) => { Self.getShipped = async(landed, addressFk, agencyModeFk, warehouseFk, options) => {
let myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
let stmts = []; let stmts = [];
stmts.push(new ParameterizedSQL( stmts.push(new ParameterizedSQL(
`CALL vn.zone_getShippedWarehouse(?, ?, ?)`, [ `CALL vn.zone_getShippedWarehouse(?, ?, ?)`, [
@ -44,14 +49,14 @@ module.exports = Self => {
] ]
)); ));
let rsIndex = stmts.push(new ParameterizedSQL( const rsIndex = stmts.push(new ParameterizedSQL(
`SELECT * FROM tmp.zoneGetShipped WHERE warehouseFk = ?`, [ `SELECT * FROM tmp.zoneGetShipped WHERE warehouseFk = ?`, [
warehouseFk warehouseFk
] ]
)) - 1; )) - 1;
let sql = ParameterizedSQL.join(stmts, ';'); const sql = ParameterizedSQL.join(stmts, ';');
let shipped = await Self.rawStmt(sql); const shipped = await Self.rawStmt(sql, myOptions);
return shipped[rsIndex][0]; return shipped[rsIndex][0];
}; };

View File

@ -2,27 +2,49 @@ const app = require('vn-loopback/server/server');
describe('agency getShipped()', () => { describe('agency getShipped()', () => {
it('should return a shipment date', async() => { it('should return a shipment date', async() => {
const landed = new Date(); const tx = await app.models.Agency.beginTransaction({});
landed.setDate(landed.getDate() + 1); let result;
const addressFk = 121;
const agencyModeFk = 7;
const warehouseFk = 1;
let result = await app.models.Agency.getShipped(landed, addressFk, agencyModeFk, warehouseFk); try {
const options = {transaction: tx};
const landed = new Date();
landed.setDate(landed.getDate() + 1);
const addressFk = 121;
const agencyModeFk = 7;
const warehouseFk = 1;
result = await app.models.Agency.getShipped(landed, addressFk, agencyModeFk, warehouseFk, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
expect(result).toBeDefined(); expect(result).toBeDefined();
}); });
it('should not return a shipment date', async() => { it('should not return a shipment date', async() => {
let newDate = new Date(); const tx = await app.models.Agency.beginTransaction({});
newDate.setMonth(newDate.getMonth() - 1); let result;
const landed = newDate; try {
const addressFk = 121; const options = {transaction: tx};
const agencyModeFk = 7; let newDate = new Date();
const warehouseFk = 1; newDate.setMonth(newDate.getMonth() - 1);
const landed = newDate;
const addressFk = 121;
const agencyModeFk = 7;
const warehouseFk = 1;
let result = await app.models.Agency.getShipped(landed, addressFk, agencyModeFk, warehouseFk); result = await app.models.Agency.getShipped(landed, addressFk, agencyModeFk, warehouseFk, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
expect(result).toBeUndefined(); expect(result).toBeUndefined();
}); });