refactor(ticket): all ticket endpoints are using transactions now
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
This commit is contained in:
parent
55a2ec83da
commit
cb7d1b24e8
|
@ -7,13 +7,13 @@ module.exports = Self => {
|
||||||
accepts: [
|
accepts: [
|
||||||
{
|
{
|
||||||
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',
|
||||||
http: {source: 'query'},
|
http: {source: 'query'},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
returns: {
|
returns: {
|
||||||
type: ['Object'],
|
type: ['object'],
|
||||||
root: true,
|
root: true,
|
||||||
},
|
},
|
||||||
http: {
|
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(
|
const stmt = new ParameterizedSQL(
|
||||||
`SELECT
|
`SELECT
|
||||||
e.id,
|
e.id,
|
||||||
|
@ -55,6 +60,6 @@ module.exports = Self => {
|
||||||
`);
|
`);
|
||||||
stmt.merge(Self.buildSuffix(filter, 'e'));
|
stmt.merge(Self.buildSuffix(filter, 'e'));
|
||||||
|
|
||||||
return await Self.rawStmt(stmt);
|
return Self.rawStmt(stmt, myOptions);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -7,13 +7,13 @@ module.exports = Self => {
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: [{
|
accepts: [{
|
||||||
arg: 'filter',
|
arg: 'filter',
|
||||||
type: 'Object',
|
type: 'object',
|
||||||
required: false,
|
required: false,
|
||||||
description: 'Filter defining where and paginated data',
|
description: 'Filter defining where and paginated data',
|
||||||
http: {source: 'query'}
|
http: {source: 'query'}
|
||||||
}],
|
}],
|
||||||
returns: {
|
returns: {
|
||||||
type: ['Object'],
|
type: ['object'],
|
||||||
root: true
|
root: true
|
||||||
},
|
},
|
||||||
http: {
|
http: {
|
||||||
|
@ -22,9 +22,14 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.listPackaging = async filter => {
|
Self.listPackaging = async(filter, options) => {
|
||||||
let conn = Self.dataSource.connector;
|
const conn = Self.dataSource.connector;
|
||||||
let stmt = new ParameterizedSQL(
|
const myOptions = {};
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
const stmt = new ParameterizedSQL(
|
||||||
`SELECT name, itemFk, packagingFk
|
`SELECT name, itemFk, packagingFk
|
||||||
FROM (SELECT i.name, i.id itemFk, p.id packagingFk
|
FROM (SELECT i.name, i.id itemFk, p.id packagingFk
|
||||||
FROM item i
|
FROM item i
|
||||||
|
@ -33,6 +38,7 @@ module.exports = Self => {
|
||||||
);
|
);
|
||||||
|
|
||||||
stmt.merge(conn.makeSuffix(filter));
|
stmt.merge(conn.makeSuffix(filter));
|
||||||
return conn.executeStmt(stmt);
|
|
||||||
|
return conn.executeStmt(stmt, myOptions);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,12 +1,22 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
|
||||||
describe('ticket listPackaging()', () => {
|
describe('ticket listPackaging()', () => {
|
||||||
it('should return the packaging', async() => {
|
it('should return the packaging', async() => {
|
||||||
let filter = {where: {packagingFk: 1}};
|
const tx = await models.Packaging.beginTransaction({});
|
||||||
let response = await app.models.Packaging.listPackaging(filter);
|
|
||||||
|
|
||||||
expect(response[0].name).toBeDefined();
|
try {
|
||||||
expect(response[0].name).toEqual('Container ammo box 1m');
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
const filter = {where: {packagingFk: 1}};
|
||||||
|
const response = await models.Packaging.listPackaging(filter, options);
|
||||||
|
|
||||||
|
expect(response[0].name).toEqual('Container ammo box 1m');
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -7,11 +7,11 @@ module.exports = Self => {
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: [{
|
accepts: [{
|
||||||
arg: 'filter',
|
arg: 'filter',
|
||||||
type: 'Object',
|
type: 'object',
|
||||||
description: 'Filter defining where and paginated data'
|
description: 'Filter defining where and paginated data'
|
||||||
}],
|
}],
|
||||||
returns: {
|
returns: {
|
||||||
type: ['Object'],
|
type: ['object'],
|
||||||
root: true
|
root: true
|
||||||
},
|
},
|
||||||
http: {
|
http: {
|
||||||
|
@ -20,8 +20,13 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.listSaleTracking = async filter => {
|
Self.listSaleTracking = async(filter, options) => {
|
||||||
let stmt = new ParameterizedSQL(`
|
const myOptions = {};
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
const stmt = new ParameterizedSQL(`
|
||||||
SELECT
|
SELECT
|
||||||
st.id,
|
st.id,
|
||||||
s.ticketFk,
|
s.ticketFk,
|
||||||
|
@ -41,9 +46,9 @@ module.exports = Self => {
|
||||||
|
|
||||||
stmt.merge(Self.makeSuffix(filter));
|
stmt.merge(Self.makeSuffix(filter));
|
||||||
|
|
||||||
let trackings = await Self.rawStmt(stmt);
|
const trackings = await Self.rawStmt(stmt, myOptions);
|
||||||
|
|
||||||
let salesFilter = {
|
const salesFilter = {
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
relation: 'item'
|
relation: 'item'
|
||||||
|
@ -52,14 +57,14 @@ module.exports = Self => {
|
||||||
where: {ticketFk: filter.where.ticketFk}
|
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 => {
|
for (const tracking of trackings) {
|
||||||
sales.forEach(sale => {
|
for (const sale of sales) {
|
||||||
if (tracking.itemFk == sale.itemFk)
|
if (tracking.itemFk == sale.itemFk)
|
||||||
tracking.item = sale.item();
|
tracking.item = sale.item();
|
||||||
});
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
return trackings;
|
return trackings;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,17 +1,39 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
|
||||||
describe('ticket listSaleTracking()', () => {
|
describe('ticket listSaleTracking()', () => {
|
||||||
it('should call the listSaleTracking method and return the response', async() => {
|
it('should call the listSaleTracking method and return the response', async() => {
|
||||||
let filter = {where: {ticketFk: 1}};
|
const tx = await models.SaleTracking.beginTransaction({});
|
||||||
let result = await app.models.SaleTracking.listSaleTracking(filter);
|
|
||||||
|
|
||||||
expect(result.length).toEqual(4);
|
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() => {
|
it(`should call the listSaleTracking method and return zero if doesn't have lines`, async() => {
|
||||||
let filter = {where: {ticketFk: 2}};
|
const tx = await models.SaleTracking.beginTransaction({});
|
||||||
let result = await app.models.SaleTracking.listSaleTracking(filter);
|
|
||||||
|
|
||||||
expect(result.length).toEqual(0);
|
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;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('editableStates', {
|
Self.remoteMethodCtx('editableStates', {
|
||||||
description: 'Gets the editable states according the user role ',
|
description: 'Gets the editable states according the user role ',
|
||||||
|
@ -8,7 +7,7 @@ module.exports = Self => {
|
||||||
type: 'object'
|
type: 'object'
|
||||||
},
|
},
|
||||||
returns: {
|
returns: {
|
||||||
type: ['Object'],
|
type: ['object'],
|
||||||
root: true
|
root: true
|
||||||
},
|
},
|
||||||
http: {
|
http: {
|
||||||
|
@ -17,14 +16,18 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.editableStates = async(ctx, filter) => {
|
Self.editableStates = async(ctx, filter, options) => {
|
||||||
let userId = ctx.req.accessToken.userId;
|
const models = Self.app.models;
|
||||||
let models = Self.app.models;
|
const userId = ctx.req.accessToken.userId;
|
||||||
let statesList = await models.State.find({where: filter.where});
|
const myOptions = {};
|
||||||
|
|
||||||
let isProduction = await models.Account.hasRole(userId, 'production');
|
if (typeof options == 'object')
|
||||||
let isSalesPerson = await models.Account.hasRole(userId, 'salesPerson');
|
Object.assign(myOptions, options);
|
||||||
let isAdministrative = await models.Account.hasRole(userId, 'administrative');
|
|
||||||
|
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)
|
if (isProduction || isAdministrative)
|
||||||
return statesList;
|
return statesList;
|
||||||
|
|
|
@ -1,34 +1,73 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
|
||||||
describe('ticket editableStates()', () => {
|
describe('ticket editableStates()', () => {
|
||||||
const filter = {where: {name: {like: '%%'}}};
|
const filter = {where: {name: {like: '%%'}}};
|
||||||
it('should return the expected state for the given role', async() => {
|
it('should return the expected state for the given role', async() => {
|
||||||
const productionRole = 49;
|
const tx = await models.State.beginTransaction({});
|
||||||
const ctx = {req: {accessToken: {userId: productionRole}}};
|
|
||||||
|
|
||||||
let result = await app.models.State.editableStates(ctx, filter);
|
try {
|
||||||
let deliveredState = result.some(state => state.code == 'DELIVERED');
|
const options = {transaction: tx};
|
||||||
|
|
||||||
expect(deliveredState).toBeTruthy();
|
const productionRole = 49;
|
||||||
|
const ctx = {req: {accessToken: {userId: productionRole}}};
|
||||||
|
|
||||||
|
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() => {
|
it(`should return the expected states by a specific role`, async() => {
|
||||||
const productionRole = 18;
|
const tx = await models.State.beginTransaction({});
|
||||||
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');
|
|
||||||
|
|
||||||
expect(deliveredState).toBeFalsy();
|
try {
|
||||||
expect(pickerDesignedState).toBeTruthy();
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
const productionRole = 18;
|
||||||
|
const ctx = {req: {accessToken: {userId: productionRole}}};
|
||||||
|
|
||||||
|
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() => {
|
it(`should return again the expected state by a specific role`, async() => {
|
||||||
const employeeRole = 1;
|
const tx = await models.State.beginTransaction({});
|
||||||
const ctx = {req: {accessToken: {userId: employeeRole}}};
|
|
||||||
let result = await app.models.State.editableStates(ctx, filter);
|
|
||||||
let pickerDesignedState = result.some(state => state.code == 'PICKER_DESIGNED');
|
|
||||||
|
|
||||||
expect(pickerDesignedState).toBeTruthy();
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
const employeeRole = 1;
|
||||||
|
const ctx = {req: {accessToken: {userId: employeeRole}}};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,12 +4,12 @@ module.exports = Self => {
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: {
|
accepts: {
|
||||||
arg: 'id',
|
arg: 'id',
|
||||||
type: 'Number',
|
type: 'number',
|
||||||
description: 'The document id',
|
description: 'The document id',
|
||||||
http: {source: 'path'}
|
http: {source: 'path'}
|
||||||
},
|
},
|
||||||
returns: {
|
returns: {
|
||||||
type: 'Object',
|
type: 'object',
|
||||||
root: true
|
root: true
|
||||||
},
|
},
|
||||||
http: {
|
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 models = Self.app.models;
|
||||||
const targetTicketDms = await models.TicketDms.findById(id);
|
const myOptions = {};
|
||||||
const targetDms = await models.Dms.findById(targetTicketDms.dmsFk);
|
let tx;
|
||||||
const trashDmsType = await models.DmsType.findOne({where: {code: 'trash'}});
|
|
||||||
|
|
||||||
await models.Dms.removeFile(ctx, targetTicketDms.dmsFk);
|
if (typeof options == 'object')
|
||||||
await targetTicketDms.destroy();
|
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;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,25 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
|
||||||
describe('TicketDms removeFile()', () => {
|
describe('TicketDms removeFile()', () => {
|
||||||
const ticketDmsId = 1;
|
const ticketDmsId = 1;
|
||||||
it(`should return an error for a user without enough privileges`, async() => {
|
it(`should return an error for a user without enough privileges`, async() => {
|
||||||
let clientId = 1101;
|
const tx = await models.TicketDms.beginTransaction({});
|
||||||
let ctx = {req: {accessToken: {userId: clientId}}};
|
|
||||||
|
|
||||||
let error;
|
let error;
|
||||||
await app.models.TicketDms.removeFile(ctx, ticketDmsId).catch(e => {
|
try {
|
||||||
error = e;
|
const options = {transaction: tx};
|
||||||
}).finally(() => {
|
|
||||||
expect(error.message).toEqual(`You don't have enough privileges`);
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(error).toBeDefined();
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(error.message).toEqual(`You don't have enough privileges`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,22 +6,22 @@ module.exports = Self => {
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: [{
|
accepts: [{
|
||||||
arg: 'id',
|
arg: 'id',
|
||||||
type: 'Integer',
|
type: 'number',
|
||||||
required: true,
|
required: true,
|
||||||
description: 'The request ID',
|
description: 'The request ID',
|
||||||
}, {
|
}, {
|
||||||
arg: 'itemFk',
|
arg: 'itemFk',
|
||||||
type: 'Integer',
|
type: 'number',
|
||||||
required: true,
|
required: true,
|
||||||
description: 'The requested item ID',
|
description: 'The requested item ID',
|
||||||
}, {
|
}, {
|
||||||
arg: 'quantity',
|
arg: 'quantity',
|
||||||
type: 'Integer',
|
type: 'number',
|
||||||
required: true,
|
required: true,
|
||||||
description: 'The requested item quantity',
|
description: 'The requested item quantity',
|
||||||
}],
|
}],
|
||||||
returns: {
|
returns: {
|
||||||
type: 'Object',
|
type: 'object',
|
||||||
root: true
|
root: true
|
||||||
},
|
},
|
||||||
http: {
|
http: {
|
||||||
|
@ -30,25 +30,37 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.confirm = async ctx => {
|
Self.confirm = async(ctx, options) => {
|
||||||
const userId = ctx.req.accessToken.userId;
|
const userId = ctx.req.accessToken.userId;
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const tx = await Self.beginTransaction({});
|
|
||||||
const $t = ctx.req.__; // $translate
|
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 {
|
try {
|
||||||
let options = {transaction: tx};
|
const item = await models.Item.findById(ctx.args.itemFk, null, myOptions);
|
||||||
|
|
||||||
let item = await models.Item.findById(ctx.args.itemFk, null, options);
|
|
||||||
if (!item)
|
if (!item)
|
||||||
throw new UserError(`That item doesn't exists`);
|
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'}
|
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;
|
const isAvailable = itemStock.available > 0;
|
||||||
|
|
||||||
if (!isAvailable)
|
if (!isAvailable)
|
||||||
|
@ -57,23 +69,24 @@ module.exports = Self => {
|
||||||
if (request.saleFk)
|
if (request.saleFk)
|
||||||
throw new UserError(`This request already contains a sale`);
|
throw new UserError(`This request already contains a sale`);
|
||||||
|
|
||||||
sale = await models.Sale.create({
|
const sale = await models.Sale.create({
|
||||||
ticketFk: request.ticketFk,
|
ticketFk: request.ticketFk,
|
||||||
itemFk: ctx.args.itemFk,
|
itemFk: ctx.args.itemFk,
|
||||||
quantity: ctx.args.quantity,
|
quantity: ctx.args.quantity,
|
||||||
concept: item.name
|
concept: item.name
|
||||||
}, options);
|
}, myOptions);
|
||||||
await request.updateAttributes({
|
await request.updateAttributes({
|
||||||
saleFk: sale.id,
|
saleFk: sale.id,
|
||||||
itemFk: sale.itemFk,
|
itemFk: sale.itemFk,
|
||||||
isOk: true
|
isOk: true
|
||||||
}, options);
|
}, myOptions);
|
||||||
|
|
||||||
query = `CALL vn.sale_calculateComponent(?, NULL)`;
|
const query = `CALL vn.sale_calculateComponent(?, NULL)`;
|
||||||
await Self.rawSql(query, [sale.id], options);
|
await Self.rawSql(query, [sale.id], myOptions);
|
||||||
|
|
||||||
const origin = ctx.req.headers.origin;
|
const origin = ctx.req.headers.origin;
|
||||||
const requesterId = request.requesterFk;
|
const requesterId = request.requesterFk;
|
||||||
|
|
||||||
const message = $t('Bought units from buy request', {
|
const message = $t('Bought units from buy request', {
|
||||||
quantity: sale.quantity,
|
quantity: sale.quantity,
|
||||||
concept: sale.concept,
|
concept: sale.concept,
|
||||||
|
@ -82,10 +95,9 @@ module.exports = Self => {
|
||||||
url: `${origin}/#!/ticket/${sale.ticketFk}/summary`,
|
url: `${origin}/#!/ticket/${sale.ticketFk}/summary`,
|
||||||
urlItem: `${origin}/#!/item/${sale.itemFk}/summary`
|
urlItem: `${origin}/#!/item/${sale.itemFk}/summary`
|
||||||
});
|
});
|
||||||
await models.Chat.sendCheckingPresence(ctx, requesterId, message);
|
await models.Chat.sendCheckingPresence(ctx, requesterId, message, myOptions);
|
||||||
|
|
||||||
// log
|
const logRecord = {
|
||||||
let logRecord = {
|
|
||||||
originFk: sale.ticketFk,
|
originFk: sale.ticketFk,
|
||||||
userFk: userId,
|
userFk: userId,
|
||||||
action: 'update',
|
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;
|
return sale;
|
||||||
} catch (error) {
|
} catch (e) {
|
||||||
await tx.rollback();
|
if (tx) await tx.rollback();
|
||||||
throw error;
|
throw e;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,7 +4,7 @@ module.exports = Self => {
|
||||||
accessType: 'WRITE',
|
accessType: 'WRITE',
|
||||||
accepts: [{
|
accepts: [{
|
||||||
arg: 'id',
|
arg: 'id',
|
||||||
type: 'Integer',
|
type: 'number',
|
||||||
required: true,
|
required: true,
|
||||||
description: 'The request ID',
|
description: 'The request ID',
|
||||||
}, {
|
}, {
|
||||||
|
@ -23,17 +23,37 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.deny = async ctx => {
|
Self.deny = async(ctx, options) => {
|
||||||
let userId = ctx.req.accessToken.userId;
|
const myOptions = {};
|
||||||
let worker = await Self.app.models.Worker.findOne({where: {userFk: userId}});
|
let tx;
|
||||||
|
|
||||||
let params = {
|
if (typeof options == 'object')
|
||||||
isOk: false,
|
Object.assign(myOptions, options);
|
||||||
attenderFk: worker.id,
|
|
||||||
response: ctx.args.observation,
|
|
||||||
};
|
|
||||||
|
|
||||||
let request = await Self.app.models.TicketRequest.findById(ctx.args.id);
|
if (!myOptions.transaction) {
|
||||||
return request.updateAttributes(params);
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -68,9 +68,13 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.filter = async(ctx, filter) => {
|
Self.filter = async(ctx, filter, options) => {
|
||||||
let conn = Self.dataSource.connector;
|
const conn = Self.dataSource.connector;
|
||||||
let userId = ctx.req.accessToken.userId;
|
const userId = ctx.req.accessToken.userId;
|
||||||
|
const myOptions = {};
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
if (ctx.args.mine)
|
if (ctx.args.mine)
|
||||||
ctx.args.attenderFk = userId;
|
ctx.args.attenderFk = userId;
|
||||||
|
@ -111,9 +115,7 @@ module.exports = Self => {
|
||||||
|
|
||||||
filter = mergeFilters(filter, {where});
|
filter = mergeFilters(filter, {where});
|
||||||
|
|
||||||
let stmt;
|
const stmt = new ParameterizedSQL(
|
||||||
|
|
||||||
stmt = new ParameterizedSQL(
|
|
||||||
`SELECT
|
`SELECT
|
||||||
tr.id,
|
tr.id,
|
||||||
tr.ticketFk,
|
tr.ticketFk,
|
||||||
|
@ -149,8 +151,6 @@ module.exports = Self => {
|
||||||
LEFT JOIN account.user ua ON ua.id = wka.userFk`);
|
LEFT JOIN account.user ua ON ua.id = wka.userFk`);
|
||||||
stmt.merge(conn.makeSuffix(filter));
|
stmt.merge(conn.makeSuffix(filter));
|
||||||
|
|
||||||
let result = await conn.executeStmt(stmt);
|
return conn.executeStmt(stmt, myOptions);
|
||||||
|
|
||||||
return result;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
|
||||||
describe('ticket-request confirm()', () => {
|
describe('ticket-request confirm()', () => {
|
||||||
let ctx = {
|
let ctx = {
|
||||||
|
@ -12,74 +12,89 @@ describe('ticket-request confirm()', () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
it(`should throw an error if the item doesn't exist`, async() => {
|
it(`should throw an error if the item doesn't exist`, async() => {
|
||||||
ctx.args = {itemFk: 999};
|
const tx = await models.TicketRequest.beginTransaction({});
|
||||||
|
|
||||||
let error;
|
let error;
|
||||||
try {
|
try {
|
||||||
await app.models.TicketRequest.confirm(ctx);
|
const options = {transaction: tx};
|
||||||
} catch (err) {
|
|
||||||
error = err;
|
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`);
|
expect(error.message).toEqual(`That item doesn't exists`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw an error if the item is not available', async() => {
|
it('should throw an error if the item is not available', async() => {
|
||||||
const requestId = 5;
|
const tx = await models.TicketRequest.beginTransaction({});
|
||||||
const itemId = 4;
|
|
||||||
const quantity = 99999;
|
|
||||||
|
|
||||||
ctx.args = {
|
|
||||||
itemFk: itemId,
|
|
||||||
id: requestId,
|
|
||||||
quantity: quantity
|
|
||||||
};
|
|
||||||
|
|
||||||
let error;
|
let error;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await app.models.TicketRequest.confirm(ctx);
|
const options = {transaction: tx};
|
||||||
} catch (err) {
|
|
||||||
error = err;
|
const requestId = 5;
|
||||||
|
const itemId = 4;
|
||||||
|
const quantity = 99999;
|
||||||
|
|
||||||
|
ctx.args = {
|
||||||
|
itemFk: itemId,
|
||||||
|
id: requestId,
|
||||||
|
quantity: quantity
|
||||||
|
};
|
||||||
|
|
||||||
|
await models.TicketRequest.confirm(ctx, options);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
error = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(error.message).toEqual(`This item is not available`);
|
expect(error.message).toEqual(`This item is not available`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should throw if there's a sale id`, async() => {
|
it(`should throw if there's a sale id`, async() => {
|
||||||
const requestId = 4;
|
const tx = await models.TicketRequest.beginTransaction({});
|
||||||
const itemId = 1;
|
|
||||||
const quantity = 10;
|
|
||||||
|
|
||||||
ctx.args = {
|
|
||||||
itemFk: itemId,
|
|
||||||
id: requestId,
|
|
||||||
quantity: quantity
|
|
||||||
};
|
|
||||||
|
|
||||||
const request = await app.models.TicketRequest.findById(requestId);
|
|
||||||
|
|
||||||
expect(request.saleFk).toBeNull();
|
|
||||||
|
|
||||||
await request.updateAttributes({saleFk: 2});
|
|
||||||
|
|
||||||
ctx.args = {
|
|
||||||
itemFk: itemId,
|
|
||||||
id: requestId,
|
|
||||||
quantity: quantity
|
|
||||||
};
|
|
||||||
|
|
||||||
let error;
|
let error;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await app.models.TicketRequest.confirm(ctx);
|
const options = {transaction: tx};
|
||||||
} catch (err) {
|
|
||||||
error = err;
|
const requestId = 4;
|
||||||
|
const itemId = 1;
|
||||||
|
const quantity = 10;
|
||||||
|
|
||||||
|
ctx.args = {
|
||||||
|
itemFk: itemId,
|
||||||
|
id: requestId,
|
||||||
|
quantity: quantity
|
||||||
|
};
|
||||||
|
|
||||||
|
const request = await models.TicketRequest.findById(requestId, null, options);
|
||||||
|
|
||||||
|
expect(request.saleFk).toBeNull();
|
||||||
|
|
||||||
|
await request.updateAttributes({saleFk: 2}, options);
|
||||||
|
|
||||||
|
ctx.args = {
|
||||||
|
itemFk: itemId,
|
||||||
|
id: requestId,
|
||||||
|
quantity: quantity
|
||||||
|
};
|
||||||
|
|
||||||
|
await models.TicketRequest.confirm(ctx, options);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
error = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(error.message).toEqual(`This request already contains a sale`);
|
expect(error.message).toEqual(`This request already contains a sale`);
|
||||||
|
|
||||||
// restores
|
|
||||||
await request.updateAttributes({saleFk: null});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,25 +1,22 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
|
||||||
describe('ticket-request deny()', () => {
|
describe('ticket-request deny()', () => {
|
||||||
let request;
|
it('should return the dinied ticket request', async() => {
|
||||||
afterAll(async done => {
|
const tx = await models.TicketRequest.beginTransaction({});
|
||||||
let params = {
|
|
||||||
isOk: null,
|
|
||||||
attenderFk: request.attenderFk,
|
|
||||||
response: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
await request.updateAttributes(params);
|
try {
|
||||||
done();
|
const options = {transaction: tx};
|
||||||
});
|
|
||||||
|
|
||||||
it('should return all ticket requests', async() => {
|
const ctx = {req: {accessToken: {userId: 9}}, args: {id: 4, observation: 'my observation'}};
|
||||||
let ctx = {req: {accessToken: {userId: 9}}, args: {id: 4, observation: 'my observation'}};
|
|
||||||
|
|
||||||
request = await app.models.TicketRequest.findById(ctx.args.id);
|
const result = await models.TicketRequest.deny(ctx, options);
|
||||||
|
|
||||||
let result = await app.models.TicketRequest.deny(ctx);
|
expect(result.id).toEqual(4);
|
||||||
|
|
||||||
expect(result.id).toEqual(4);
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,85 +1,184 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
|
||||||
describe('ticket-request filter()', () => {
|
describe('ticket-request filter()', () => {
|
||||||
const userId = 9;
|
const userId = 9;
|
||||||
let ctx = {req: {accessToken: {userId: userId}}};
|
let ctx = {req: {accessToken: {userId: userId}}};
|
||||||
|
|
||||||
it('should now return all ticket requests', async() => {
|
it('should now return all ticket requests', async() => {
|
||||||
ctx.args = {};
|
const tx = await models.TicketRequest.beginTransaction({});
|
||||||
|
|
||||||
const result = await app.models.TicketRequest.filter(ctx);
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
expect(result.length).toEqual(3);
|
ctx.args = {};
|
||||||
|
|
||||||
|
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() => {
|
it('should return the ticket request matching a generic search value which is the ticket ID', async() => {
|
||||||
ctx.args = {search: 11};
|
const tx = await models.TicketRequest.beginTransaction({});
|
||||||
|
|
||||||
const result = await app.models.TicketRequest.filter(ctx);
|
try {
|
||||||
const requestId = result[0].id;
|
const options = {transaction: tx};
|
||||||
|
|
||||||
expect(requestId).toEqual(4);
|
ctx.args = {search: 11};
|
||||||
|
|
||||||
|
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() => {
|
it('should return the ticket request matching a generic search value which is the client address alias', async() => {
|
||||||
ctx.args = {search: 'NY roofs'};
|
const tx = await models.TicketRequest.beginTransaction({});
|
||||||
|
|
||||||
const result = await app.models.TicketRequest.filter(ctx);
|
try {
|
||||||
const requestId = result[0].id;
|
const options = {transaction: tx};
|
||||||
|
|
||||||
expect(requestId).toEqual(4);
|
ctx.args = {search: 'NY roofs'};
|
||||||
|
|
||||||
|
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() => {
|
it('should return the ticket request matching the ticket ID', async() => {
|
||||||
ctx.args = {ticketFk: 11};
|
const tx = await models.TicketRequest.beginTransaction({});
|
||||||
const result = await app.models.TicketRequest.filter(ctx);
|
|
||||||
const requestId = result[0].id;
|
|
||||||
|
|
||||||
expect(requestId).toEqual(4);
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
ctx.args = {ticketFk: 11};
|
||||||
|
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() => {
|
it('should return the ticket request matching the atender ID', async() => {
|
||||||
ctx.args = {attenderFk: 35};
|
const tx = await models.TicketRequest.beginTransaction({});
|
||||||
|
|
||||||
const result = await app.models.TicketRequest.filter(ctx);
|
try {
|
||||||
const requestId = result[0].id;
|
const options = {transaction: tx};
|
||||||
|
|
||||||
expect(requestId).toEqual(3);
|
ctx.args = {attenderFk: 35};
|
||||||
|
|
||||||
|
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() => {
|
it('should return the ticket request matching the isOk triple-state', async() => {
|
||||||
ctx.args = {isOk: null};
|
const tx = await models.TicketRequest.beginTransaction({});
|
||||||
|
|
||||||
const result = await app.models.TicketRequest.filter(ctx);
|
try {
|
||||||
const requestId = result[0].id;
|
const options = {transaction: tx};
|
||||||
|
|
||||||
expect(requestId).toEqual(3);
|
ctx.args = {isOk: null};
|
||||||
|
|
||||||
|
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() => {
|
it('should return the ticket request matching the client ID', async() => {
|
||||||
ctx.args = {clientFk: 1102};
|
const tx = await models.TicketRequest.beginTransaction({});
|
||||||
|
|
||||||
const result = await app.models.TicketRequest.filter(ctx);
|
try {
|
||||||
const requestId = result[0].id;
|
const options = {transaction: tx};
|
||||||
|
|
||||||
expect(requestId).toEqual(4);
|
ctx.args = {clientFk: 1102};
|
||||||
|
|
||||||
|
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() => {
|
it('should return the ticket request matching the warehouse ID', async() => {
|
||||||
ctx.args = {warehouse: 1};
|
const tx = await models.TicketRequest.beginTransaction({});
|
||||||
|
|
||||||
const result = await app.models.TicketRequest.filter(ctx, {order: 'id'});
|
try {
|
||||||
const requestId = result[0].id;
|
const options = {transaction: tx};
|
||||||
|
|
||||||
expect(requestId).toEqual(3);
|
ctx.args = {warehouse: 1};
|
||||||
|
|
||||||
|
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() => {
|
it('should return the ticket request matching the salesPerson ID', async() => {
|
||||||
ctx.args = {salesPersonFk: 18};
|
const tx = await models.TicketRequest.beginTransaction({});
|
||||||
|
|
||||||
const result = await app.models.TicketRequest.filter(ctx);
|
try {
|
||||||
const requestId = result[0].id;
|
const options = {transaction: tx};
|
||||||
|
|
||||||
expect(requestId).toEqual(3);
|
ctx.args = {salesPersonFk: 18};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,13 +6,13 @@ module.exports = Self => {
|
||||||
{
|
{
|
||||||
arg: 'ticketIds',
|
arg: 'ticketIds',
|
||||||
description: 'the array of ticket ids to set as delivered',
|
description: 'the array of ticket ids to set as delivered',
|
||||||
type: ['Number'],
|
type: ['number'],
|
||||||
required: true,
|
required: true,
|
||||||
http: {source: 'body'}
|
http: {source: 'body'}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
returns: {
|
returns: {
|
||||||
type: 'Object',
|
type: 'object',
|
||||||
root: true
|
root: true
|
||||||
},
|
},
|
||||||
http: {
|
http: {
|
||||||
|
@ -21,30 +21,47 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.setDelivered = async(ctx, ticketIds) => {
|
Self.setDelivered = async(ctx, ticketIds, options) => {
|
||||||
let userId = ctx.req.accessToken.userId;
|
const userId = ctx.req.accessToken.userId;
|
||||||
let models = Self.app.models;
|
const models = Self.app.models;
|
||||||
|
const myOptions = {};
|
||||||
|
let tx;
|
||||||
|
|
||||||
let state = await models.State.findOne({
|
if (typeof options == 'object')
|
||||||
where: {
|
Object.assign(myOptions, options);
|
||||||
code: 'delivered'
|
|
||||||
},
|
|
||||||
fields: ['id', 'name', 'alertLevel', 'code']
|
|
||||||
});
|
|
||||||
|
|
||||||
let worker = await models.Worker.findOne({where: {userFk: userId}});
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
let promises = [];
|
myOptions.transaction = tx;
|
||||||
for (let id of ticketIds) {
|
|
||||||
let promise = models.TicketTracking.changeState(ctx, {
|
|
||||||
stateFk: state.id,
|
|
||||||
workerFk: worker.id,
|
|
||||||
ticketFk: id
|
|
||||||
});
|
|
||||||
promises.push(promise);
|
|
||||||
}
|
}
|
||||||
await Promise.all(promises);
|
|
||||||
|
|
||||||
return state;
|
try {
|
||||||
|
const state = await models.State.findOne({
|
||||||
|
where: {
|
||||||
|
code: 'delivered'
|
||||||
|
},
|
||||||
|
fields: ['id', 'name', 'alertLevel', 'code']
|
||||||
|
}, myOptions);
|
||||||
|
|
||||||
|
const worker = await models.Worker.findOne({where: {userFk: userId}}, myOptions);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const models = require('vn-loopback/server/server').models;
|
||||||
const LoopBackContext = require('loopback-context');
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('ticket setDelivered()', () => {
|
describe('ticket setDelivered()', () => {
|
||||||
|
@ -7,50 +7,41 @@ describe('ticket setDelivered()', () => {
|
||||||
accessToken: {userId: userId},
|
accessToken: {userId: userId},
|
||||||
};
|
};
|
||||||
|
|
||||||
let ticketOne;
|
|
||||||
let ticketTwo;
|
|
||||||
|
|
||||||
beforeAll(async done => {
|
beforeAll(async done => {
|
||||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
active: activeCtx
|
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();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return the state which has been applied to the given tickets', async() => {
|
it('should return the state which has been applied to the given tickets', async() => {
|
||||||
let ctx = {req: {accessToken: {userId: 49}}};
|
const tx = await models.TicketTracking.beginTransaction({});
|
||||||
let delivered = await app.models.State.findOne({where: {code: 'delivered'}, fields: ['id']});
|
|
||||||
|
|
||||||
let params = [ticketOne.id, ticketTwo.id];
|
try {
|
||||||
let state = await app.models.TicketTracking.setDelivered(ctx, params);
|
const options = {transaction: tx};
|
||||||
|
|
||||||
expect(state.id).toEqual(delivered.id);
|
const ctx = {req: {accessToken: {userId: 49}}};
|
||||||
|
|
||||||
// restores
|
const originalTicketOne = await models.Ticket.findById(8, null, options);
|
||||||
await app.models.TicketTracking.destroyById(state.id);
|
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);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,18 +10,18 @@ module.exports = Self => {
|
||||||
accepts: [
|
accepts: [
|
||||||
{
|
{
|
||||||
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',
|
||||||
http: {source: 'query'}
|
http: {source: 'query'}
|
||||||
}, {
|
}, {
|
||||||
arg: 'search',
|
arg: 'search',
|
||||||
type: 'String',
|
type: 'string',
|
||||||
description: `If it's and integer searchs by id, otherwise it searchs by client id`,
|
description: `If it's and integer searchs by id, otherwise it searchs by client id`,
|
||||||
http: {source: 'query'}
|
http: {source: 'query'}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
returns: {
|
returns: {
|
||||||
type: ['Object'],
|
type: ['object'],
|
||||||
root: true
|
root: true
|
||||||
},
|
},
|
||||||
http: {
|
http: {
|
||||||
|
@ -30,10 +30,14 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.filter = async(ctx, filter) => {
|
Self.filter = async(ctx, filter, options) => {
|
||||||
let conn = Self.dataSource.connector;
|
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) {
|
switch (param) {
|
||||||
case 'search':
|
case 'search':
|
||||||
return {or: [
|
return {or: [
|
||||||
|
@ -46,10 +50,9 @@ module.exports = Self => {
|
||||||
|
|
||||||
filter = mergeFilters(ctx.args.filter, {where});
|
filter = mergeFilters(ctx.args.filter, {where});
|
||||||
|
|
||||||
let stmts = [];
|
const stmts = [];
|
||||||
let stmt;
|
|
||||||
|
|
||||||
stmt = new ParameterizedSQL(
|
const stmt = new ParameterizedSQL(
|
||||||
`SELECT t.id AS ticketFk, c.id AS clientFk, c.name AS clientName, tw.weekDay,
|
`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
|
wh.name AS warehouseName, u.id AS workerFk, u.name AS userName, u.nickName, tw.agencyModeFk
|
||||||
FROM ticketWeekly tw
|
FROM ticketWeekly tw
|
||||||
|
@ -60,10 +63,10 @@ module.exports = Self => {
|
||||||
);
|
);
|
||||||
|
|
||||||
stmt.merge(conn.makeSuffix(filter));
|
stmt.merge(conn.makeSuffix(filter));
|
||||||
let itemsIndex = stmts.push(stmt) - 1;
|
const itemsIndex = stmts.push(stmt) - 1;
|
||||||
|
|
||||||
let sql = ParameterizedSQL.join(stmts, ';');
|
const sql = ParameterizedSQL.join(stmts, ';');
|
||||||
let result = await conn.executeStmt(sql);
|
const result = await conn.executeStmt(sql, myOptions);
|
||||||
return itemsIndex === 0 ? result : result[itemsIndex];
|
return itemsIndex === 0 ? result : result[itemsIndex];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,43 +1,89 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
|
||||||
describe('ticket-weekly filter()', () => {
|
describe('ticket-weekly filter()', () => {
|
||||||
const authUserId = 9;
|
const authUserId = 9;
|
||||||
it('should all return the tickets matching the filter', async() => {
|
it('should all return the tickets matching the filter', async() => {
|
||||||
const filter = {order: 't.id ASC'};
|
const tx = await models.TicketWeekly.beginTransaction({});
|
||||||
const ctx = {req: {accessToken: {userId: authUserId}}, args: {filter: filter}};
|
|
||||||
const result = await app.models.TicketWeekly.filter(ctx);
|
|
||||||
|
|
||||||
const firstRow = result[0];
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
expect(firstRow.ticketFk).toEqual(1);
|
const filter = {order: 't.id ASC'};
|
||||||
expect(result.length).toEqual(5);
|
|
||||||
|
const ctx = {req: {accessToken: {userId: authUserId}}, args: {filter: filter}};
|
||||||
|
|
||||||
|
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() => {
|
it('should return the ticket with id one', async() => {
|
||||||
const ctx = {req: {accessToken: {userId: authUserId}}, args: {search: 2}};
|
const tx = await models.TicketWeekly.beginTransaction({});
|
||||||
const filter = {};
|
|
||||||
const result = await app.models.TicketWeekly.filter(ctx, filter);
|
|
||||||
const firstRow = result[0];
|
|
||||||
|
|
||||||
expect(firstRow.ticketFk).toEqual(2);
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
const ctx = {req: {accessToken: {userId: authUserId}}, args: {search: 2}};
|
||||||
|
|
||||||
|
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() => {
|
it('should return the ticket matching the client name', async() => {
|
||||||
const ctx = {req: {accessToken: {userId: authUserId}}, args: {search: 'bruce'}};
|
const tx = await models.TicketWeekly.beginTransaction({});
|
||||||
const filter = {};
|
|
||||||
const result = await app.models.TicketWeekly.filter(ctx, filter);
|
|
||||||
const firstRow = result[0];
|
|
||||||
|
|
||||||
expect(firstRow.clientName).toEqual('Bruce Wayne');
|
try {
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
const ctx = {req: {accessToken: {userId: authUserId}}, args: {search: 'bruce'}};
|
||||||
|
|
||||||
|
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() => {
|
it('should return the ticket matching the client id', async() => {
|
||||||
const ctx = {req: {accessToken: {userId: authUserId}}, args: {search: 1101}};
|
const tx = await models.TicketWeekly.beginTransaction({});
|
||||||
const filter = {};
|
|
||||||
const result = await app.models.TicketWeekly.filter(ctx, filter);
|
|
||||||
const firstRow = result[0];
|
|
||||||
|
|
||||||
expect(firstRow.clientFk).toEqual(1101);
|
try {
|
||||||
expect(firstRow.clientName).toEqual('Bruce Wayne');
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
const ctx = {req: {accessToken: {userId: authUserId}}, args: {search: 1101}};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue