Merge pull request '2973-module_zone_transactions' (#669) from 2973-module_zone_transactions into dev
gitea/salix/pipeline/head This commit looks good Details

Reviewed-on: #669
Reviewed-by: Joan Sanchez <joan@verdnatura.es>
This commit is contained in:
Joan Sanchez 2021-06-22 09:29:13 +00:00
commit 7d93f0ac0e
24 changed files with 454 additions and 192 deletions

View File

@ -6,7 +6,7 @@ module.exports = Self => {
description: 'Returns a list of agencies from a warehouse', description: 'Returns a list of agencies from a warehouse',
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`
}], }],
returns: { returns: {
@ -19,9 +19,14 @@ module.exports = Self => {
} }
}); });
Self.byWarehouse = async filter => { Self.byWarehouse = async(filter, options) => {
const conn = Self.dataSource.connector; const conn = Self.dataSource.connector;
const where = {isActive: true}; const where = {isActive: true};
let myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
filter = mergeFilters(filter, {where}); filter = mergeFilters(filter, {where});
let stmt = new ParameterizedSQL( let stmt = new ParameterizedSQL(
@ -30,7 +35,9 @@ module.exports = Self => {
SELECT DISTINCT am.id, am.name, am.isActive, zw.warehouseFk SELECT DISTINCT am.id, am.name, am.isActive, zw.warehouseFk
FROM zoneWarehouse zw FROM zoneWarehouse zw
JOIN zone z ON z.id = zw.zoneFk JOIN zone z ON z.id = zw.zoneFk
JOIN agencyMode am ON am.id = z.agencyModeFk) am`); JOIN agencyMode am ON am.id = z.agencyModeFk) am`,
null, myOptions);
stmt.merge(conn.makeSuffix(filter)); stmt.merge(conn.makeSuffix(filter));
return conn.executeStmt(stmt); return conn.executeStmt(stmt);

View File

@ -4,17 +4,41 @@ describe('AgencyMode byWarehhouse()', () => {
const warehouseId = 1; const warehouseId = 1;
it('should return all the agencies', async() => { it('should return all the agencies', async() => {
const where = {}; const where = {};
const agencies = await app.models.AgencyMode.byWarehouse({where});
expect(agencies.length).toBeGreaterThan(10); const tx = await app.models.Zone.beginTransaction({});
try {
const options = {transaction: tx};
const agencies = await app.models.AgencyMode.byWarehouse({where}, options);
expect(agencies.length).toBeGreaterThan(10);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should return only the agencies for a warehouse', async() => { it('should return only the agencies for a warehouse', async() => {
const where = {warehouseFk: warehouseId}; const where = {warehouseFk: warehouseId};
const agencies = await app.models.AgencyMode.byWarehouse({where});
const validWarehouse = agencies.every(agency => agency.warehouseFk = warehouseId);
expect(agencies.length).toEqual(6); const tx = await app.models.Zone.beginTransaction({});
expect(validWarehouse).toBeTruthy();
try {
const options = {transaction: tx};
const agencies = await app.models.AgencyMode.byWarehouse({where}, options);
const validWarehouse = agencies.every(agency => agency.warehouseFk = warehouseId);
expect(agencies.length).toEqual(6);
expect(validWarehouse).toBeTruthy();
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -6,11 +6,13 @@ module.exports = Self => {
arg: 'addressFk', arg: 'addressFk',
type: 'number', type: 'number',
required: true required: true
}, { },
{
arg: 'landed', arg: 'landed',
type: 'date', type: 'date',
required: true required: true
}, { },
{
arg: 'warehouseFk', arg: 'warehouseFk',
type: 'number', type: 'number',
required: true required: true
@ -26,9 +28,15 @@ module.exports = Self => {
} }
}); });
Self.getAgenciesWithWarehouse = async(addressFk, landed, warehouseFk) => { Self.getAgenciesWithWarehouse = async(addressFk, landed, warehouseFk, options) => {
let query = `CALL vn.zone_getWarehouse(?, ?, ?)`; let myOptions = {};
let [result] = await Self.rawSql(query, [addressFk, landed, warehouseFk]);
if (typeof options == 'object')
Object.assign(myOptions, options);
const query = 'CALL vn.zone_getWarehouse(?, ?, ?)';
const [result] = await Self.rawSql(query, [addressFk, landed, warehouseFk], myOptions);
return result; return result;
}; };
}; };

View File

@ -34,7 +34,12 @@ module.exports = Self => {
} }
}); });
Self.getLanded = async(ctx, shipped, addressFk, agencyModeFk, warehouseFk) => { Self.getLanded = async(ctx, shipped, addressFk, agencyModeFk, warehouseFk, options) => {
let myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const userId = ctx.req.accessToken.userId; const userId = ctx.req.accessToken.userId;
const models = Self.app.models; const models = Self.app.models;
const roles = await models.Account.getRoles(userId); const roles = await models.Account.getRoles(userId);
@ -44,23 +49,24 @@ module.exports = Self => {
let showExpired = false; let showExpired = false;
if (canSeeExpired.length) showExpired = true; if (canSeeExpired.length) showExpired = true;
let stmts = []; const stmts = [];
stmts.push(new ParameterizedSQL( stmts.push(new ParameterizedSQL(
`CALL vn.zone_getLanded(?, ?, ?, ?, ?)`, [ 'CALL vn.zone_getLanded(?, ?, ?, ?, ?)', [
shipped, shipped,
addressFk, addressFk,
agencyModeFk, agencyModeFk,
warehouseFk, warehouseFk,
showExpired showExpired
] ],
myOptions
)); ));
let rsIndex = stmts.push( const rsIndex = stmts.push('SELECT * FROM tmp.zoneGetLanded') - 1;
`SELECT * FROM tmp.zoneGetLanded`) - 1;
stmts.push(`DROP TEMPORARY TABLE tmp.zoneGetLanded`);
let sql = ParameterizedSQL.join(stmts, ';'); stmts.push('DROP TEMPORARY TABLE tmp.zoneGetLanded');
let landed = await Self.rawStmt(sql);
const sql = ParameterizedSQL.join(stmts, ';');
const landed = await Self.rawStmt(sql, myOptions);
return landed[rsIndex][0]; return landed[rsIndex][0];
}; };

View File

@ -40,7 +40,7 @@ module.exports = Self => {
if (typeof options == 'object') if (typeof options == 'object')
Object.assign(myOptions, options); Object.assign(myOptions, options);
let stmts = []; const stmts = [];
stmts.push(new ParameterizedSQL( stmts.push(new ParameterizedSQL(
`CALL vn.zone_getShippedWarehouse(?, ?, ?)`, [ `CALL vn.zone_getShippedWarehouse(?, ?, ?)`, [
landed, landed,

View File

@ -22,13 +22,18 @@ module.exports = Self => {
} }
}); });
Self.landsThatDay = async(addressFk, landed) => { Self.landsThatDay = async(addressFk, landed, options) => {
let myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
let query = ` let query = `
CALL vn.zone_getAgency(?, ?); CALL vn.zone_getAgency(?, ?);
SELECT * FROM tmp.zoneGetAgency; SELECT * FROM tmp.zoneGetAgency;
DROP TEMPORARY TABLE tmp.zoneGetAgency; DROP TEMPORARY TABLE tmp.zoneGetAgency;
`; `;
let result = await Self.rawSql(query, [addressFk, landed]); const result = await Self.rawSql(query, [addressFk, landed], myOptions);
return result[1]; return result[1];
}; };

View File

@ -3,17 +3,39 @@ const app = require('vn-loopback/server/server');
describe('Agency getAgenciesWithWarehouse()', () => { describe('Agency getAgenciesWithWarehouse()', () => {
const today = new Date(); const today = new Date();
it('should return the agencies that can handle the given delivery request', async() => { it('should return the agencies that can handle the given delivery request', async() => {
let agencies = await app.models.Agency.getAgenciesWithWarehouse(101, today, 1); const tx = await app.models.Zone.beginTransaction({});
expect(agencies.length).toEqual(3); try {
expect(agencies[0].agencyMode).toEqual('inhouse pickup'); const options = {transaction: tx};
expect(agencies[1].agencyMode).toEqual('Other agency');
expect(agencies[2].agencyMode).toEqual('Refund'); const agencies = await app.models.Agency.getAgenciesWithWarehouse(101, today, 1, options);
expect(agencies.length).toEqual(3);
expect(agencies[0].agencyMode).toEqual('inhouse pickup');
expect(agencies[1].agencyMode).toEqual('Other agency');
expect(agencies[2].agencyMode).toEqual('Refund');
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should return no agencies if the date is incorrect', async() => { it('should return no agencies if the date is incorrect', async() => {
let agencies = await app.models.Agency.getAgenciesWithWarehouse(101, null, 1); const tx = await app.models.Zone.beginTransaction({});
expect(agencies.length).toEqual(0); try {
const options = {transaction: tx};
const agencies = await app.models.Agency.getAgenciesWithWarehouse(101, null, 1, options);
expect(agencies.length).toEqual(0);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -8,8 +8,20 @@ describe('agency getLanded()', () => {
const addressFk = 121; const addressFk = 121;
const agencyModeFk = 7; const agencyModeFk = 7;
const warehouseFk = 1; const warehouseFk = 1;
let result = await app.models.Agency.getLanded(ctx, shipped, addressFk, agencyModeFk, warehouseFk);
expect(result.landed).toBeDefined(); const tx = await app.models.Zone.beginTransaction({});
try {
const options = {transaction: tx};
const result = await app.models.Agency.getLanded(ctx, shipped, addressFk, agencyModeFk, warehouseFk, options);
expect(result.landed).toBeDefined();
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -2,50 +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();
landed.setDate(landed.getDate() + 1);
const addressFk = 121;
const agencyModeFk = 7;
const warehouseFk = 1;
const tx = await app.models.Agency.beginTransaction({}); const tx = await app.models.Agency.beginTransaction({});
let result;
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
const landed = new Date(); const result = await app.models.Agency.getShipped(landed, addressFk, agencyModeFk, warehouseFk, options);
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); expect(result).toBeDefined();
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
await tx.rollback(); await tx.rollback();
throw e; throw e;
} }
expect(result).toBeDefined();
}); });
it('should not return a shipment date', async() => { it('should not return a shipment date', async() => {
const newDate = new Date();
newDate.setMonth(newDate.getMonth() - 1);
const landed = newDate;
const addressFk = 121;
const agencyModeFk = 7;
const warehouseFk = 1;
const tx = await app.models.Agency.beginTransaction({}); const tx = await app.models.Agency.beginTransaction({});
let result;
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
let newDate = new Date();
newDate.setMonth(newDate.getMonth() - 1);
const landed = newDate;
const addressFk = 121;
const agencyModeFk = 7;
const warehouseFk = 1;
result = await app.models.Agency.getShipped(landed, addressFk, agencyModeFk, warehouseFk, options); const result = await app.models.Agency.getShipped(landed, addressFk, agencyModeFk, warehouseFk, options);
expect(result).toBeUndefined();
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
await tx.rollback(); await tx.rollback();
throw e; throw e;
} }
expect(result).toBeUndefined();
}); });
}); });

View File

@ -3,8 +3,19 @@ const app = require('vn-loopback/server/server');
describe('Agency landsThatDay()', () => { describe('Agency landsThatDay()', () => {
const today = new Date(); const today = new Date();
it('should return a list of agencies that can land a shipment on a day for an address', async() => { it('should return a list of agencies that can land a shipment on a day for an address', async() => {
let agencies = await app.models.Agency.landsThatDay(101, today); const tx = await app.models.Agency.beginTransaction({});
expect(agencies.length).toBeGreaterThanOrEqual(3); try {
const options = {transaction: tx};
const agencies = await app.models.Agency.landsThatDay(101, today, options);
expect(agencies.length).toBeGreaterThanOrEqual(3);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -11,7 +11,7 @@ module.exports = Self => {
}, },
returns: { returns: {
root: true, root: true,
type: 'Object' type: 'object'
}, },
http: { http: {
path: '/:id/clone', path: '/:id/clone',
@ -19,13 +19,20 @@ module.exports = Self => {
} }
}); });
Self.clone = async id => { Self.clone = async(id, options) => {
const models = Self.app.models; const models = Self.app.models;
const tx = await Self.beginTransaction({}); let tx;
let myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try { try {
let options = {transaction: tx};
// Find original zone // Find original zone
const zone = await models.Zone.findOne({ const zone = await models.Zone.findOne({
fields: [ fields: [
@ -37,37 +44,37 @@ module.exports = Self => {
'bonus', 'bonus',
'isVolumetric'], 'isVolumetric'],
where: {id} where: {id}
}, options); }, myOptions);
// Find all original included geolocations // Find all original included geolocations
const includedGeo = await models.ZoneIncluded.find({ const includedGeo = await models.ZoneIncluded.find({
fields: ['geoFk', 'isIncluded'], fields: ['geoFk', 'isIncluded'],
where: {zoneFk: id} where: {zoneFk: id}
}, options); }, myOptions);
// Find all original selected days // Find all original selected days
const calendarDays = await models.ZoneEvent.find({ const calendarDays = await models.ZoneEvent.find({
fields: {id: false}, fields: {id: false},
where: {zoneFk: id} where: {zoneFk: id}
}, options); }, myOptions);
const newZone = await Self.create(zone, options); const newZone = await Self.create(zone, myOptions);
const newIncludedGeo = includedGeo.map(included => { const newIncludedGeo = includedGeo.map(included => {
included.zoneFk = newZone.id; included.zoneFk = newZone.id;
return included; return included;
}); });
const newCalendayDays = calendarDays.map(day => { const newCalendarDays = calendarDays.map(day => {
day.zoneFk = newZone.id; day.zoneFk = newZone.id;
return day; return day;
}); });
await models.ZoneIncluded.create(newIncludedGeo, options); await models.ZoneIncluded.create(newIncludedGeo, myOptions);
await models.ZoneEvent.create(newCalendayDays, options); await models.ZoneEvent.create(newCalendarDays, myOptions);
await tx.commit(); if (tx) await tx.commit();
return newZone; return newZone;
} catch (e) { } catch (e) {
await tx.rollback(); if (tx) await tx.rollback();
throw e; throw e;
} }
}; };

View File

@ -4,12 +4,12 @@ module.exports = Self => {
accessType: 'WRITE', accessType: 'WRITE',
accepts: { accepts: {
arg: 'id', arg: 'id',
type: 'Number', type: 'number',
description: 'The zone id', description: 'The zone id',
http: {source: 'path'} http: {source: 'path'}
}, },
returns: { returns: {
type: 'Object', type: 'object',
root: true root: true
}, },
http: { http: {
@ -18,15 +18,25 @@ module.exports = Self => {
} }
}); });
Self.deleteZone = async(ctx, id) => { Self.deleteZone = async(ctx, id, options) => {
const models = Self.app.models; const models = Self.app.models;
const token = ctx.req.accessToken; const token = ctx.req.accessToken;
const userId = token.userId; const userId = token.userId;
const today = new Date(); const today = new Date();
today.setHours(0, 0, 0, 0); today.setHours(0, 0, 0, 0);
const tx = await Self.beginTransaction({});
let tx;
let myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try { try {
const options = {transaction: tx};
const filter = { const filter = {
where: { where: {
zoneFk: id, zoneFk: id,
@ -41,13 +51,13 @@ module.exports = Self => {
}; };
const promises = []; const promises = [];
const ticketList = await models.Ticket.find(filter, options); const ticketList = await models.Ticket.find(filter, myOptions);
const fixingState = await models.State.findOne({where: {code: 'FIXING'}}, options); const fixingState = await models.State.findOne({where: {code: 'FIXING'}}, myOptions);
const worker = await models.Worker.findOne({ const worker = await models.Worker.findOne({
where: {userFk: userId} where: {userFk: userId}
}, options); }, myOptions);
await models.Ticket.rawSql('UPDATE ticket SET zoneFk = NULL WHERE zoneFk = ?', [id], options); await models.Ticket.rawSql('UPDATE ticket SET zoneFk = NULL WHERE zoneFk = ?', [id], myOptions);
for (ticket of ticketList) { for (ticket of ticketList) {
if (ticket.ticketState().alertLevel == 0) { if (ticket.ticketState().alertLevel == 0) {
@ -55,16 +65,17 @@ module.exports = Self => {
ticketFk: ticket.id, ticketFk: ticket.id,
stateFk: fixingState.id, stateFk: fixingState.id,
workerFk: worker.id workerFk: worker.id
}, options)); }, myOptions));
} }
} }
await Promise.all(promises); await Promise.all(promises, myOptions);
await models.Zone.destroyById(id, options); await models.Zone.destroyById(id, myOptions);
await tx.commit();
if (tx) await tx.commit();
return id; return id;
} catch (err) { } catch (err) {
await tx.rollback(); if (tx) await tx.rollback();
throw err; throw err;
} }
}; };

View File

@ -5,17 +5,18 @@ module.exports = Self => {
accepts: [ accepts: [
{ {
arg: 'geoFk', arg: 'geoFk',
type: 'Number', type: 'number',
description: 'The geo id' description: 'The geo id'
}, { },
{
arg: 'agencyModeFk', arg: 'agencyModeFk',
type: 'Number', type: 'number',
description: 'The agency mode id' description: 'The agency mode id'
} }
], ],
returns: { returns: {
type: 'Object', type: 'object',
root: true root: true
}, },
http: { http: {
@ -24,11 +25,14 @@ module.exports = Self => {
} }
}); });
Self.getEvents = async(geoFk, agencyModeFk) => { Self.getEvents = async(geoFk, agencyModeFk, options) => {
let [events, exclusions] = await Self.rawSql( let myOptions = {};
`CALL zone_getEvents(?, ?)`,
[geoFk, agencyModeFk] if (typeof options == 'object')
); Object.assign(myOptions, options);
const [events, exclusions] = await Self.rawSql('CALL zone_getEvents(?, ?)', [geoFk, agencyModeFk], myOptions);
return {events, exclusions}; return {events, exclusions};
}; };
}; };

View File

@ -5,22 +5,24 @@ module.exports = Self => {
accepts: [ accepts: [
{ {
arg: 'id', arg: 'id',
type: 'Number', type: 'number',
description: 'The zone id', description: 'The zone id',
http: {source: 'path'}, http: {source: 'path'},
required: true required: true
}, { },
{
arg: 'parentId', arg: 'parentId',
type: 'Number', type: 'number',
description: 'Get the children of the specified father', description: 'Get the children of the specified father',
}, { },
{
arg: 'search', arg: 'search',
type: 'String', type: 'string',
description: 'Filter nodes whose name starts with', description: 'Filter nodes whose name starts with',
} }
], ],
returns: { returns: {
type: ['Object'], type: ['object'],
root: true root: true
}, },
http: { http: {
@ -29,13 +31,19 @@ module.exports = Self => {
} }
}); });
Self.getLeaves = async(id, parentId = null, search) => { Self.getLeaves = async(id, parentId = null, search, options) => {
let [res] = await Self.rawSql( let myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const [res] = await Self.rawSql(
`CALL zone_getLeaves(?, ?, ?)`, `CALL zone_getLeaves(?, ?, ?)`,
[id, parentId, search] [id, parentId, search],
myOptions
); );
let map = new Map(); const map = new Map();
for (let node of res) { for (let node of res) {
if (!map.has(node.parentFk)) if (!map.has(node.parentFk))
map.set(node.parentFk, []); map.set(node.parentFk, []);
@ -50,7 +58,7 @@ module.exports = Self => {
} }
} }
let leaves = map.get(parentId); const leaves = map.get(parentId);
setLeaves(leaves); setLeaves(leaves);
return leaves || []; return leaves || [];

View File

@ -4,7 +4,7 @@ module.exports = Self => {
accessType: 'READ', accessType: 'READ',
accepts: [], accepts: [],
returns: { returns: {
type: ['Object'], type: ['object'],
root: true root: true
}, },
http: { http: {
@ -13,8 +13,13 @@ module.exports = Self => {
} }
}); });
Self.getUpcomingDeliveries = async() => { Self.getUpcomingDeliveries = async options => {
const [zones] = await Self.rawSql(`CALL vn.zone_upcomingDeliveries()`); let myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const [zones] = await Self.rawSql('CALL vn.zone_upcomingDeliveries()', null, myOptions);
const details = []; const details = [];

View File

@ -1,5 +1,4 @@
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
const mergeFilters = require('vn-loopback/util/filter').mergeFilters;
module.exports = Self => { module.exports = Self => {
Self.remoteMethodCtx('includingExpired', { Self.remoteMethodCtx('includingExpired', {
@ -19,7 +18,12 @@ module.exports = Self => {
} }
}); });
Self.includingExpired = async(ctx, filter) => { Self.includingExpired = async(ctx, filter, options) => {
let myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const userId = ctx.req.accessToken.userId; const userId = ctx.req.accessToken.userId;
const conn = Self.dataSource.connector; const conn = Self.dataSource.connector;
const models = Self.app.models; const models = Self.app.models;
@ -32,7 +36,7 @@ module.exports = Self => {
&& where.agencyModeFk && where.warehouseFk; && where.agencyModeFk && where.warehouseFk;
if (filterByAvailability) { if (filterByAvailability) {
const roles = await models.Account.getRoles(userId); const roles = await models.Account.getRoles(userId, myOptions);
const canSeeExpired = roles.filter(role => const canSeeExpired = roles.filter(role =>
role == 'productionBoss' || role == 'administrative' role == 'productionBoss' || role == 'administrative'
); );
@ -44,7 +48,10 @@ module.exports = Self => {
where.addressFk, where.addressFk,
where.agencyModeFk, where.agencyModeFk,
where.warehouseFk, where.warehouseFk,
showExpired]); showExpired
],
myOptions);
stmts.push(stmt); stmts.push(stmt);
} }
@ -54,7 +61,7 @@ module.exports = Self => {
stmt = new ParameterizedSQL( stmt = new ParameterizedSQL(
`SELECT id, name, agencyModeFk `SELECT id, name, agencyModeFk
FROM vn.zone z`); FROM vn.zone z`, null, myOptions);
if (filterByAvailability) if (filterByAvailability)
stmt.merge(`JOIN tmp.zoneGetLanded zgl ON zgl.zoneFk = z.id`); stmt.merge(`JOIN tmp.zoneGetLanded zgl ON zgl.zoneFk = z.id`);
@ -67,7 +74,7 @@ module.exports = Self => {
else stmts.push(stmt); else stmts.push(stmt);
const sql = ParameterizedSQL.join(stmts, ';'); const sql = ParameterizedSQL.join(stmts, ';');
const result = await conn.executeStmt(sql); const result = await conn.executeStmt(sql, myOptions);
return index ? result[index] : result; return index ? result[index] : result;
}; };

View File

@ -1,17 +1,20 @@
const app = require('vn-loopback/server/server'); const app = require('vn-loopback/server/server');
describe('agency clone()', () => { describe('agency clone()', () => {
let newZone;
afterAll(async done => {
await app.models.Zone.destroyById(newZone.id);
done();
});
it('should clone a zone', async() => { it('should clone a zone', async() => {
newZone = await app.models.Zone.clone(1); const tx = await app.models.Zone.beginTransaction({});
expect(newZone.name).toEqual('Zone pickup A'); try {
const options = {transaction: tx};
const newZone = await app.models.Zone.clone(1, options);
expect(newZone.name).toEqual('Zone pickup A');
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -7,30 +7,21 @@ describe('zone deletezone()', () => {
accessToken: {userId: userId}, accessToken: {userId: userId},
}; };
const ctx = {req: activeCtx}; const ctx = {req: activeCtx};
let zoneId = 9; const zoneId = 9;
let originalZone;
let originalZoneWarehouses;
let originalTickets;
let ticketIDs; let ticketIDs;
let originalZoneIncluded;
let originalTicketStates; let originalTicketStates;
let originalRoutes;
beforeAll(async done => { beforeAll(async done => {
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
active: activeCtx active: activeCtx
}); });
try { try {
originalZone = await app.models.Zone.findById(zoneId); const originalTickets = await app.models.Ticket.find({
originalZoneWarehouses = await app.models.ZoneWarehouse.findById(zoneId);
originalTickets = await app.models.Ticket.find({
where: { where: {
zoneFk: zoneId zoneFk: zoneId
} }
}); });
originalRoutes = await app.models.Route.find({where: {zoneFk: zoneId}});
ticketIDs = originalTickets.map(ticket => ticket.id); ticketIDs = originalTickets.map(ticket => ticket.id);
originalZoneIncluded = await app.models.ZoneIncluded.find({where: {zoneFk: zoneId}});
originalTicketStates = await app.models.TicketState.find({where: { originalTicketStates = await app.models.TicketState.find({where: {
ticketFk: {inq: ticketIDs}, ticketFk: {inq: ticketIDs},
code: 'FIXING'}}); code: 'FIXING'}});
@ -41,46 +32,31 @@ describe('zone deletezone()', () => {
done(); done();
}); });
afterAll(async done => {
try {
await originalZone.save();
await app.models.ZoneWarehouse.create(originalZoneWarehouses);
for (route of originalRoutes)
await route.updateAttributes({zoneFk: zoneId});
for (ticket of originalTickets)
await ticket.updateAttributes({zoneFk: zoneId});
for (zoneIncluded of originalZoneIncluded)
await zoneIncluded.save();
const fixingStateId = 1;
const trackings = await app.models.TicketTracking.find({where: {
ticketFk: {inq: ticketIDs},
stateFk: fixingStateId}});
for (let tracking of trackings)
await app.models.TicketTracking.destroyById(tracking.id);
} catch (error) {
console.error(error);
}
done();
});
it('should delete a zone and update their tickets', async() => { it('should delete a zone and update their tickets', async() => {
await app.models.Zone.deleteZone(ctx, zoneId); const tx = await app.models.Zone.beginTransaction({});
const updatedZone = await app.models.Zone.findById(zoneId); try {
const anUpdatedTicket = await app.models.Ticket.findById(ticketIDs[0]); const options = {transaction: tx};
await app.models.Zone.deleteZone(ctx, zoneId, options);
const updatedTicketStates = await app.models.TicketState.find({where: { const updatedZone = await app.models.Zone.findById(zoneId, null, options);
ticketFk: {inq: ticketIDs}, const anUpdatedTicket = await app.models.Ticket.findById(ticketIDs[0], null, options);
code: 'FIXING'}});
expect(updatedZone).toBeNull(); const updatedTicketStates = await app.models.TicketState.find({
expect(anUpdatedTicket.zoneFk).toBeNull(); where: {
expect(updatedTicketStates.length).toBeGreaterThan(originalTicketStates.length); ticketFk: {inq: ticketIDs},
code: 'FIXING'
}
}, options);
expect(updatedZone).toBeNull();
expect(anUpdatedTicket.zoneFk).toBeNull();
expect(updatedTicketStates.length).toBeGreaterThan(originalTicketStates.length);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -0,0 +1,20 @@
const app = require('vn-loopback/server/server');
describe('zone getEvents()', () => {
it('should return all events for the specified geo and agency mode', async() => {
const tx = await app.models.Zone.beginTransaction({});
try {
const options = {transaction: tx};
let result = await app.models.Zone.getEvents(20, 1, options);
expect(result.events.length).toEqual(10);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -0,0 +1,20 @@
const app = require('vn-loopback/server/server');
describe('zone getLeaves()', () => {
it('should return the country and the childs containing the search value', async() => {
const tx = await app.models.Zone.beginTransaction({});
try {
const options = {transaction: tx};
let result = await app.models.Zone.getLeaves(1, null, '46000', options);
expect(result.length).toEqual(1);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -2,15 +2,25 @@ const app = require('vn-loopback/server/server');
describe('zone getUpcomingDeliveries()', () => { describe('zone getUpcomingDeliveries()', () => {
it('should check returns data', async() => { it('should check returns data', async() => {
let result = await app.models.Zone.getUpcomingDeliveries(); const tx = await app.models.Zone.beginTransaction({});
const firstResultLines = result[0].lines; try {
const secondResultLines = result[1].lines; const options = {transaction: tx};
const thirdResultLines = result[2].lines; let result = await app.models.Zone.getUpcomingDeliveries(options);
expect(result.length).toEqual(8); const firstResultLines = result[0].lines;
expect(firstResultLines.length).toEqual(1); const secondResultLines = result[1].lines;
expect(secondResultLines.length).toEqual(1); const thirdResultLines = result[2].lines;
expect(thirdResultLines.length).toEqual(1);
expect(result.length).toEqual(8);
expect(firstResultLines.length).toEqual(1);
expect(secondResultLines.length).toEqual(1);
expect(thirdResultLines.length).toEqual(1);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -6,22 +6,45 @@ describe('zone includingExpired()', () => {
const warehouseId = 1; const warehouseId = 1;
it('should return an array containing all zones', async() => { it('should return an array containing all zones', async() => {
const tx = await app.models.Zone.beginTransaction({});
const ctx = {req: {accessToken: {userId: 1}}}; const ctx = {req: {accessToken: {userId: 1}}};
const where = {}; const where = {};
const result = await app.models.Zone.includingExpired(ctx, {where});
expect(result.length).toBeGreaterThan(2); try {
const options = {transaction: tx};
const result = await app.models.Zone.includingExpired(ctx, {where}, options);
expect(result.length).toBeGreaterThan(2);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should return an array containing zones from the agencyMode "Inhouse pickup"', async() => { it('should return an array containing zones from the agencyMode "Inhouse pickup"', async() => {
const ctx = {req: {accessToken: {userId: 1}}}; const ctx = {req: {accessToken: {userId: 1}}};
const where = {agencyModeFk: inhousePickupId}; const where = {agencyModeFk: inhousePickupId};
const result = await app.models.Zone.includingExpired(ctx, {where});
const validAgency = result.every(zone => zone.agencyModeFk = inhousePickupId); const tx = await app.models.Zone.beginTransaction({});
expect(result.length).toEqual(3); try {
expect(validAgency).toBeTruthy(); const options = {transaction: tx};
const result = await app.models.Zone.includingExpired(ctx, {where}, options);
const validAgency = result.every(zone => zone.agencyModeFk = inhousePickupId);
expect(result.length).toEqual(3);
expect(validAgency).toBeTruthy();
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should return an array containing available zones', async() => { it('should return an array containing available zones', async() => {
@ -32,9 +55,21 @@ describe('zone includingExpired()', () => {
agencyModeFk: inhousePickupId, agencyModeFk: inhousePickupId,
warehouseFk: warehouseId warehouseFk: warehouseId
}; };
const result = await app.models.Zone.includingExpired(ctx, {where});
const firstZone = result[0];
expect(firstZone.name).toEqual('Zone pickup A'); const tx = await app.models.Zone.beginTransaction({});
try {
const options = {transaction: tx};
const result = await app.models.Zone.includingExpired(ctx, {where}, options);
const firstZone = result[0];
expect(firstZone.name).toEqual('Zone pickup A');
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -0,0 +1,56 @@
const app = require('vn-loopback/server/server');
describe('zone toggleIsIncluded()', () => {
it('should return the created location with isIncluded true', async() => {
const tx = await app.models.Zone.beginTransaction({});
try {
const options = {transaction: tx};
let result = await app.models.Zone.toggleIsIncluded(1, 20, true, options);
expect(result.isIncluded).toBeTrue();
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the created location with isIncluded false', async() => {
const tx = await app.models.Zone.beginTransaction({});
try {
const options = {transaction: tx};
let result = await app.models.Zone.toggleIsIncluded(1, 20, false, options);
expect(result.isIncluded).toBeFalse();
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the amount of deleted locations', async() => {
const tx = await app.models.Zone.beginTransaction({});
try {
const options = {transaction: tx};
await app.models.Zone.toggleIsIncluded(1, 20, false, options);
let result = await app.models.Zone.toggleIsIncluded(1, 20, undefined, options);
expect(result).toEqual({count: 1});
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -7,11 +7,13 @@ module.exports = Self => {
description: 'The zone id', description: 'The zone id',
http: {source: 'path'}, http: {source: 'path'},
required: true required: true
}, { },
{
arg: 'geoId', arg: 'geoId',
type: 'Number', type: 'Number',
required: true required: true
}, { },
{
arg: 'isIncluded', arg: 'isIncluded',
type: 'Boolean' type: 'Boolean'
}], }],
@ -25,17 +27,21 @@ module.exports = Self => {
} }
}); });
Self.toggleIsIncluded = async(id, geoId, isIncluded) => { Self.toggleIsIncluded = async(id, geoId, isIncluded, options) => {
const models = Self.app.models; const models = Self.app.models;
let myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
if (isIncluded === undefined) if (isIncluded === undefined)
return models.ZoneIncluded.destroyAll({zoneFk: id, geoFk: geoId}); return models.ZoneIncluded.destroyAll({zoneFk: id, geoFk: geoId}, myOptions);
else { else {
return models.ZoneIncluded.upsert({ return models.ZoneIncluded.upsert({
zoneFk: id, zoneFk: id,
geoFk: geoId, geoFk: geoId,
isIncluded: isIncluded isIncluded: isIncluded
}); }, myOptions);
} }
}; };
}; };