refactor(ticket): all ticket endpoints are using transactions now
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Carlos Jimenez Ruiz 2021-10-07 09:57:07 +02:00
parent 55a2ec83da
commit cb7d1b24e8
20 changed files with 653 additions and 315 deletions

View File

@ -7,13 +7,13 @@ module.exports = Self => {
accepts: [
{
arg: 'filter',
type: 'Object',
type: 'object',
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
http: {source: 'query'},
},
],
returns: {
type: ['Object'],
type: ['object'],
root: true,
},
http: {
@ -22,7 +22,12 @@ module.exports = Self => {
},
});
Self.filter = async filter => {
Self.filter = async(filter, options) => {
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const stmt = new ParameterizedSQL(
`SELECT
e.id,
@ -55,6 +60,6 @@ module.exports = Self => {
`);
stmt.merge(Self.buildSuffix(filter, 'e'));
return await Self.rawStmt(stmt);
return Self.rawStmt(stmt, myOptions);
};
};

View File

@ -0,0 +1,21 @@
const models = require('vn-loopback/server/server').models;
describe('expedition filter()', () => {
it('should return the expeditions matching the filter', async() => {
const tx = await models.Expedition.beginTransaction({});
try {
const options = {transaction: tx};
const filter = {where: {packagingFk: 1}};
const response = await models.Expedition.filter(filter, options);
expect(response.length).toEqual(10);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -7,13 +7,13 @@ module.exports = Self => {
accessType: 'READ',
accepts: [{
arg: 'filter',
type: 'Object',
type: 'object',
required: false,
description: 'Filter defining where and paginated data',
http: {source: 'query'}
}],
returns: {
type: ['Object'],
type: ['object'],
root: true
},
http: {
@ -22,9 +22,14 @@ module.exports = Self => {
}
});
Self.listPackaging = async filter => {
let conn = Self.dataSource.connector;
let stmt = new ParameterizedSQL(
Self.listPackaging = async(filter, options) => {
const conn = Self.dataSource.connector;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const stmt = new ParameterizedSQL(
`SELECT name, itemFk, packagingFk
FROM (SELECT i.name, i.id itemFk, p.id packagingFk
FROM item i
@ -33,6 +38,7 @@ module.exports = Self => {
);
stmt.merge(conn.makeSuffix(filter));
return conn.executeStmt(stmt);
return conn.executeStmt(stmt, myOptions);
};
};

View File

@ -1,12 +1,22 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('ticket listPackaging()', () => {
it('should return the packaging', async() => {
let filter = {where: {packagingFk: 1}};
let response = await app.models.Packaging.listPackaging(filter);
const tx = await models.Packaging.beginTransaction({});
try {
const options = {transaction: tx};
const filter = {where: {packagingFk: 1}};
const response = await models.Packaging.listPackaging(filter, options);
expect(response[0].name).toBeDefined();
expect(response[0].name).toEqual('Container ammo box 1m');
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -7,11 +7,11 @@ module.exports = Self => {
accessType: 'READ',
accepts: [{
arg: 'filter',
type: 'Object',
type: 'object',
description: 'Filter defining where and paginated data'
}],
returns: {
type: ['Object'],
type: ['object'],
root: true
},
http: {
@ -20,8 +20,13 @@ module.exports = Self => {
}
});
Self.listSaleTracking = async filter => {
let stmt = new ParameterizedSQL(`
Self.listSaleTracking = async(filter, options) => {
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const stmt = new ParameterizedSQL(`
SELECT
st.id,
s.ticketFk,
@ -41,9 +46,9 @@ module.exports = Self => {
stmt.merge(Self.makeSuffix(filter));
let trackings = await Self.rawStmt(stmt);
const trackings = await Self.rawStmt(stmt, myOptions);
let salesFilter = {
const salesFilter = {
include: [
{
relation: 'item'
@ -52,14 +57,14 @@ module.exports = Self => {
where: {ticketFk: filter.where.ticketFk}
};
let sales = await Self.app.models.Sale.find(salesFilter);
const sales = await Self.app.models.Sale.find(salesFilter, myOptions);
trackings.forEach(tracking => {
sales.forEach(sale => {
for (const tracking of trackings) {
for (const sale of sales) {
if (tracking.itemFk == sale.itemFk)
tracking.item = sale.item();
});
});
}
}
return trackings;
};

View File

@ -1,17 +1,39 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('ticket listSaleTracking()', () => {
it('should call the listSaleTracking method and return the response', async() => {
let filter = {where: {ticketFk: 1}};
let result = await app.models.SaleTracking.listSaleTracking(filter);
const tx = await models.SaleTracking.beginTransaction({});
try {
const options = {transaction: tx};
const filter = {where: {ticketFk: 1}};
const result = await models.SaleTracking.listSaleTracking(filter, options);
expect(result.length).toEqual(4);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it(`should call the listSaleTracking method and return zero if doesn't have lines`, async() => {
let filter = {where: {ticketFk: 2}};
let result = await app.models.SaleTracking.listSaleTracking(filter);
const tx = await models.SaleTracking.beginTransaction({});
try {
const options = {transaction: tx};
const filter = {where: {ticketFk: 2}};
const result = await models.SaleTracking.listSaleTracking(filter, options);
expect(result.length).toEqual(0);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,4 +1,3 @@
module.exports = Self => {
Self.remoteMethodCtx('editableStates', {
description: 'Gets the editable states according the user role ',
@ -8,7 +7,7 @@ module.exports = Self => {
type: 'object'
},
returns: {
type: ['Object'],
type: ['object'],
root: true
},
http: {
@ -17,14 +16,18 @@ module.exports = Self => {
}
});
Self.editableStates = async(ctx, filter) => {
let userId = ctx.req.accessToken.userId;
let models = Self.app.models;
let statesList = await models.State.find({where: filter.where});
Self.editableStates = async(ctx, filter, options) => {
const models = Self.app.models;
const userId = ctx.req.accessToken.userId;
const myOptions = {};
let isProduction = await models.Account.hasRole(userId, 'production');
let isSalesPerson = await models.Account.hasRole(userId, 'salesPerson');
let isAdministrative = await models.Account.hasRole(userId, 'administrative');
if (typeof options == 'object')
Object.assign(myOptions, options);
let statesList = await models.State.find({where: filter.where}, myOptions);
const isProduction = await models.Account.hasRole(userId, 'production', myOptions);
const isSalesPerson = await models.Account.hasRole(userId, 'salesPerson', myOptions);
const isAdministrative = await models.Account.hasRole(userId, 'administrative', myOptions);
if (isProduction || isAdministrative)
return statesList;

View File

@ -1,34 +1,73 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('ticket editableStates()', () => {
const filter = {where: {name: {like: '%%'}}};
it('should return the expected state for the given role', async() => {
const tx = await models.State.beginTransaction({});
try {
const options = {transaction: tx};
const productionRole = 49;
const ctx = {req: {accessToken: {userId: productionRole}}};
let result = await app.models.State.editableStates(ctx, filter);
let deliveredState = result.some(state => state.code == 'DELIVERED');
const editableStates = await models.State.editableStates(ctx, filter, options);
const deliveredState = editableStates.some(state => state.code == 'DELIVERED');
expect(deliveredState).toBeTruthy();
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it(`should return the expected states by a specific role`, async() => {
const tx = await models.State.beginTransaction({});
try {
const options = {transaction: tx};
const productionRole = 18;
const ctx = {req: {accessToken: {userId: productionRole}}};
let result = await app.models.State.editableStates(ctx, filter);
let deliveredState = result.some(state => state.code == 'DELIVERED');
let pickerDesignedState = result.some(state => state.code == 'PICKER_DESIGNED');
const editableStates = await models.State.editableStates(ctx, filter, options);
const deliveredState = editableStates.some(state => state.code == 'DELIVERED');
const pickerDesignedState = editableStates.some(state => state.code == 'PICKER_DESIGNED');
expect(deliveredState).toBeFalsy();
expect(pickerDesignedState).toBeTruthy();
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it(`should return again the expected state by a specific role`, async() => {
const tx = await models.State.beginTransaction({});
try {
const options = {transaction: tx};
const employeeRole = 1;
const ctx = {req: {accessToken: {userId: employeeRole}}};
let result = await app.models.State.editableStates(ctx, filter);
let pickerDesignedState = result.some(state => state.code == 'PICKER_DESIGNED');
const editableStates = await models.State.editableStates(ctx, filter, options);
const pickerDesignedState = editableStates.some(state => state.code == 'PICKER_DESIGNED');
expect(pickerDesignedState).toBeTruthy();
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -4,12 +4,12 @@ module.exports = Self => {
accessType: 'WRITE',
accepts: {
arg: 'id',
type: 'Number',
type: 'number',
description: 'The document id',
http: {source: 'path'}
},
returns: {
type: 'Object',
type: 'object',
root: true
},
http: {
@ -18,16 +18,36 @@ module.exports = Self => {
}
});
Self.removeFile = async(ctx, id) => {
Self.removeFile = async(ctx, id, options) => {
const models = Self.app.models;
const targetTicketDms = await models.TicketDms.findById(id);
const targetDms = await models.Dms.findById(targetTicketDms.dmsFk);
const trashDmsType = await models.DmsType.findOne({where: {code: 'trash'}});
const myOptions = {};
let tx;
await models.Dms.removeFile(ctx, targetTicketDms.dmsFk);
await targetTicketDms.destroy();
if (typeof options == 'object')
Object.assign(myOptions, options);
return targetDms.updateAttribute('dmsTypeFk', trashDmsType.id);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const targetTicketDms = await models.TicketDms.findById(id, null, myOptions);
const targetDms = await models.Dms.findById(targetTicketDms.dmsFk, null, myOptions);
const trashDmsType = await models.DmsType.findOne({where: {code: 'trash'}}, myOptions);
await models.Dms.removeFile(ctx, targetTicketDms.dmsFk, myOptions);
await targetTicketDms.destroy(myOptions);
await targetDms.updateAttribute('dmsTypeFk', trashDmsType.id, myOptions);
if (tx) await tx.commit();
return targetDms;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};

View File

@ -1,18 +1,25 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('TicketDms removeFile()', () => {
const ticketDmsId = 1;
it(`should return an error for a user without enough privileges`, async() => {
let clientId = 1101;
let ctx = {req: {accessToken: {userId: clientId}}};
const tx = await models.TicketDms.beginTransaction({});
let error;
await app.models.TicketDms.removeFile(ctx, ticketDmsId).catch(e => {
try {
const options = {transaction: tx};
const clientId = 1101;
const ctx = {req: {accessToken: {userId: clientId}}};
await models.TicketDms.removeFile(ctx, ticketDmsId, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}).finally(() => {
}
expect(error.message).toEqual(`You don't have enough privileges`);
});
expect(error).toBeDefined();
});
});

View File

@ -6,22 +6,22 @@ module.exports = Self => {
accessType: 'WRITE',
accepts: [{
arg: 'id',
type: 'Integer',
type: 'number',
required: true,
description: 'The request ID',
}, {
arg: 'itemFk',
type: 'Integer',
type: 'number',
required: true,
description: 'The requested item ID',
}, {
arg: 'quantity',
type: 'Integer',
type: 'number',
required: true,
description: 'The requested item quantity',
}],
returns: {
type: 'Object',
type: 'object',
root: true
},
http: {
@ -30,25 +30,37 @@ module.exports = Self => {
}
});
Self.confirm = async ctx => {
Self.confirm = async(ctx, options) => {
const userId = ctx.req.accessToken.userId;
const models = Self.app.models;
const tx = await Self.beginTransaction({});
const $t = ctx.req.__; // $translate
let sale;
const myOptions = {};
let tx;
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
let options = {transaction: tx};
let item = await models.Item.findById(ctx.args.itemFk, null, options);
const item = await models.Item.findById(ctx.args.itemFk, null, myOptions);
if (!item)
throw new UserError(`That item doesn't exists`);
let request = await models.TicketRequest.findById(ctx.args.id, {
const request = await models.TicketRequest.findById(ctx.args.id, {
include: {relation: 'ticket'}
}, options);
}, myOptions);
const itemStock = await models.Item.getVisibleAvailable(
ctx.args.itemFk,
request.ticket().warehouseFk,
request.ticket().shipped,
myOptions
);
const itemStock = await models.Item.getVisibleAvailable(ctx.args.itemFk, request.ticket().warehouseFk, request.ticket().shipped);
const isAvailable = itemStock.available > 0;
if (!isAvailable)
@ -57,23 +69,24 @@ module.exports = Self => {
if (request.saleFk)
throw new UserError(`This request already contains a sale`);
sale = await models.Sale.create({
const sale = await models.Sale.create({
ticketFk: request.ticketFk,
itemFk: ctx.args.itemFk,
quantity: ctx.args.quantity,
concept: item.name
}, options);
}, myOptions);
await request.updateAttributes({
saleFk: sale.id,
itemFk: sale.itemFk,
isOk: true
}, options);
}, myOptions);
query = `CALL vn.sale_calculateComponent(?, NULL)`;
await Self.rawSql(query, [sale.id], options);
const query = `CALL vn.sale_calculateComponent(?, NULL)`;
await Self.rawSql(query, [sale.id], myOptions);
const origin = ctx.req.headers.origin;
const requesterId = request.requesterFk;
const message = $t('Bought units from buy request', {
quantity: sale.quantity,
concept: sale.concept,
@ -82,10 +95,9 @@ module.exports = Self => {
url: `${origin}/#!/ticket/${sale.ticketFk}/summary`,
urlItem: `${origin}/#!/item/${sale.itemFk}/summary`
});
await models.Chat.sendCheckingPresence(ctx, requesterId, message);
await models.Chat.sendCheckingPresence(ctx, requesterId, message, myOptions);
// log
let logRecord = {
const logRecord = {
originFk: sale.ticketFk,
userFk: userId,
action: 'update',
@ -99,14 +111,14 @@ module.exports = Self => {
}
};
await Self.app.models.TicketLog.create(logRecord);
await Self.app.models.TicketLog.create(logRecord, myOptions);
await tx.commit();
if (tx) await tx.commit();
return sale;
} catch (error) {
await tx.rollback();
throw error;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};

View File

@ -4,7 +4,7 @@ module.exports = Self => {
accessType: 'WRITE',
accepts: [{
arg: 'id',
type: 'Integer',
type: 'number',
required: true,
description: 'The request ID',
}, {
@ -23,17 +23,37 @@ module.exports = Self => {
}
});
Self.deny = async ctx => {
let userId = ctx.req.accessToken.userId;
let worker = await Self.app.models.Worker.findOne({where: {userFk: userId}});
Self.deny = async(ctx, options) => {
const myOptions = {};
let tx;
let params = {
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const userId = ctx.req.accessToken.userId;
const worker = await Self.app.models.Worker.findOne({where: {userFk: userId}}, myOptions);
const params = {
isOk: false,
attenderFk: worker.id,
response: ctx.args.observation,
};
let request = await Self.app.models.TicketRequest.findById(ctx.args.id);
return request.updateAttributes(params);
const request = await Self.app.models.TicketRequest.findById(ctx.args.id, null, myOptions);
await request.updateAttributes(params, myOptions);
if (tx) await tx.commit();
return request;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};

View File

@ -68,9 +68,13 @@ module.exports = Self => {
}
});
Self.filter = async(ctx, filter) => {
let conn = Self.dataSource.connector;
let userId = ctx.req.accessToken.userId;
Self.filter = async(ctx, filter, options) => {
const conn = Self.dataSource.connector;
const userId = ctx.req.accessToken.userId;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
if (ctx.args.mine)
ctx.args.attenderFk = userId;
@ -111,9 +115,7 @@ module.exports = Self => {
filter = mergeFilters(filter, {where});
let stmt;
stmt = new ParameterizedSQL(
const stmt = new ParameterizedSQL(
`SELECT
tr.id,
tr.ticketFk,
@ -149,8 +151,6 @@ module.exports = Self => {
LEFT JOIN account.user ua ON ua.id = wka.userFk`);
stmt.merge(conn.makeSuffix(filter));
let result = await conn.executeStmt(stmt);
return result;
return conn.executeStmt(stmt, myOptions);
};
};

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('ticket-request confirm()', () => {
let ctx = {
@ -12,19 +12,31 @@ describe('ticket-request confirm()', () => {
};
it(`should throw an error if the item doesn't exist`, async() => {
ctx.args = {itemFk: 999};
const tx = await models.TicketRequest.beginTransaction({});
let error;
try {
await app.models.TicketRequest.confirm(ctx);
} catch (err) {
error = err;
const options = {transaction: tx};
ctx.args = {itemFk: 999};
await models.TicketRequest.confirm(ctx, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
expect(error.message).toEqual(`That item doesn't exists`);
});
it('should throw an error if the item is not available', async() => {
const tx = await models.TicketRequest.beginTransaction({});
let error;
try {
const options = {transaction: tx};
const requestId = 5;
const itemId = 4;
const quantity = 99999;
@ -35,18 +47,24 @@ describe('ticket-request confirm()', () => {
quantity: quantity
};
let error;
await models.TicketRequest.confirm(ctx, options);
try {
await app.models.TicketRequest.confirm(ctx);
} catch (err) {
error = err;
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
expect(error.message).toEqual(`This item is not available`);
});
it(`should throw if there's a sale id`, async() => {
const tx = await models.TicketRequest.beginTransaction({});
let error;
try {
const options = {transaction: tx};
const requestId = 4;
const itemId = 1;
const quantity = 10;
@ -57,11 +75,11 @@ describe('ticket-request confirm()', () => {
quantity: quantity
};
const request = await app.models.TicketRequest.findById(requestId);
const request = await models.TicketRequest.findById(requestId, null, options);
expect(request.saleFk).toBeNull();
await request.updateAttributes({saleFk: 2});
await request.updateAttributes({saleFk: 2}, options);
ctx.args = {
itemFk: itemId,
@ -69,17 +87,14 @@ describe('ticket-request confirm()', () => {
quantity: quantity
};
let error;
await models.TicketRequest.confirm(ctx, options);
try {
await app.models.TicketRequest.confirm(ctx);
} catch (err) {
error = err;
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
expect(error.message).toEqual(`This request already contains a sale`);
// restores
await request.updateAttributes({saleFk: null});
});
});

View File

@ -1,25 +1,22 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('ticket-request deny()', () => {
let request;
afterAll(async done => {
let params = {
isOk: null,
attenderFk: request.attenderFk,
response: null,
};
it('should return the dinied ticket request', async() => {
const tx = await models.TicketRequest.beginTransaction({});
await request.updateAttributes(params);
done();
});
try {
const options = {transaction: tx};
it('should return all ticket requests', async() => {
let ctx = {req: {accessToken: {userId: 9}}, args: {id: 4, observation: 'my observation'}};
const ctx = {req: {accessToken: {userId: 9}}, args: {id: 4, observation: 'my observation'}};
request = await app.models.TicketRequest.findById(ctx.args.id);
let result = await app.models.TicketRequest.deny(ctx);
const result = await models.TicketRequest.deny(ctx, options);
expect(result.id).toEqual(4);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,85 +1,184 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('ticket-request filter()', () => {
const userId = 9;
let ctx = {req: {accessToken: {userId: userId}}};
it('should now return all ticket requests', async() => {
const tx = await models.TicketRequest.beginTransaction({});
try {
const options = {transaction: tx};
ctx.args = {};
const result = await app.models.TicketRequest.filter(ctx);
const result = await models.TicketRequest.filter(ctx, options);
expect(result.length).toEqual(3);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the ticket request matching a generic search value which is the ticket ID', async() => {
const tx = await models.TicketRequest.beginTransaction({});
try {
const options = {transaction: tx};
ctx.args = {search: 11};
const result = await app.models.TicketRequest.filter(ctx);
const result = await models.TicketRequest.filter(ctx, options);
const requestId = result[0].id;
expect(requestId).toEqual(4);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the ticket request matching a generic search value which is the client address alias', async() => {
const tx = await models.TicketRequest.beginTransaction({});
try {
const options = {transaction: tx};
ctx.args = {search: 'NY roofs'};
const result = await app.models.TicketRequest.filter(ctx);
const result = await models.TicketRequest.filter(ctx, options);
const requestId = result[0].id;
expect(requestId).toEqual(4);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the ticket request matching the ticket ID', async() => {
const tx = await models.TicketRequest.beginTransaction({});
try {
const options = {transaction: tx};
ctx.args = {ticketFk: 11};
const result = await app.models.TicketRequest.filter(ctx);
const result = await models.TicketRequest.filter(ctx, options);
const requestId = result[0].id;
expect(requestId).toEqual(4);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the ticket request matching the atender ID', async() => {
const tx = await models.TicketRequest.beginTransaction({});
try {
const options = {transaction: tx};
ctx.args = {attenderFk: 35};
const result = await app.models.TicketRequest.filter(ctx);
const result = await models.TicketRequest.filter(ctx, options);
const requestId = result[0].id;
expect(requestId).toEqual(3);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the ticket request matching the isOk triple-state', async() => {
const tx = await models.TicketRequest.beginTransaction({});
try {
const options = {transaction: tx};
ctx.args = {isOk: null};
const result = await app.models.TicketRequest.filter(ctx);
const result = await models.TicketRequest.filter(ctx, options);
const requestId = result[0].id;
expect(requestId).toEqual(3);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the ticket request matching the client ID', async() => {
const tx = await models.TicketRequest.beginTransaction({});
try {
const options = {transaction: tx};
ctx.args = {clientFk: 1102};
const result = await app.models.TicketRequest.filter(ctx);
const result = await models.TicketRequest.filter(ctx, options);
const requestId = result[0].id;
expect(requestId).toEqual(4);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the ticket request matching the warehouse ID', async() => {
const tx = await models.TicketRequest.beginTransaction({});
try {
const options = {transaction: tx};
ctx.args = {warehouse: 1};
const result = await app.models.TicketRequest.filter(ctx, {order: 'id'});
const result = await models.TicketRequest.filter(ctx, {order: 'id'}, options);
const requestId = result[0].id;
expect(requestId).toEqual(3);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the ticket request matching the salesPerson ID', async() => {
const tx = await models.TicketRequest.beginTransaction({});
try {
const options = {transaction: tx};
ctx.args = {salesPersonFk: 18};
const result = await app.models.TicketRequest.filter(ctx);
const result = await models.TicketRequest.filter(ctx, options);
const requestId = result[0].id;
expect(requestId).toEqual(3);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -6,13 +6,13 @@ module.exports = Self => {
{
arg: 'ticketIds',
description: 'the array of ticket ids to set as delivered',
type: ['Number'],
type: ['number'],
required: true,
http: {source: 'body'}
}
],
returns: {
type: 'Object',
type: 'object',
root: true
},
http: {
@ -21,30 +21,47 @@ module.exports = Self => {
}
});
Self.setDelivered = async(ctx, ticketIds) => {
let userId = ctx.req.accessToken.userId;
let models = Self.app.models;
Self.setDelivered = async(ctx, ticketIds, options) => {
const userId = ctx.req.accessToken.userId;
const models = Self.app.models;
const myOptions = {};
let tx;
let state = await models.State.findOne({
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const state = await models.State.findOne({
where: {
code: 'delivered'
},
fields: ['id', 'name', 'alertLevel', 'code']
});
}, myOptions);
let worker = await models.Worker.findOne({where: {userFk: userId}});
const worker = await models.Worker.findOne({where: {userFk: userId}}, myOptions);
let promises = [];
for (let id of ticketIds) {
let promise = models.TicketTracking.changeState(ctx, {
const promises = [];
for (const id of ticketIds) {
const promise = models.TicketTracking.changeState(ctx, {
stateFk: state.id,
workerFk: worker.id,
ticketFk: id
});
}, myOptions);
promises.push(promise);
}
await Promise.all(promises);
if (tx) await tx.commit();
return state;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
};
};

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
const LoopBackContext = require('loopback-context');
describe('ticket setDelivered()', () => {
@ -7,50 +7,41 @@ describe('ticket setDelivered()', () => {
accessToken: {userId: userId},
};
let ticketOne;
let ticketTwo;
beforeAll(async done => {
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
active: activeCtx
});
try {
let originalTicketOne = await app.models.Ticket.findById(8);
let originalTicketTwo = await app.models.Ticket.findById(10);
originalTicketOne.id = null;
originalTicketTwo.id = null;
ticketOne = await app.models.Ticket.create(originalTicketOne);
ticketTwo = await app.models.Ticket.create(originalTicketTwo);
} catch (error) {
console.error(error);
}
done();
});
afterAll(async done => {
try {
await app.models.Ticket.destroyById(ticketOne.id);
await app.models.Ticket.destroyById(ticketTwo.id);
} catch (error) {
console.error(error);
}
done();
});
it('should return the state which has been applied to the given tickets', async() => {
let ctx = {req: {accessToken: {userId: 49}}};
let delivered = await app.models.State.findOne({where: {code: 'delivered'}, fields: ['id']});
const tx = await models.TicketTracking.beginTransaction({});
let params = [ticketOne.id, ticketTwo.id];
let state = await app.models.TicketTracking.setDelivered(ctx, params);
try {
const options = {transaction: tx};
const ctx = {req: {accessToken: {userId: 49}}};
const originalTicketOne = await models.Ticket.findById(8, null, options);
const originalTicketTwo = await models.Ticket.findById(10, null, options);
originalTicketOne.id = null;
originalTicketTwo.id = null;
const ticketOne = await models.Ticket.create(originalTicketOne, options);
const ticketTwo = await models.Ticket.create(originalTicketTwo, options);
const delivered = await models.State.findOne({where: {code: 'delivered'}, fields: ['id']}, options);
const params = [ticketOne.id, ticketTwo.id];
const state = await models.TicketTracking.setDelivered(ctx, params, options);
expect(state.id).toEqual(delivered.id);
// restores
await app.models.TicketTracking.destroyById(state.id);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -10,18 +10,18 @@ module.exports = Self => {
accepts: [
{
arg: 'filter',
type: 'Object',
type: 'object',
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
http: {source: 'query'}
}, {
arg: 'search',
type: 'String',
type: 'string',
description: `If it's and integer searchs by id, otherwise it searchs by client id`,
http: {source: 'query'}
}
],
returns: {
type: ['Object'],
type: ['object'],
root: true
},
http: {
@ -30,10 +30,14 @@ module.exports = Self => {
}
});
Self.filter = async(ctx, filter) => {
let conn = Self.dataSource.connector;
Self.filter = async(ctx, filter, options) => {
const conn = Self.dataSource.connector;
const myOptions = {};
let where = buildFilter(ctx.args, (param, value) => {
if (typeof options == 'object')
Object.assign(myOptions, options);
const where = buildFilter(ctx.args, (param, value) => {
switch (param) {
case 'search':
return {or: [
@ -46,10 +50,9 @@ module.exports = Self => {
filter = mergeFilters(ctx.args.filter, {where});
let stmts = [];
let stmt;
const stmts = [];
stmt = new ParameterizedSQL(
const stmt = new ParameterizedSQL(
`SELECT t.id AS ticketFk, c.id AS clientFk, c.name AS clientName, tw.weekDay,
wh.name AS warehouseName, u.id AS workerFk, u.name AS userName, u.nickName, tw.agencyModeFk
FROM ticketWeekly tw
@ -60,10 +63,10 @@ module.exports = Self => {
);
stmt.merge(conn.makeSuffix(filter));
let itemsIndex = stmts.push(stmt) - 1;
const itemsIndex = stmts.push(stmt) - 1;
let sql = ParameterizedSQL.join(stmts, ';');
let result = await conn.executeStmt(sql);
const sql = ParameterizedSQL.join(stmts, ';');
const result = await conn.executeStmt(sql, myOptions);
return itemsIndex === 0 ? result : result[itemsIndex];
};
};

View File

@ -1,43 +1,89 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('ticket-weekly filter()', () => {
const authUserId = 9;
it('should all return the tickets matching the filter', async() => {
const tx = await models.TicketWeekly.beginTransaction({});
try {
const options = {transaction: tx};
const filter = {order: 't.id ASC'};
const ctx = {req: {accessToken: {userId: authUserId}}, args: {filter: filter}};
const result = await app.models.TicketWeekly.filter(ctx);
const result = await models.TicketWeekly.filter(ctx, null, options);
const firstRow = result[0];
expect(firstRow.ticketFk).toEqual(1);
expect(result.length).toEqual(5);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the ticket with id one', async() => {
const tx = await models.TicketWeekly.beginTransaction({});
try {
const options = {transaction: tx};
const ctx = {req: {accessToken: {userId: authUserId}}, args: {search: 2}};
const filter = {};
const result = await app.models.TicketWeekly.filter(ctx, filter);
const result = await models.TicketWeekly.filter(ctx, null, options);
const firstRow = result[0];
expect(firstRow.ticketFk).toEqual(2);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the ticket matching the client name', async() => {
const tx = await models.TicketWeekly.beginTransaction({});
try {
const options = {transaction: tx};
const ctx = {req: {accessToken: {userId: authUserId}}, args: {search: 'bruce'}};
const filter = {};
const result = await app.models.TicketWeekly.filter(ctx, filter);
const result = await models.TicketWeekly.filter(ctx, null, options);
const firstRow = result[0];
expect(firstRow.clientName).toEqual('Bruce Wayne');
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the ticket matching the client id', async() => {
const tx = await models.TicketWeekly.beginTransaction({});
try {
const options = {transaction: tx};
const ctx = {req: {accessToken: {userId: authUserId}}, args: {search: 1101}};
const filter = {};
const result = await app.models.TicketWeekly.filter(ctx, filter);
const result = await models.TicketWeekly.filter(ctx, null, options);
const firstRow = result[0];
expect(firstRow.clientFk).toEqual(1101);
expect(firstRow.clientName).toEqual('Bruce Wayne');
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});