3002-more_module_transactions #688

Merged
joan merged 6 commits from 3002-more_module_transactions into dev 2021-07-13 08:15:58 +00:00
112 changed files with 2951 additions and 1931 deletions

View File

@ -21,8 +21,9 @@ module.exports = Self => {
}); });
Self.removeFile = async(ctx, id, options) => { Self.removeFile = async(ctx, id, options) => {
const models = Self.app.models;
let tx; let tx;
let myOptions = {}; const myOptions = {};
if (typeof options == 'object') if (typeof options == 'object')
Object.assign(myOptions, options); Object.assign(myOptions, options);
@ -33,7 +34,6 @@ module.exports = Self => {
} }
try { try {
const models = Self.app.models;
const dms = await models.Dms.findById(id, null, myOptions); const dms = await models.Dms.findById(id, null, myOptions);
const trashDmsType = await models.DmsType.findOne({ const trashDmsType = await models.DmsType.findOne({
where: {code: 'trash'} where: {code: 'trash'}

View File

@ -12,18 +12,22 @@ module.exports = function(Self) {
} }
}); });
Self.getUserConfig = async ctx => { Self.getUserConfig = async(ctx, options) => {
const models = Self.app.models; const models = Self.app.models;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
let userConfig = await models.UserConfig.findOne({ let userConfig = await models.UserConfig.findOne({
where: {userFk: ctx.req.accessToken.userId} where: {userFk: ctx.req.accessToken.userId}
}); }, myOptions);
const companyFilter = {where: {code: 'VNL'}}; const companyFilter = {where: {code: 'VNL'}};
const company = await models.Company.findOne(companyFilter); const company = await models.Company.findOne(companyFilter, myOptions);
const warehouseFilter = {where: {code: 'ALG'}}; const warehouseFilter = {where: {code: 'ALG'}};
const warehouse = await models.Warehouse.findOne(warehouseFilter); const warehouse = await models.Warehouse.findOne(warehouseFilter, myOptions);
if (!userConfig) { if (!userConfig) {
let newConfig = { let newConfig = {
@ -32,7 +36,7 @@ module.exports = function(Self) {
userFk: ctx.req.accessToken.userId userFk: ctx.req.accessToken.userId
}; };
userConfig = await models.UserConfig.create(newConfig); userConfig = await models.UserConfig.create(newConfig, myOptions);
} }
return userConfig; return userConfig;
}; };

View File

@ -1,10 +1,21 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('userConfig getUserConfig()', () => { describe('userConfig getUserConfig()', () => {
it(`should return the configuration data of a given user`, async() => { it(`should return the configuration data of a given user`, async() => {
const result = await app.models.UserConfig.getUserConfig({req: {accessToken: {userId: 9}}}); const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
expect(result.warehouseFk).toEqual(1); try {
expect(result.companyFk).toEqual(442); const ctx = {req: {accessToken: {userId: 9}}};
const result = await models.UserConfig.getUserConfig(ctx, options);
expect(result.warehouseFk).toEqual(1);
expect(result.companyFk).toEqual(442);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -25,8 +25,9 @@ module.exports = Self => {
}); });
Self.createFromSales = async(ctx, ticketId, sales, options) => { Self.createFromSales = async(ctx, ticketId, sales, options) => {
const models = Self.app.models;
let tx; let tx;
let myOptions = {}; const myOptions = {};
if (typeof options == 'object') if (typeof options == 'object')
Object.assign(myOptions, options); Object.assign(myOptions, options);
@ -35,7 +36,6 @@ module.exports = Self => {
tx = await Self.beginTransaction({}); tx = await Self.beginTransaction({});
myOptions.transaction = tx; myOptions.transaction = tx;
} }
const models = Self.app.models;
const userId = ctx.req.accessToken.userId; const userId = ctx.req.accessToken.userId;
try { try {

View File

@ -79,10 +79,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 /^\d+$/.test(value) return /^\d+$/.test(value)
@ -111,10 +115,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 cl.id, c.name, cl.clientFk, cl.workerFk, u.name AS userName, cs.description, cl.created `SELECT cl.id, c.name, cl.clientFk, cl.workerFk, u.name AS userName, cs.description, cl.created
FROM claim cl FROM claim cl
LEFT JOIN client c ON c.id = cl.clientFk LEFT JOIN client c ON c.id = cl.clientFk
@ -124,10 +127,11 @@ 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;
const sql = ParameterizedSQL.join(stmts, ';');
const result = await conn.executeStmt(sql, myOptions);
let sql = ParameterizedSQL.join(stmts, ';');
let result = await conn.executeStmt(sql);
return itemsIndex === 0 ? result : result[itemsIndex]; return itemsIndex === 0 ? result : result[itemsIndex];
}; };
}; };

View File

@ -19,12 +19,16 @@ module.exports = Self => {
} }
}); });
Self.getSummary = async id => { Self.getSummary = async(id, options) => {
let promises = []; const myOptions = {};
let summary = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const promises = [];
const summary = {};
// Claim // Claim
let filter = { let filter = {
where: {id: id}, where: {id: id},
include: [ include: [
@ -61,13 +65,14 @@ module.exports = Self => {
] ]
}; };
promises.push(Self.app.models.Claim.find(filter)); promises.push(Self.app.models.Claim.find(filter, myOptions));
// Claim detail // Claim detail
filter = { filter = {
where: {claimFk: id}, where: {claimFk: id},
include: [ include: [
{relation: 'sale', {
relation: 'sale',
scope: { scope: {
fields: ['concept', 'ticketFk', 'price', 'quantity', 'discount', 'itemFk'], fields: ['concept', 'ticketFk', 'price', 'quantity', 'discount', 'itemFk'],
include: { include: {
@ -77,7 +82,7 @@ module.exports = Self => {
} }
] ]
}; };
promises.push(Self.app.models.ClaimBeginning.find(filter)); promises.push(Self.app.models.ClaimBeginning.find(filter, myOptions));
// Claim developments // Claim developments
filter = { filter = {
@ -109,7 +114,7 @@ module.exports = Self => {
} }
] ]
}; };
promises.push(Self.app.models.ClaimDevelopment.find(filter)); promises.push(Self.app.models.ClaimDevelopment.find(filter, myOptions));
// Claim action // Claim action
filter = { filter = {
@ -126,9 +131,9 @@ module.exports = Self => {
{relation: 'claimBeggining'} {relation: 'claimBeggining'}
] ]
}; };
promises.push(Self.app.models.ClaimEnd.find(filter)); promises.push(Self.app.models.ClaimEnd.find(filter, myOptions));
let res = await Promise.all(promises); const res = await Promise.all(promises);
[summary.claim] = res[0]; [summary.claim] = res[0];
summary.salesClaimed = res[1]; summary.salesClaimed = res[1];

View File

@ -19,15 +19,21 @@ module.exports = Self => {
} }
}); });
Self.isEditable = async(ctx, id) => { Self.isEditable = async(ctx, id, options) => {
const userId = ctx.req.accessToken.userId; const userId = ctx.req.accessToken.userId;
const isClaimManager = await Self.app.models.Account.hasRole(userId, 'claimManager'); const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const isClaimManager = await Self.app.models.Account.hasRole(userId, 'claimManager', myOptions);
const claim = await Self.app.models.Claim.findById(id, { const claim = await Self.app.models.Claim.findById(id, {
fields: ['claimStateFk'], fields: ['claimStateFk'],
include: [{ include: [{
relation: 'claimState' relation: 'claimState'
}] }]
}); }, myOptions);
const isClaimResolved = claim && claim.claimState().code == 'resolved'; const isClaimResolved = claim && claim.claimState().code == 'resolved';

View File

@ -2,26 +2,59 @@ const app = require('vn-loopback/server/server');
describe('claim filter()', () => { describe('claim filter()', () => {
it('should return 1 result filtering by id', async() => { it('should return 1 result filtering by id', async() => {
let result = await app.models.Claim.filter({args: {filter: {}, search: 1}}); const tx = await app.models.Claim.beginTransaction({});
expect(result.length).toEqual(1); try {
expect(result[0].id).toEqual(1); const options = {transaction: tx};
const result = await app.models.Claim.filter({args: {filter: {}, search: 1}}, null, options);
expect(result.length).toEqual(1);
expect(result[0].id).toEqual(1);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should return 1 result filtering by string', async() => { it('should return 1 result filtering by string', async() => {
let result = await app.models.Claim.filter({args: {filter: {}, search: 'Tony Stark'}}); const tx = await app.models.Claim.beginTransaction({});
expect(result.length).toEqual(1); try {
expect(result[0].id).toEqual(4); const options = {transaction: tx};
const result = await app.models.Claim.filter({args: {filter: {}, search: 'Tony Stark'}}, null, options);
expect(result.length).toEqual(1);
expect(result[0].id).toEqual(4);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should return 4 results filtering by worker id', async() => { it('should return 4 results filtering by worker id', async() => {
let result = await app.models.Claim.filter({args: {filter: {}, workerFk: 18}}); const tx = await app.models.Claim.beginTransaction({});
expect(result.length).toEqual(4); try {
expect(result[0].id).toEqual(1); const options = {transaction: tx};
expect(result[1].id).toEqual(2);
expect(result[2].id).toEqual(3); const result = await app.models.Claim.filter({args: {filter: {}, workerFk: 18}}, null, options);
expect(result[3].id).toEqual(4);
expect(result.length).toEqual(4);
expect(result[0].id).toEqual(1);
expect(result[1].id).toEqual(2);
expect(result[2].id).toEqual(3);
expect(result[3].id).toEqual(4);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -2,12 +2,23 @@ const app = require('vn-loopback/server/server');
describe('claim getSummary()', () => { describe('claim getSummary()', () => {
it('should return summary with claim, salesClaimed, developments and actions defined ', async() => { it('should return summary with claim, salesClaimed, developments and actions defined ', async() => {
let result = await app.models.Claim.getSummary(1); const tx = await app.models.Claim.beginTransaction({});
let keys = Object.keys(result);
expect(keys).toContain('claim'); try {
expect(keys).toContain('salesClaimed'); const options = {transaction: tx};
expect(keys).toContain('developments');
expect(keys).toContain('actions'); const result = await app.models.Claim.getSummary(1, options);
const keys = Object.keys(result);
expect(keys).toContain('claim');
expect(keys).toContain('salesClaimed');
expect(keys).toContain('developments');
expect(keys).toContain('actions');
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -4,30 +4,74 @@ describe('claim isEditable()', () => {
const salesPerdonId = 18; const salesPerdonId = 18;
const claimManagerId = 72; const claimManagerId = 72;
it('should return false if the given claim does not exist', async() => { it('should return false if the given claim does not exist', async() => {
let ctx = {req: {accessToken: {userId: claimManagerId}}}; const tx = await app.models.Claim.beginTransaction({});
let result = await app.models.Claim.isEditable(ctx, 99999);
expect(result).toEqual(false); try {
const options = {transaction: tx};
const ctx = {req: {accessToken: {userId: claimManagerId}}};
const result = await app.models.Claim.isEditable(ctx, 99999, options);
expect(result).toEqual(false);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should not be able to edit a resolved claim for a salesPerson', async() => { it('should not be able to edit a resolved claim for a salesPerson', async() => {
let ctx = {req: {accessToken: {userId: salesPerdonId}}}; const tx = await app.models.Claim.beginTransaction({});
let result = await app.models.Claim.isEditable(ctx, 4);
expect(result).toEqual(false); try {
const options = {transaction: tx};
const ctx = {req: {accessToken: {userId: salesPerdonId}}};
const result = await app.models.Claim.isEditable(ctx, 4, options);
expect(result).toEqual(false);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should be able to edit a resolved claim for a claimManager', async() => { it('should be able to edit a resolved claim for a claimManager', async() => {
let ctx = {req: {accessToken: {userId: claimManagerId}}}; const tx = await app.models.Claim.beginTransaction({});
let result = await app.models.Claim.isEditable(ctx, 4);
expect(result).toEqual(true); try {
const options = {transaction: tx};
const ctx = {req: {accessToken: {userId: claimManagerId}}};
const result = await app.models.Claim.isEditable(ctx, 4, options);
expect(result).toEqual(true);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should be able to edit a claim for a claimManager', async() => { it('should be able to edit a claim for a claimManager', async() => {
let ctx = {req: {accessToken: {userId: salesPerdonId}}}; const tx = await app.models.Claim.beginTransaction({});
let result = await app.models.Claim.isEditable(ctx, 1);
expect(result).toEqual(true); try {
const options = {transaction: tx};
const ctx = {req: {accessToken: {userId: salesPerdonId}}};
const result = await app.models.Claim.isEditable(ctx, 1, options);
expect(result).toEqual(true);
await tx.rollback();
} catch (e) {
await tx.rollback();
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 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,13 +18,33 @@ 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 clientDms = await Self.findById(id); let tx;
const myOptions = {};
await models.Dms.removeFile(ctx, clientDms.dmsFk); if (typeof options == 'object')
Object.assign(myOptions, options);
return clientDms.destroy(); if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const clientDms = await Self.findById(id, null, myOptions);
await models.Dms.removeFile(ctx, clientDms.dmsFk, myOptions);
const destroyedClient = await clientDms.destroy(myOptions);
if (tx) await tx.commit();
return destroyedClient;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
}; };
}; };

View File

@ -1,17 +1,24 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('ClientDms removeFile()', () => { describe('ClientDms removeFile()', () => {
const clientDmsFk = 3;
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.Client.beginTransaction({});
let ctx = {req: {accessToken: {userId: clientId}}};
let error; let error;
await app.models.ClientDms.removeFile(ctx, clientDmsFk).catch(e => {
try {
const options = {transaction: tx};
const clientDmsFk = 3;
const clientId = 1101;
const ctx = {req: {accessToken: {userId: clientId}}};
await models.ClientDms.removeFile(ctx, clientDmsFk, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e; error = e;
}).finally(() => { }
expect(error.message).toEqual(`You don't have enough privileges`);
});
expect(error).toBeDefined(); expect(error).toBeDefined();
}); });

View File

@ -12,7 +12,7 @@ module.exports = function(Self) {
}, },
{ {
arg: 'data', arg: 'data',
type: 'Object', type: 'object',
required: true, required: true,
description: 'data with new value', description: 'data with new value',
http: {source: 'body'} http: {source: 'body'}
@ -29,12 +29,21 @@ module.exports = function(Self) {
} }
}); });
Self.addressesPropagateRe = async(id, data) => { Self.addressesPropagateRe = async(id, data, options) => {
if (data.hasOwnProperty('isEqualizated')) { const models = Self.app.models;
let client = await Self.app.models.Client.findById(id); const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const isEqualizated = Object.prototype.hasOwnProperty.call(data, 'isEqualizated');
if (isEqualizated) {
const client = await models.Client.findById(id, null, myOptions);
if (client) { if (client) {
await Self.app.models.Address.updateAll({clientFk: id}, data); await models.Address.updateAll({clientFk: id}, data, myOptions);
await client.updateAttributes({hasToInvoiceByAddress: false}); await client.updateAttributes({hasToInvoiceByAddress: false}, myOptions);
return true; return true;
} }
} }

View File

@ -20,8 +20,15 @@ module.exports = Self => {
} }
}); });
Self.canCreateTicket = async id => { Self.canCreateTicket = async(id, options) => {
const client = await Self.app.models.Client.findById(id); const models = Self.app.models;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const client = await models.Client.findById(id, null, myOptions);
const canCreateTicket = client && client.isActive; const canCreateTicket = client && client.isActive;
if (!canCreateTicket) if (!canCreateTicket)
return false; return false;

View File

@ -9,7 +9,7 @@ module.exports = Self => {
description: 'Transaction id' description: 'Transaction id'
}], }],
returns: { returns: {
type: 'Object', type: 'object',
root: true root: true
}, },
http: { http: {
@ -18,23 +18,32 @@ module.exports = Self => {
} }
}); });
Self.confirmTransaction = async(ctx, id) => { Self.confirmTransaction = async(ctx, id, options) => {
let userId = ctx.req.accessToken.userId; const models = Self.app.models;
let tx = await Self.beginTransaction({}); const userId = ctx.req.accessToken.userId;
let tx;
const 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}; const oldTpvTransaction = await models.TpvTransaction.findById(id, null, myOptions);
let oldTpvTransaction = await Self.app.models.TpvTransaction.findById(id, null, options); const confirm = await Self.rawSql('CALL hedera.tpvTransaction_confirmById(?)', [id], myOptions);
let confirm = await Self.rawSql('CALL hedera.tpvTransaction_confirmById(?)', [id], options); const tpvTransaction = await models.TpvTransaction.findById(id, null, myOptions);
let tpvTransaction = await Self.app.models.TpvTransaction.findById(id, null, options); const oldInstance = {status: oldTpvTransaction.status};
const newInstance = {status: tpvTransaction.status};
let oldInstance = {status: oldTpvTransaction.status}; const logRecord = {
let newInstance = {status: tpvTransaction.status};
let logRecord = {
originFk: tpvTransaction.clientFk, originFk: tpvTransaction.clientFk,
userFk: userId, userFk: userId,
action: 'update', action: 'update',
@ -44,12 +53,13 @@ module.exports = Self => {
newInstance: newInstance newInstance: newInstance
}; };
await Self.app.models.ClientLog.create(logRecord, options); await models.ClientLog.create(logRecord, myOptions);
if (tx) await tx.commit();
await tx.commit();
return confirm; return confirm;
} catch (e) { } catch (e) {
await tx.rollback(); if (tx) await tx.rollback();
throw e; throw e;
} }
}; };

View File

@ -10,44 +10,52 @@ 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'
}, { },
{
arg: 'search', arg: 'search',
type: 'String', type: 'string',
description: `If it's and integer searchs by id, otherwise it searchs by name` description: `If it's and integer searchs by id, otherwise it searchs by name`
}, { },
{
arg: 'itemId', arg: 'itemId',
type: 'Number', type: 'number',
description: 'Item id' description: 'Item id'
}, { },
{
arg: 'categoryId', arg: 'categoryId',
type: 'Number', type: 'number',
description: 'Category id' description: 'Category id'
}, { },
{
arg: 'typeId', arg: 'typeId',
type: 'Number', type: 'number',
description: 'Item type id', description: 'Item type id',
}, { },
{
arg: 'buyerId', arg: 'buyerId',
type: 'Number', type: 'number',
description: 'Buyer id' description: 'Buyer id'
}, { },
{
arg: 'from', arg: 'from',
type: 'Date', type: 'date',
description: `The from date filter` description: `The from date filter`
}, { },
{
arg: 'to', arg: 'to',
type: 'Date', type: 'date',
description: `The to date filter` description: `The to date filter`
}, { },
{
arg: 'grouped', arg: 'grouped',
type: 'Boolean', type: 'boolean',
description: 'Group by item' description: 'Group by item'
} }
], ],
returns: { returns: {
type: ['Object'], type: ['object'],
root: true root: true
}, },
http: { http: {
@ -56,7 +64,12 @@ module.exports = Self => {
} }
}); });
Self.consumption = async(ctx, filter) => { Self.consumption = async(ctx, filter, options) => {
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const conn = Self.dataSource.connector; const conn = Self.dataSource.connector;
const args = ctx.args; const args = ctx.args;
const where = buildFilter(ctx.args, (param, value) => { const where = buildFilter(ctx.args, (param, value) => {
@ -83,7 +96,7 @@ module.exports = Self => {
}); });
filter = mergeFilters(filter, {where}); filter = mergeFilters(filter, {where});
let stmt = new ParameterizedSQL('SELECT'); const stmt = new ParameterizedSQL('SELECT');
if (args.grouped) if (args.grouped)
stmt.merge(`SUM(s.quantity) AS quantity,`); stmt.merge(`SUM(s.quantity) AS quantity,`);
else else
@ -121,6 +134,6 @@ module.exports = Self => {
stmt.merge(conn.makePagination(filter)); stmt.merge(conn.makePagination(filter));
return conn.executeStmt(stmt); return conn.executeStmt(stmt, myOptions);
}; };
}; };

View File

@ -62,7 +62,7 @@ module.exports = function(Self) {
}], }],
returns: { returns: {
root: true, root: true,
type: 'Object' type: 'object'
}, },
http: { http: {
verb: 'post', verb: 'post',
@ -70,18 +70,26 @@ module.exports = function(Self) {
} }
}); });
Self.createAddress = async(ctx, clientFk) => { Self.createAddress = async(ctx, clientFk, options) => {
const models = Self.app.models; const models = Self.app.models;
const args = ctx.args; const args = ctx.args;
const tx = await models.Address.beginTransaction({}); let tx;
const 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 province = await models.Province.findById(args.provinceFk, { const province = await models.Province.findById(args.provinceFk, {
include: { include: {
relation: 'country' relation: 'country'
} }
}, options); }, myOptions);
const isUeeMember = province.country().isUeeMember; const isUeeMember = province.country().isUeeMember;
if (!isUeeMember && !args.incotermsFk) if (!isUeeMember && !args.incotermsFk)
@ -91,19 +99,20 @@ module.exports = function(Self) {
throw new UserError(`Customs agent is required for a non UEE member`); throw new UserError(`Customs agent is required for a non UEE member`);
delete args.ctx; // Remove unwanted properties delete args.ctx; // Remove unwanted properties
const newAddress = await models.Address.create(args, options); const newAddress = await models.Address.create(args, myOptions);
const client = await Self.findById(clientFk, null, options); const client = await Self.findById(clientFk, null, myOptions);
if (args.isDefaultAddress) { if (args.isDefaultAddress) {
await client.updateAttributes({ await client.updateAttributes({
defaultAddressFk: newAddress.id defaultAddressFk: newAddress.id
}, options); }, myOptions);
} }
await tx.commit(); if (tx) await tx.commit();
return newAddress; return newAddress;
} catch (e) { } catch (e) {
await tx.rollback(); if (tx) await tx.rollback();
throw e; throw e;
} }
}; };

View File

@ -48,19 +48,26 @@ module.exports = function(Self) {
} }
}); });
Self.createReceipt = async ctx => { Self.createReceipt = async(ctx, options) => {
const models = Self.app.models; const models = Self.app.models;
const args = ctx.args; const args = ctx.args;
const tx = await models.Address.beginTransaction({}); let tx;
const 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};
delete args.ctx; // Remove unwanted properties delete args.ctx; // Remove unwanted properties
const newReceipt = await models.Receipt.create(args, options); const newReceipt = await models.Receipt.create(args, myOptions);
const clientOriginal = await models.Client.findById(args.clientFk); const originalClient = await models.Client.findById(args.clientFk, null, myOptions);
const bank = await models.Bank.findById(args.bankFk); const bank = await models.Bank.findById(args.bankFk, null, myOptions);
const accountingType = await models.AccountingType.findById(bank.accountingTypeFk); const accountingType = await models.AccountingType.findById(bank.accountingTypeFk, null, myOptions);
if (accountingType.code == 'compensation') { if (accountingType.code == 'compensation') {
if (!args.compensationAccount) if (!args.compensationAccount)
@ -70,14 +77,16 @@ module.exports = function(Self) {
where: { where: {
account: args.compensationAccount account: args.compensationAccount
} }
}); }, myOptions);
let clientCompensation = {}; let clientCompensation = {};
if (!supplierCompensation) { if (!supplierCompensation) {
clientCompensation = await models.Client.findOne({ clientCompensation = await models.Client.findOne({
where: { where: {
accountingAccount: args.compensationAccount accountingAccount: args.compensationAccount
} }
}); }, myOptions);
} }
if (!supplierCompensation && !clientCompensation) if (!supplierCompensation && !clientCompensation)
throw new UserError('Invalid account'); throw new UserError('Invalid account');
@ -87,20 +96,21 @@ module.exports = function(Self) {
[ [
args.compensationAccount, args.compensationAccount,
args.bankFk, args.bankFk,
accountingType.receiptDescription + clientOriginal.accountingAccount, accountingType.receiptDescription + originalClient.accountingAccount,
args.amountPaid, args.amountPaid,
args.companyFk, args.companyFk,
clientOriginal.accountingAccount originalClient.accountingAccount
], ],
options); myOptions
);
} else if (accountingType.isAutoConciliated == true) { } else if (accountingType.isAutoConciliated == true) {
const description = `${clientOriginal.id} : ${clientOriginal.socialName} - ${accountingType.receiptDescription}`; const description = `${originalClient.id} : ${originalClient.socialName} - ${accountingType.receiptDescription}`;
const [xdiarioNew] = await Self.rawSql( const [xdiarioNew] = await Self.rawSql(
`SELECT xdiario_new(?, CURDATE(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ledger;`, `SELECT xdiario_new(?, CURDATE(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ledger;`,
[ [
null, null,
bank.account, bank.account,
clientOriginal.accountingAccount, originalClient.accountingAccount,
description, description,
args.amountPaid, args.amountPaid,
0, 0,
@ -112,13 +122,14 @@ module.exports = function(Self) {
false, false,
args.companyFk args.companyFk
], ],
options); myOptions
);
await Self.rawSql( await Self.rawSql(
`SELECT xdiario_new(?, CURDATE(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);`, `SELECT xdiario_new(?, CURDATE(), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);`,
[ [
xdiarioNew.ledger, xdiarioNew.ledger,
clientOriginal.accountingAccount, originalClient.accountingAccount,
bank.account, bank.account,
description, description,
0, 0,
@ -131,13 +142,15 @@ module.exports = function(Self) {
false, false,
args.companyFk args.companyFk
], ],
options); myOptions
);
} }
await tx.commit(); if (tx) await tx.commit();
return newReceipt; return newReceipt;
} catch (e) { } catch (e) {
await tx.rollback(); if (tx) await tx.rollback();
throw e; throw e;
} }
}; };

View File

@ -16,22 +16,29 @@ module.exports = function(Self) {
} }
}); });
Self.createWithUser = async data => { Self.createWithUser = async(data, options) => {
let firstEmail = data.email ? data.email.split(',')[0] : null; const models = Self.app.models;
let user = { let tx;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
const firstEmail = data.email ? data.email.split(',')[0] : null;
const user = {
name: data.userName, name: data.userName,
email: firstEmail, email: firstEmail,
password: parseInt(Math.random() * 100000000000000) password: parseInt(Math.random() * 100000000000000)
}; };
const Account = Self.app.models.Account;
const Address = Self.app.models.Address;
const tx = await Account.beginTransaction({});
try { try {
let options = {transaction: tx}; const account = await models.Account.create(user, myOptions);
const client = await Self.create({
let account = await Account.create(user, options);
let client = await Self.create({
id: account.id, id: account.id,
name: data.name, name: data.name,
fi: data.fi, fi: data.fi,
@ -44,9 +51,9 @@ module.exports = function(Self) {
provinceFk: data.provinceFk, provinceFk: data.provinceFk,
countryFk: data.countryFk, countryFk: data.countryFk,
isEqualizated: data.isEqualizated isEqualizated: data.isEqualizated
}, options); }, myOptions);
let address = await Address.create({ const address = await models.Address.create({
clientFk: client.id, clientFk: client.id,
nickname: client.name, nickname: client.name,
city: client.city, city: client.city,
@ -55,16 +62,17 @@ module.exports = function(Self) {
provinceFk: client.provinceFk, provinceFk: client.provinceFk,
isEqualizated: client.isEqualizated, isEqualizated: client.isEqualizated,
isActive: true isActive: true
}, options); }, myOptions);
await client.updateAttributes({ await client.updateAttributes({
defaultAddressFk: address.id defaultAddressFk: address.id
}, options); }, myOptions);
if (tx) await tx.commit();
await tx.commit();
return client; return client;
} catch (e) { } catch (e) {
await tx.rollback(); if (tx) await tx.rollback();
throw e; throw e;
} }
}; };

View File

@ -19,9 +19,14 @@ module.exports = Self => {
} }
}); });
Self.getAverageInvoiced = async clientFk => { Self.getAverageInvoiced = async(clientFk, options) => {
let query = `SELECT invoiced FROM vn.annualAverageInvoiced WHERE clientFk = ?`; const myOptions = {};
let [invoiced] = await Self.rawSql(query, [clientFk]);
if (typeof options == 'object')
Object.assign(myOptions, options);
const query = `SELECT invoiced FROM vn.annualAverageInvoiced WHERE clientFk = ?`;
const [invoiced] = await Self.rawSql(query, [clientFk], myOptions);
return invoiced; return invoiced;
}; };

View File

@ -9,7 +9,7 @@ module.exports = function(Self) {
http: {source: 'path'} http: {source: 'path'}
}, },
returns: { returns: {
type: 'Object', type: 'object',
root: true root: true
}, },
http: { http: {
@ -18,8 +18,13 @@ module.exports = function(Self) {
} }
}); });
Self.getCard = async function(id) { Self.getCard = async(id, options) => {
let client = await Self.findOne({ const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const client = await Self.findOne({
where: { where: {
id: id id: id
}, },
@ -29,38 +34,44 @@ module.exports = function(Self) {
scope: { scope: {
fields: ['id', 'name'] fields: ['id', 'name']
} }
}, { },
{
relation: 'province', relation: 'province',
scope: { scope: {
fields: ['id', 'name'] fields: ['id', 'name']
} }
}, { },
}, { {
relation: 'salesPersonUser', relation: 'salesPersonUser',
scope: { scope: {
fields: ['id', 'name'] fields: ['id', 'name']
} }
}, { },
{
relation: 'country', relation: 'country',
scope: { scope: {
fields: ['id', 'country'] fields: ['id', 'country']
} }
}, { },
{
relation: 'payMethod', relation: 'payMethod',
scope: { scope: {
fields: ['id', 'name'] fields: ['id', 'name']
} }
}, { },
{
relation: 'account', relation: 'account',
scope: { scope: {
fields: ['id', 'name', 'active'] fields: ['id', 'name', 'active']
} }
} }
] ]
}); }, myOptions);
let query = `SELECT vn.clientGetDebt(?, CURDATE()) AS debt`; const query = `SELECT vn.clientGetDebt(?, CURDATE()) AS debt`;
client.debt = (await Self.rawSql(query, [id]))[0].debt; const data = await Self.rawSql(query, [id], myOptions);
client.debt = data[0].debt;
return client; return client;
}; };

View File

@ -19,9 +19,14 @@ module.exports = Self => {
} }
}); });
Self.getDebt = async clientFk => { Self.getDebt = async(clientFk, options) => {
let query = `SELECT vn.clientGetDebt(?, CURDATE()) AS debt`; const myOptions = {};
let [debt] = await Self.rawSql(query, [clientFk]);
if (typeof options == 'object')
Object.assign(myOptions, options);
const query = `SELECT vn.clientGetDebt(?, CURDATE()) AS debt`;
const [debt] = await Self.rawSql(query, [clientFk], myOptions);
return debt; return debt;
}; };

View File

@ -19,9 +19,14 @@ module.exports = Self => {
} }
}); });
Self.getMana = async clientFk => { Self.getMana = async(clientFk, options) => {
let query = `SELECT vn.clientGetMana(?) AS mana`; const myOptions = {};
let [mana] = await Self.rawSql(query, [clientFk]);
if (typeof options == 'object')
Object.assign(myOptions, options);
const query = `SELECT vn.clientGetMana(?) AS mana`;
const [mana] = await Self.rawSql(query, [clientFk], myOptions);
return mana; return mana;
}; };

View File

@ -7,12 +7,12 @@ module.exports = Self => {
accessType: 'READ', accessType: 'READ',
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: {
@ -21,9 +21,14 @@ module.exports = Self => {
} }
}); });
Self.getTransactions = async filter => { Self.getTransactions = async(filter, options) => {
let conn = Self.dataSource.connector; const myOptions = {};
let stmt = new ParameterizedSQL(`
if (typeof options == 'object')
Object.assign(myOptions, options);
const conn = Self.dataSource.connector;
const stmt = new ParameterizedSQL(`
SELECT SELECT
t.id, t.id,
t.clientFk, t.clientFk,
@ -39,6 +44,6 @@ module.exports = Self => {
stmt.merge(conn.makeSuffix(filter, 't')); stmt.merge(conn.makeSuffix(filter, 't'));
return await Self.rawStmt(stmt); return Self.rawStmt(stmt, myOptions);
}; };
}; };

View File

@ -2,23 +2,13 @@ module.exports = Self => {
Self.remoteMethod('hasCustomerRole', { Self.remoteMethod('hasCustomerRole', {
description: 'Comprueba si un usuario tiene el rol de cliente', description: 'Comprueba si un usuario tiene el rol de cliente',
accessType: 'READ', accessType: 'READ',
accepts: [ accepts: [{
{ arg: 'id',
arg: 'id', type: 'string',
type: 'string', required: true,
required: true, description: 'The user id',
description: 'The user id', http: {source: 'path'}
http: {source: 'path'} }],
}, {
arg: 'context',
type: 'object',
required: true,
description: 'Filter defining where',
http: function(context) {
return context.req.query;
}
}
],
returns: { returns: {
type: 'boolean', type: 'boolean',
root: true root: true
@ -29,17 +19,19 @@ module.exports = Self => {
} }
}); });
Self.hasCustomerRole = (id, context, callback) => { Self.hasCustomerRole = (id, options) => {
let query = ` const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const query = `
SELECT COUNT(*) > 0 isCustomer SELECT COUNT(*) > 0 isCustomer
FROM salix.Account A FROM salix.Account A
JOIN salix.Role r ON r.id = A.roleFK JOIN salix.Role r ON r.id = A.roleFK
WHERE r.name = 'customer' WHERE r.name = 'customer'
AND A.id IN (?)`; AND A.id IN (?)`;
Self.rawSql(query, [id]).then( return Self.rawSql(query, [id], myOptions);
instances => callback(null, instances[0]),
err => callback(err)
);
}; };
}; };

View File

@ -9,14 +9,6 @@ module.exports = Self => {
required: true, required: true,
description: 'The user id', description: 'The user id',
http: {source: 'path'} http: {source: 'path'}
}, {
arg: 'context',
type: 'object',
required: true,
description: 'Filter defining where',
http: function(context) {
return context.req.query;
}
} }
], ],
returns: { returns: {
@ -29,8 +21,13 @@ module.exports = Self => {
} }
}); });
Self.isValidClient = async id => { Self.isValidClient = async(id, options) => {
let query = ` const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const query = `
SELECT r.name SELECT r.name
FROM salix.Account a FROM salix.Account a
JOIN vn.client c ON a.id = c.id JOIN vn.client c ON a.id = c.id
@ -38,9 +35,9 @@ module.exports = Self => {
JOIN salix.Role r ON r.id = rm.roleId JOIN salix.Role r ON r.id = rm.roleId
WHERE a.id = ? AND c.isActive AND c.isTaxDataChecked`; WHERE a.id = ? AND c.isActive AND c.isTaxDataChecked`;
let roleNames = await Self.rawSql(query, [id]); const roleNames = await Self.rawSql(query, [id], myOptions);
let isEmployee = roleNames.findIndex(role => { const isEmployee = roleNames.findIndex(role => {
return role.name === 'employee'; return role.name === 'employee';
}); });

View File

@ -2,19 +2,22 @@ module.exports = Self => {
Self.remoteMethod('lastActiveTickets', { Self.remoteMethod('lastActiveTickets', {
description: 'Returns the last three active tickets of a client', description: 'Returns the last three active tickets of a client',
accessType: 'READ', accessType: 'READ',
accepts: [{ accepts: [
arg: 'id', {
type: 'Number', arg: 'id',
required: true, type: 'number',
description: 'Client id', required: true,
http: {source: 'path'} description: 'Client id',
}, { http: {source: 'path'}
arg: 'ticketId', },
type: 'Number', {
required: true arg: 'ticketId',
}], type: 'number',
required: true
}
],
returns: { returns: {
type: ['Object'], type: ['object'],
root: true root: true
}, },
http: { http: {
@ -23,8 +26,13 @@ module.exports = Self => {
} }
}); });
Self.lastActiveTickets = async(id, ticketId) => { Self.lastActiveTickets = async(id, ticketId, options) => {
const ticket = await Self.app.models.Ticket.findById(ticketId); const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const ticket = await Self.app.models.Ticket.findById(ticketId, null, myOptions);
const query = ` const query = `
SELECT SELECT
t.id, t.id,
@ -47,7 +55,7 @@ module.exports = Self => {
ORDER BY t.shipped ORDER BY t.shipped
LIMIT 10`; LIMIT 10`;
return Self.rawSql(query, [id, ticketId, ticket.warehouseFk]); return Self.rawSql(query, [id, ticketId, ticket.warehouseFk], myOptions);
}; };
}; };

View File

@ -5,23 +5,23 @@ module.exports = Self => {
accessType: 'WRITE', accessType: 'WRITE',
accepts: [{ accepts: [{
arg: 'id', arg: 'id',
type: 'Number', type: 'number',
required: true, required: true,
description: 'The ticket id', description: 'The ticket id',
http: {source: 'path'} http: {source: 'path'}
}, },
{ {
arg: 'destination', arg: 'destination',
type: 'String', type: 'string',
required: true, required: true,
}, },
{ {
arg: 'message', arg: 'message',
type: 'String', type: 'string',
required: true, required: true,
}], }],
returns: { returns: {
type: 'Object', type: 'object',
root: true root: true
}, },
http: { http: {
@ -30,11 +30,17 @@ module.exports = Self => {
} }
}); });
Self.sendSms = async(ctx, id, destination, message) => { Self.sendSms = async(ctx, id, destination, message, options) => {
const models = Self.app.models;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const userId = ctx.req.accessToken.userId; const userId = ctx.req.accessToken.userId;
let sms = await Self.app.models.Sms.send(ctx, id, destination, message); const sms = await models.Sms.send(ctx, id, destination, message);
let logRecord = { const logRecord = {
originFk: id, originFk: id,
userFk: userId, userFk: userId,
action: 'insert', action: 'insert',
@ -48,7 +54,7 @@ module.exports = Self => {
} }
}; };
const clientLog = await Self.app.models.ClientLog.create(logRecord); const clientLog = await models.ClientLog.create(logRecord, myOptions);
sms.logId = clientLog.id; sms.logId = clientLog.id;

View File

@ -1,40 +1,30 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('Client addressesPropagateRe', () => { describe('Client addressesPropagateRe', () => {
let client;
beforeEach(async() => {
client = await app.models.Client.findById(1101);
await app.models.Address.update({clientFk: 1101}, {isEqualizated: false});
await client.updateAttributes({hasToInvoiceByAddress: true});
});
afterAll(async done => {
await app.models.Address.update({clientFk: 1101}, {isEqualizated: false});
await client.updateAttributes({hasToInvoiceByAddress: true});
done();
});
it('should propagate the isEqualizated on both addresses of Mr Wayne and set hasToInvoiceByAddress to false', async() => { it('should propagate the isEqualizated on both addresses of Mr Wayne and set hasToInvoiceByAddress to false', async() => {
let id = 1101; const tx = await models.Client.beginTransaction({});
let data = {
isEqualizated: true
};
let resultAddress = await app.models.Address.find({where: {clientFk: id}}); try {
let resultClient = await app.models.Client.find({where: {id: id}}); const options = {transaction: tx};
expect(resultAddress[0].isEqualizated).toBeFalsy(); let id = 1101;
expect(resultAddress[1].isEqualizated).toBeFalsy(); let data = {
expect(resultClient[0].hasToInvoiceByAddress).toBeTruthy(); isEqualizated: true
};
await app.models.Client.addressesPropagateRe(id, data); await models.Client.addressesPropagateRe(id, data, options);
resultAddress = await app.models.Address.find({where: {clientFk: id}}); const addresses = await models.Address.find({where: {clientFk: id}}, options);
resultClient = await app.models.Client.find({where: {id: id}}); const client = await models.Client.findById(id, null, options);
expect(resultAddress[0].isEqualizated).toBeTruthy(); expect(addresses[0].isEqualizated).toBeTruthy();
expect(resultAddress[1].isEqualizated).toBeTruthy(); expect(addresses[1].isEqualizated).toBeTruthy();
expect(resultClient[0].hasToInvoiceByAddress).toBeFalsy(); expect(client.hasToInvoiceByAddress).toBeFalsy();
await tx.rollback();
} catch (e) {
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'); const LoopBackContext = require('loopback-context');
describe('client canBeInvoiced()', () => { describe('client canBeInvoiced()', () => {
@ -7,7 +7,6 @@ describe('client canBeInvoiced()', () => {
const activeCtx = { const activeCtx = {
accessToken: {userId: userId} accessToken: {userId: userId}
}; };
const models = app.models;
beforeAll(async done => { beforeAll(async done => {
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
@ -18,7 +17,7 @@ describe('client canBeInvoiced()', () => {
}); });
it('should return falsy for a client without the data checked', async() => { it('should return falsy for a client without the data checked', async() => {
const tx = await models.Ticket.beginTransaction({}); const tx = await models.Client.beginTransaction({});
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
@ -37,7 +36,7 @@ describe('client canBeInvoiced()', () => {
}); });
it('should return falsy for a client with invoicing disabled', async() => { it('should return falsy for a client with invoicing disabled', async() => {
const tx = await models.Ticket.beginTransaction({}); const tx = await models.Client.beginTransaction({});
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
@ -56,8 +55,18 @@ describe('client canBeInvoiced()', () => {
}); });
it('should return truthy for an invoiceable client', async() => { it('should return truthy for an invoiceable client', async() => {
const canBeInvoiced = await models.Client.canBeInvoiced(clientId); const tx = await models.Client.beginTransaction({});
expect(canBeInvoiced).toEqual(true); try {
const options = {transaction: tx};
const canBeInvoiced = await models.Client.canBeInvoiced(clientId, options);
expect(canBeInvoiced).toEqual(true);
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
}); });

View File

@ -1,17 +1,37 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('Client canCreateTicket', () => { describe('Client canCreateTicket', () => {
it('should receive true if the client is active', async() => { it('should receive true if the client is active', async() => {
let id = 1105; const tx = await models.Client.beginTransaction({});
let canCreateTicket = await app.models.Client.canCreateTicket(id);
expect(canCreateTicket).toBeTruthy(); try {
const options = {transaction: tx};
const id = 1105;
const canCreateTicket = await models.Client.canCreateTicket(id, null, options);
expect(canCreateTicket).toBeTruthy();
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
it(`should receive false if the client isn't active`, async() => { it(`should receive false if the client isn't active`, async() => {
let id = 1106; const tx = await models.Client.beginTransaction({});
let canCreateTicket = await app.models.Client.canCreateTicket(id);
expect(canCreateTicket).toBe(false); try {
const options = {transaction: tx};
const id = 1106;
const canCreateTicket = await models.Client.canCreateTicket(id, null, options);
expect(canCreateTicket).toBe(false);
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
}); });

View File

@ -1,24 +1,26 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('Client confirmTransaction', () => { describe('Client confirmTransaction', () => {
const transactionId = 2;
afterAll(async done => {
await app.models.Client.rawSql(`
CALL hedera.tpvTransaction_undo(?)`, [transactionId]);
done();
});
it('should call confirmTransaction() method to mark transaction as confirmed', async() => { it('should call confirmTransaction() method to mark transaction as confirmed', async() => {
let ctx = {req: {accessToken: {userId: 1}}}; const tx = await models.Client.beginTransaction({});
await app.models.Client.confirmTransaction(ctx, transactionId); const transactionId = 2;
let [receipt] = await app.models.Client.rawSql( try {
`SELECT receiptFk const options = {transaction: tx};
FROM hedera.tpvTransaction
WHERE id = ?`, [transactionId]);
expect(receipt.receiptFk).toBeGreaterThan(0); let ctx = {req: {accessToken: {userId: 1}}};
await models.Client.confirmTransaction(ctx, transactionId, options);
let [receipt] = await models.Client.rawSql(
`SELECT receiptFk
FROM hedera.tpvTransaction
WHERE id = ?`, [transactionId], options);
expect(receipt.receiptFk).toBeGreaterThan(0);
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
}); });

View File

@ -1,60 +1,90 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('client consumption() filter', () => { describe('client consumption() filter', () => {
it('should return a list of buyed items by ticket', async() => { it('should return a list of buyed items by ticket', async() => {
const ctx = {req: {accessToken: {userId: 9}}, args: {}}; const tx = await models.Client.beginTransaction({});
const filter = {
where: {
clientFk: 1101
},
order: 'itemTypeFk, itemName, itemSize'
};
const result = await app.models.Client.consumption(ctx, filter);
expect(result.length).toEqual(10); try {
const options = {transaction: tx};
const ctx = {req: {accessToken: {userId: 9}}, args: {}};
const filter = {
where: {
clientFk: 1101
},
order: 'itemTypeFk, itemName, itemSize'
};
const result = await app.models.Client.consumption(ctx, filter, options);
expect(result.length).toEqual(10);
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
it('should return a list of tickets grouped by item', async() => { it('should return a list of tickets grouped by item', async() => {
const ctx = {req: {accessToken: {userId: 9}}, const tx = await models.Client.beginTransaction({});
args: {
grouped: true
}
};
const filter = {
where: {
clientFk: 1101
},
order: 'itemFk'
};
const result = await app.models.Client.consumption(ctx, filter);
const firstRow = result[0]; try {
const secondRow = result[1]; const options = {transaction: tx};
const thirdRow = result[2];
expect(result.length).toEqual(3); const ctx = {req: {accessToken: {userId: 9}},
expect(firstRow.quantity).toEqual(10); args: {
expect(secondRow.quantity).toEqual(15); grouped: true
expect(thirdRow.quantity).toEqual(20); }
};
const filter = {
where: {
clientFk: 1101
},
order: 'itemFk'
};
const result = await app.models.Client.consumption(ctx, filter, options);
const firstRow = result[0];
const secondRow = result[1];
const thirdRow = result[2];
expect(result.length).toEqual(3);
expect(firstRow.quantity).toEqual(10);
expect(secondRow.quantity).toEqual(15);
expect(thirdRow.quantity).toEqual(20);
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
it('should return a list of tickets from the item id 4', async() => { it('should return a list of tickets from the item id 4', async() => {
const ctx = {req: {accessToken: {userId: 9}}, const tx = await models.Client.beginTransaction({});
args: {
itemId: 4
}
};
const filter = {
where: {
clientFk: 1101
},
order: 'itemTypeFk, itemName, itemSize'
};
const result = await app.models.Client.consumption(ctx, filter);
const expectedItemId = 4; try {
const firstRow = result[0]; const options = {transaction: tx};
expect(firstRow.itemFk).toEqual(expectedItemId); const ctx = {req: {accessToken: {userId: 9}},
args: {
itemId: 4
}
};
const filter = {
where: {
clientFk: 1101
},
order: 'itemTypeFk, itemName, itemSize'
};
const result = await app.models.Client.consumption(ctx, filter, options);
const expectedItemId = 4;
const firstRow = result[0];
expect(firstRow.itemFk).toEqual(expectedItemId);
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
}); });

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('Address createAddress', () => { describe('Address createAddress', () => {
const clientFk = 1101; const clientFk = 1101;
@ -7,107 +7,131 @@ describe('Address createAddress', () => {
const customAgentOneId = 1; const customAgentOneId = 1;
it('should throw a non uee member error if no incoterms is defined', async() => { it('should throw a non uee member error if no incoterms is defined', async() => {
const expectedResult = 'My edited address'; const tx = await models.Client.beginTransaction({});
const ctx = {
args: { let error;
provinceFk: provinceFk,
nickname: expectedResult,
street: 'Wall Street',
city: 'New York',
customsAgentFk: customAgentOneId
}
};
try { try {
await app.models.Client.createAddress(ctx, clientFk); const options = {transaction: tx};
const expectedResult = 'My edited address';
const ctx = {
args: {
provinceFk: provinceFk,
nickname: expectedResult,
street: 'Wall Street',
city: 'New York',
customsAgentFk: customAgentOneId
}
};
await models.Client.createAddress(ctx, clientFk, options);
await tx.rollback();
} catch (e) { } catch (e) {
err = e; await tx.rollback();
error = e;
} }
expect(err).toBeDefined(); expect(error).toBeDefined();
expect(err.message).toEqual('Incoterms is required for a non UEE member'); expect(error.message).toEqual('Incoterms is required for a non UEE member');
}); });
it('should throw a non uee member error if no customsAgent is defined', async() => { it('should throw a non uee member error if no customsAgent is defined', async() => {
const expectedResult = 'My edited address'; const tx = await models.Client.beginTransaction({});
const ctx = {
args: { let error;
provinceFk: provinceFk,
nickname: expectedResult,
street: 'Wall Street',
city: 'New York',
incotermsFk: incotermsFk
}
};
try { try {
await app.models.Client.createAddress(ctx, clientFk); const options = {transaction: tx};
const expectedResult = 'My edited address';
const ctx = {
args: {
provinceFk: provinceFk,
nickname: expectedResult,
street: 'Wall Street',
city: 'New York',
incotermsFk: incotermsFk
}
};
await models.Client.createAddress(ctx, clientFk, options);
await tx.rollback();
} catch (e) { } catch (e) {
err = e; await tx.rollback();
error = e;
} }
expect(err).toBeDefined(); expect(error).toBeDefined();
expect(err.message).toEqual('Customs agent is required for a non UEE member'); expect(error.message).toEqual('Customs agent is required for a non UEE member');
});
it('should verify that client defaultAddressFk is untainted', async() => {
const client = await app.models.Client.findById(clientFk);
expect(client.defaultAddressFk).toEqual(1);
}); });
it('should create a new address and set as a client default address', async() => { it('should create a new address and set as a client default address', async() => {
const ctx = { const tx = await models.Client.beginTransaction({});
args: {
clientFk: 1101,
provinceFk: 1,
nickname: 'My address',
street: 'Wall Street',
city: 'New York',
phone: 678678678,
mobile: 678678678,
postalCode: 46680,
agencyModeFk: 1,
incotermsFk: incotermsFk,
customsAgentFk: customAgentOneId,
isDefaultAddress: true
}
};
const address = await app.models.Client.createAddress(ctx, clientFk); try {
const client = await app.models.Client.findById(clientFk); const options = {transaction: tx};
expect(client.defaultAddressFk).toEqual(address.id); const ctx = {
args: {
clientFk: 1101,
provinceFk: 1,
nickname: 'My address',
street: 'Wall Street',
city: 'New York',
phone: 678678678,
mobile: 678678678,
postalCode: 46680,
agencyModeFk: 1,
incotermsFk: incotermsFk,
customsAgentFk: customAgentOneId,
isDefaultAddress: true
}
};
// restores const address = await models.Client.createAddress(ctx, clientFk, options);
await client.updateAttributes({defaultAddressFk: 1}); const client = await models.Client.findById(clientFk, null, options);
await address.destroy();
expect(client.defaultAddressFk).toEqual(address.id);
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
it('should create a new address and set all properties', async() => { it('should create a new address and set all properties', async() => {
const ctx = { const tx = await models.Client.beginTransaction({});
args: {
clientFk: 1101,
provinceFk: 1,
nickname: 'My address',
street: 'Wall Street',
city: 'New York',
phone: '678678678',
mobile: '678678678',
postalCode: '46680',
agencyModeFk: 1,
incotermsFk: incotermsFk,
customsAgentFk: customAgentOneId,
isDefaultAddress: true
}
};
address = await app.models.Client.createAddress(ctx, clientFk); try {
const options = {transaction: tx};
expect(address).toEqual(jasmine.objectContaining(ctx.args)); const ctx = {
// restores args: {
const client = await app.models.Client.findById(clientFk); clientFk: 1101,
await client.updateAttributes({defaultAddressFk: 1}); provinceFk: 1,
await address.destroy(); nickname: 'My address',
street: 'Wall Street',
city: 'New York',
phone: '678678678',
mobile: '678678678',
postalCode: '46680',
agencyModeFk: 1,
incotermsFk: incotermsFk,
customsAgentFk: customAgentOneId,
isDefaultAddress: true
}
};
address = await models.Client.createAddress(ctx, clientFk, options);
expect(address).toEqual(jasmine.objectContaining(ctx.args));
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
}); });

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'); const LoopBackContext = require('loopback-context');
describe('Client createReceipt', () => { describe('Client createReceipt', () => {
@ -27,49 +27,55 @@ describe('Client createReceipt', () => {
}); });
it('should create a new receipt', async() => { it('should create a new receipt', async() => {
const bankFk = 1; const tx = await models.Client.beginTransaction({});
ctx.args = {
clientFk: clientFk,
payed: payed,
companyFk: companyFk,
bankFk: bankFk,
amountPaid: amountPaid,
description: description
};
const receipt = await app.models.Client.createReceipt(ctx); try {
delete ctx.args.payed; const options = {transaction: tx};
const till = await app.models.Till.findOne({ const bankFk = 1;
where: { ctx.args = {
clientFk: clientFk,
payed: payed,
companyFk: companyFk,
bankFk: bankFk, bankFk: bankFk,
in: amountPaid, amountPaid: amountPaid,
number: clientFk description: description
} };
});
expect(receipt).toEqual(jasmine.objectContaining(ctx.args)); const receipt = await models.Client.createReceipt(ctx, options);
delete ctx.args.payed;
// restores expect(receipt).toEqual(jasmine.objectContaining(ctx.args));
await receipt.destroy();
await till.destroy(); await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
it('should throw Compensation account is empty', async() => { it('should throw Compensation account is empty', async() => {
const bankFk = 3; const tx = await models.Client.beginTransaction({});
ctx.args = { let error;
clientFk: clientFk,
payed: payed,
companyFk: companyFk,
bankFk: bankFk,
amountPaid: amountPaid,
description: description
};
try { try {
await app.models.Client.createReceipt(ctx); const options = {transaction: tx};
const bankFk = 3;
ctx.args = {
clientFk: clientFk,
payed: payed,
companyFk: companyFk,
bankFk: bankFk,
amountPaid: amountPaid,
description: description
};
await models.Client.createReceipt(ctx, options);
await tx.rollback();
} catch (e) { } catch (e) {
await tx.rollback();
error = e; error = e;
} }
@ -78,21 +84,29 @@ describe('Client createReceipt', () => {
}); });
it('should throw Invalid account if compensationAccount does not belongs to a client nor a supplier', async() => { it('should throw Invalid account if compensationAccount does not belongs to a client nor a supplier', async() => {
const tx = await models.Client.beginTransaction({});
let error; let error;
const bankFk = 3;
ctx.args = {
clientFk: clientFk,
payed: payed,
companyFk: companyFk,
bankFk: bankFk,
amountPaid: amountPaid,
description: description,
compensationAccount: 'non existing account'
};
try { try {
await app.models.Client.createReceipt(ctx); const options = {transaction: tx};
const bankFk = 3;
ctx.args = {
clientFk: clientFk,
payed: payed,
companyFk: companyFk,
bankFk: bankFk,
amountPaid: amountPaid,
description: description,
compensationAccount: 'non existing account'
};
await models.Client.createReceipt(ctx, options);
await tx.rollback();
} catch (e) { } catch (e) {
await tx.rollback();
error = e; error = e;
} }
@ -101,84 +115,78 @@ describe('Client createReceipt', () => {
}); });
it('should create a new receipt with a compensation for a client', async() => { it('should create a new receipt with a compensation for a client', async() => {
const bankFk = 3; const tx = await models.Client.beginTransaction({});
ctx.args = { try {
clientFk: clientFk, const options = {transaction: tx};
payed: payed,
companyFk: companyFk,
bankFk: bankFk,
amountPaid: amountPaid,
description: description,
compensationAccount: '4300000001'
};
const receipt = await app.models.Client.createReceipt(ctx);
const receiptCompensated = await app.models.Receipt.findOne({
where: {
clientFk: 1,
bankFk: ctx.args.bankFk
}
});
const till = await app.models.Till.findOne({ const bankFk = 3;
where: {
ctx.args = {
clientFk: clientFk,
payed: payed,
companyFk: companyFk,
bankFk: bankFk, bankFk: bankFk,
in: amountPaid, amountPaid: amountPaid,
number: clientFk description: description,
} compensationAccount: '4300000001'
}); };
const receipt = await models.Client.createReceipt(ctx, options);
const receiptCompensated = await models.Receipt.findOne({
where: {
clientFk: 1,
bankFk: ctx.args.bankFk
}
}, options);
delete ctx.args.payed; delete ctx.args.payed;
expect(receipt).toEqual(jasmine.objectContaining(ctx.args)); expect(receipt).toEqual(jasmine.objectContaining(ctx.args));
expect(receipt.amountPaid).toEqual(-receiptCompensated.amountPaid); expect(receipt.amountPaid).toEqual(-receiptCompensated.amountPaid);
// restores await tx.rollback();
await receipt.destroy(); } catch (e) {
await receiptCompensated.destroy(); await tx.rollback();
await till.destroy(); }
}); });
it('should create a new receipt with a compensation for a supplier', async() => { it('should create a new receipt with a compensation for a supplier', async() => {
const bankFk = 3; const tx = await models.Client.beginTransaction({});
ctx.args = { try {
clientFk: clientFk, const options = {transaction: tx};
payed: payed,
companyFk: companyFk,
bankFk: bankFk,
amountPaid: amountPaid,
description: description,
compensationAccount: '4100000001'
};
const receipt = await app.models.Client.createReceipt(ctx);
const paymentCompensated = await app.models.Payment.findOne({ const bankFk = 3;
where: {
clientFk: ctx.args.sale,
payed: ctx.args.payed,
amountPaid: ctx.args.amountPaid,
bankFk: ctx.args.bankFk
}
});
const till = await app.models.Till.findOne({ ctx.args = {
where: { clientFk: clientFk,
bankFk: ctx.args.bankFk, payed: payed,
in: amountPaid, companyFk: companyFk,
number: clientFk bankFk: bankFk,
} amountPaid: amountPaid,
}); description: description,
compensationAccount: '4100000001'
};
const receipt = await models.Client.createReceipt(ctx, options);
delete ctx.args.payed; const paymentCompensated = await models.Payment.findOne({
where: {
clientFk: ctx.args.sale,
payed: ctx.args.payed,
amountPaid: ctx.args.amountPaid,
bankFk: ctx.args.bankFk
}
}, options);
expect(receipt).toEqual(jasmine.objectContaining(ctx.args)); delete ctx.args.payed;
expect(paymentCompensated.amountPaid).toEqual(paymentCompensated.amountPaid); expect(receipt).toEqual(jasmine.objectContaining(ctx.args));
// restores expect(paymentCompensated.amountPaid).toEqual(paymentCompensated.amountPaid);
await receipt.destroy();
await paymentCompensated.destroy(); await tx.rollback();
await till.destroy(); } catch (e) {
await tx.rollback();
}
}); });
}); });

View File

@ -1,28 +1,7 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('Client Create', () => { describe('Client Create', () => {
const clientName = 'Wade'; const newAccount = {
const AccountName = 'Deadpool';
afterEach(async done => {
let address = await app.models.Address.findOne({where: {nickname: clientName}});
let client = await app.models.Client.findOne({where: {name: clientName}});
let account = await app.models.Account.findOne({where: {name: AccountName}});
if (address && client && account) {
try {
await app.models.Address.destroyById(address.id);
await app.models.Client.destroyById(client.id);
await app.models.Account.destroyById(account.id);
} catch (error) {
console.error(error);
}
}
done();
});
let newAccount = {
userName: 'Deadpool', userName: 'Deadpool',
email: 'Deadpool@marvel.com', email: 'Deadpool@marvel.com',
fi: '16195279J', fi: '16195279J',
@ -33,34 +12,66 @@ describe('Client Create', () => {
}; };
it(`should not find Deadpool as he's not created yet`, async() => { it(`should not find Deadpool as he's not created yet`, async() => {
let account = await app.models.Account.findOne({where: {name: newAccount.userName}}); const tx = await models.Client.beginTransaction({});
let client = await app.models.Client.findOne({where: {name: newAccount.name}});
expect(account).toEqual(null); try {
expect(client).toEqual(null); const options = {transaction: tx};
const account = await models.Account.findOne({where: {name: newAccount.userName}}, options);
const client = await models.Client.findOne({where: {name: newAccount.name}}, options);
expect(account).toEqual(null);
expect(client).toEqual(null);
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
it('should create a new account', async() => { it('should create a new account', async() => {
let client = await app.models.Client.createWithUser(newAccount); const tx = await models.Client.beginTransaction({});
let account = await app.models.Account.findOne({where: {name: newAccount.userName}});
expect(account.name).toEqual(newAccount.userName); try {
const options = {transaction: tx};
expect(client.id).toEqual(account.id); const client = await models.Client.createWithUser(newAccount, options);
expect(client.name).toEqual(newAccount.name); const account = await models.Account.findOne({where: {name: newAccount.userName}}, options);
expect(client.email).toEqual(newAccount.email);
expect(client.fi).toEqual(newAccount.fi); expect(account.name).toEqual(newAccount.userName);
expect(client.socialName).toEqual(newAccount.socialName); expect(client.id).toEqual(account.id);
expect(client.name).toEqual(newAccount.name);
expect(client.email).toEqual(newAccount.email);
expect(client.fi).toEqual(newAccount.fi);
expect(client.socialName).toEqual(newAccount.socialName);
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
it('should not be able to create a user if exists', async() => { it('should not be able to create a user if exists', async() => {
await app.models.Client.createWithUser(newAccount); const tx = await models.Client.beginTransaction({});
let error;
try { try {
let client = await app.models.Client.createWithUser(newAccount); const options = {transaction: tx};
await models.Client.createWithUser(newAccount, options);
const client = await models.Client.createWithUser(newAccount, options);
expect(client).toBeNull(); expect(client).toBeNull();
} catch (err) {
expect(err.details.codes.name[0]).toEqual('uniqueness'); await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
} }
const errorName = error.details.codes.name[0];
expect(errorName).toEqual('uniqueness');
}); });
}); });

View File

@ -1,9 +1,19 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('client getAverageInvoiced()', () => { describe('client getAverageInvoiced()', () => {
it('should call the getAverageInvoiced method', async() => { it('should call the getAverageInvoiced method', async() => {
const {invoiced} = await app.models.Client.getAverageInvoiced(1101); const tx = await models.Client.beginTransaction({});
expect(invoiced).toEqual(1500); try {
const options = {transaction: tx};
const {invoiced} = await models.Client.getAverageInvoiced(1101, options);
expect(invoiced).toEqual(1500);
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
}); });

View File

@ -1,12 +1,22 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('Client getCard()', () => { describe('Client getCard()', () => {
it('should receive a formated card of Bruce Wayne', async() => { it('should receive a formated card of Bruce Wayne', async() => {
let id = 1101; const tx = await models.Client.beginTransaction({});
let result = await app.models.Client.getCard(id);
expect(result.id).toEqual(id); try {
expect(result.name).toEqual('Bruce Wayne'); const options = {transaction: tx};
expect(result.debt).toEqual(jasmine.any(Number));
const id = 1101;
const result = await models.Client.getCard(id, options);
expect(result.id).toEqual(id);
expect(result.name).toEqual('Bruce Wayne');
expect(result.debt).toEqual(jasmine.any(Number));
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
}); });

View File

@ -1,10 +1,20 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('client getDebt()', () => { describe('client getDebt()', () => {
it('should return the client debt', async() => { it('should return the client debt', async() => {
let result = await app.models.Client.getDebt(1101); const tx = await models.Client.beginTransaction({});
expect(result.debt).toEqual(jasmine.any(Number)); try {
const options = {transaction: tx};
const result = await models.Client.getDebt(1101, options);
expect(result.debt).toEqual(jasmine.any(Number));
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
}); });

View File

@ -1,9 +1,19 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('client getMana()', () => { describe('client getMana()', () => {
it('should call the getMana method', async() => { it('should call the getMana method', async() => {
let result = await app.models.Client.getMana(1105); const tx = await models.Client.beginTransaction({});
expect(result.mana).toEqual(0.34); try {
const options = {transaction: tx};
const result = await models.Client.getMana(1105, options);
expect(result.mana).toEqual(0.34);
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
}); });

View File

@ -1,10 +1,20 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('Client getTransations', () => { describe('Client getTransations', () => {
it('should call getTransations() method to receive a list of Web Payments from Bruce Wayne', async() => { it('should call getTransations() method to receive a list of Web Payments from Bruce Wayne', async() => {
let filter = {where: {clientFk: 1101}}; const tx = await models.Client.beginTransaction({});
let result = await app.models.Client.getTransactions(filter);
expect(result[1].id).toBeTruthy(); try {
const options = {transaction: tx};
const filter = {where: {clientFk: 1101}};
const result = await models.Client.getTransactions(filter, options);
expect(result[1].id).toBeTruthy();
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
}); });

View File

@ -1,59 +1,74 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('Client hasCustomerRole', () => { describe('Client hasCustomerRole', () => {
it('should call the hasCustomerRole() method with a customer id', done => { it('should call the hasCustomerRole() method with a customer id', async() => {
let id = 1101; const tx = await models.Client.beginTransaction({});
let params = {};
let callback = (error, result) => { try {
if (error) return done.fail(error); const options = {transaction: tx};
const id = 1101;
const [result] = await models.Client.hasCustomerRole(id, options);
expect(result).toEqual(jasmine.objectContaining({isCustomer: 1})); expect(result).toEqual(jasmine.objectContaining({isCustomer: 1}));
done();
};
app.models.Client.hasCustomerRole(id, params, callback); await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
it('should call the hasCustomerRole() method with a non customer id', done => { it('should call the hasCustomerRole() method with a non customer id', async() => {
let id = 8; const tx = await models.Client.beginTransaction({});
let params = {};
let callback = (error, result) => { try {
if (error) return done.fail(error); const options = {transaction: tx};
const id = 8;
const [result] = await models.Client.hasCustomerRole(id, options);
expect(result).toEqual(jasmine.objectContaining({isCustomer: 0})); expect(result).toEqual(jasmine.objectContaining({isCustomer: 0}));
done();
};
app.models.Client.hasCustomerRole(id, params, callback); await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
it('should call the hasCustomerRole() method with an unreal id', done => { it('should call the hasCustomerRole() method with an unreal id', async() => {
let id = 999; const tx = await models.Client.beginTransaction({});
let params = {};
let callback = (error, result) => { try {
if (error) return done.fail(error); const options = {transaction: tx};
const id = 999;
const [result] = await models.Client.hasCustomerRole(id, options);
expect(result).toEqual(jasmine.objectContaining({isCustomer: 0})); expect(result).toEqual(jasmine.objectContaining({isCustomer: 0}));
done();
};
app.models.Client.hasCustomerRole(id, params, callback); await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
it('should call the hasCustomerRole() method with an invalid id', done => { it('should call the hasCustomerRole() method with an invalid id', async() => {
let id = 'WRONG!'; const tx = await models.Client.beginTransaction({});
let params = {};
let callback = (error, result) => { try {
if (error) return done.fail(error); const options = {transaction: tx};
const id = 'WRONG!';
const [result] = await models.Client.hasCustomerRole(id, options);
expect(result).toEqual(jasmine.objectContaining({isCustomer: 0})); expect(result).toEqual(jasmine.objectContaining({isCustomer: 0}));
done();
};
app.models.Client.hasCustomerRole(id, params, callback); await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
}); });

View File

@ -1,45 +1,105 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('Client isValidClient', () => { describe('Client isValidClient', () => {
it('should call the isValidClient() method with a client id and receive true', async() => { it('should call the isValidClient() method with a client id and receive true', async() => {
let id = 1101; const tx = await models.Client.beginTransaction({});
let result = await app.models.Client.isValidClient(id);
expect(result).toBeTruthy(); try {
const options = {transaction: tx};
const id = 1101;
const result = await models.Client.isValidClient(id, options);
expect(result).toBeTruthy();
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
it('should call the isValidClient() method with an employee id to receive false', async() => { it('should call the isValidClient() method with an employee id to receive false', async() => {
let id = 1; const tx = await models.Client.beginTransaction({});
let result = await app.models.Client.isValidClient(id);
expect(result).toBeFalsy(); try {
const options = {transaction: tx};
const id = 1;
const result = await models.Client.isValidClient(id, options);
expect(result).toBeFalsy();
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
it('should call the isValidClient() method with an unexistant id and receive false', async() => { it('should call the isValidClient() method with an unexistant id and receive false', async() => {
let id = 999; const tx = await models.Client.beginTransaction({});
let result = await app.models.Client.isValidClient(id);
expect(result).toBeFalsy(); try {
const options = {transaction: tx};
const id = 999;
const result = await models.Client.isValidClient(id, options);
expect(result).toBeFalsy();
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
it('should call the isValidClient() method with an invalid id and receive false', async() => { it('should call the isValidClient() method with an invalid id and receive false', async() => {
let id = 'Pepinillos'; const tx = await models.Client.beginTransaction({});
let result = await app.models.Client.isValidClient(id);
expect(result).toBeFalsy(); try {
const options = {transaction: tx};
const id = 'Pepinillos';
const result = await models.Client.isValidClient(id, options);
expect(result).toBeFalsy();
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
it('should call the isValidClient() method with a customer id which isnt active and return false', async() => { it('should call the isValidClient() method with a customer id which isnt active and return false', async() => {
let id = '1106'; const tx = await models.Client.beginTransaction({});
let result = await app.models.Client.isValidClient(id);
expect(result).toBeFalsy(); try {
const options = {transaction: tx};
const id = '1106';
const result = await models.Client.isValidClient(id, options);
expect(result).toBeFalsy();
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
it('should call the isValidClient() method with a customer id which his data isnt verified and return false', async() => { it('should call the isValidClient() method with a customer id which his data isnt verified and return false', async() => {
let id = '110'; const tx = await models.Client.beginTransaction({});
let result = await app.models.Client.isValidClient(id);
expect(result).toBeFalsy(); try {
const options = {transaction: tx};
const id = '110';
const result = await models.Client.isValidClient(id, options);
expect(result).toBeFalsy();
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
}); });

View File

@ -1,18 +1,27 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('Client last active tickets', () => { describe('Client last active tickets', () => {
it('should receive an array of last active tickets of Bruce Wayne', async() => { it('should receive an array of last active tickets of Bruce Wayne', async() => {
const ticketId = 22; const tx = await models.Client.beginTransaction({});
const clientId = 1109;
const warehouseId = 5;
const result = await app.models.Client.lastActiveTickets(clientId, ticketId, warehouseId);
const length = result.length; try {
const anyResult = result[Math.floor(Math.random() * Math.floor(length))]; const options = {transaction: tx};
const ticketId = 22;
const clientId = 1109;
const properties = Object.keys(anyResult); const result = await models.Client.lastActiveTickets(clientId, ticketId, options);
expect(properties.length).toEqual(9); const length = result.length;
expect(result.length).toEqual(3); const anyResult = result[Math.floor(Math.random() * Math.floor(length))];
const properties = Object.keys(anyResult);
expect(properties.length).toEqual(9);
expect(result.length).toEqual(3);
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
}); });

View File

@ -1,29 +1,28 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
const soap = require('soap'); const soap = require('soap');
describe('client sendSms()', () => { describe('client sendSms()', () => {
let createdLog;
afterAll(async done => {
await app.models.ClientLog.destroyById(createdLog.id);
done();
});
it('should now send a message and log it', async() => { it('should now send a message and log it', async() => {
spyOn(soap, 'createClientAsync').and.returnValue('a so fake client'); spyOn(soap, 'createClientAsync').and.returnValue('a so fake client');
let ctx = {req: {accessToken: {userId: 9}}}; const tx = await models.Client.beginTransaction({});
let id = 1101;
let destination = 222222222;
let message = 'this is the message created in a test';
let sms = await app.models.Client.sendSms(ctx, id, destination, message); try {
const options = {transaction: tx};
const ctx = {req: {accessToken: {userId: 9}}};
const id = 1101;
const destination = 222222222;
const message = 'this is the message created in a test';
logId = sms.logId; const sms = await models.Client.sendSms(ctx, id, destination, message, options);
createdLog = await app.models.ClientLog.findById(logId); const createdLog = await models.ClientLog.findById(sms.logId);
let json = JSON.parse(JSON.stringify(createdLog.newInstance)); const json = JSON.parse(JSON.stringify(createdLog.newInstance));
expect(json.message).toEqual(message); expect(json.message).toEqual(message);
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
}); });

View File

@ -1,46 +1,123 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('client summary()', () => { describe('client summary()', () => {
it('should return a summary object containing data', async() => { it('should return a summary object containing data', async() => {
let result = await app.models.Client.summary(1101); const clientId = 1101;
const tx = await models.Client.beginTransaction({});
expect(result.id).toEqual(1101); try {
expect(result.name).toEqual('Bruce Wayne'); const options = {transaction: tx};
const result = await models.Client.summary(clientId, options);
expect(result.id).toEqual(clientId);
expect(result.name).toEqual('Bruce Wayne');
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
it('should return a summary object containing mana', async() => { it('should return a summary object containing mana', async() => {
let result = await app.models.Client.summary(1105); const clientId = 1105;
const tx = await models.Client.beginTransaction({});
expect(result.mana.mana).toEqual(0.34); try {
const options = {transaction: tx};
const result = await models.Client.summary(clientId, options);
expect(result.mana.mana).toEqual(0.34);
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
it('should return a summary object containing debt', async() => { it('should return a summary object containing debt', async() => {
let result = await app.models.Client.summary(1101); const clientId = 1101;
const tx = await models.Client.beginTransaction({});
expect(result.debt.debt).toEqual(jasmine.any(Number)); try {
const options = {transaction: tx};
const result = await models.Client.summary(clientId, options);
expect(result.debt.debt).toEqual(jasmine.any(Number));
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
it('should return a summary object containing averageInvoiced', async() => { it('should return a summary object containing averageInvoiced', async() => {
let result = await app.models.Client.summary(1101); const clientId = 1101;
const tx = await models.Client.beginTransaction({});
expect(result.averageInvoiced.invoiced).toEqual(1500); try {
const options = {transaction: tx};
const result = await models.Client.summary(clientId, options);
expect(result.averageInvoiced.invoiced).toEqual(1500);
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
it('should return a summary object containing totalGreuge', async() => { it('should return a summary object containing totalGreuge', async() => {
let result = await app.models.Client.summary(1101); const clientId = 1101;
const tx = await models.Client.beginTransaction({});
expect(result.totalGreuge).toEqual(203.71); try {
const options = {transaction: tx};
const result = await models.Client.summary(clientId, options);
expect(result.totalGreuge).toEqual(203.71);
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
it('should return a summary object without containing active recoveries', async() => { it('should return a summary object without containing active recoveries', async() => {
let result = await app.models.Client.summary(1101); const clientId = 1101;
const tx = await models.Client.beginTransaction({});
expect(result.recovery).toEqual(null); try {
const options = {transaction: tx};
const result = await models.Client.summary(clientId, options);
expect(result.recovery).toEqual(null);
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
it('should return a summary object containing active recoveries', async() => { it('should return a summary object containing active recoveries', async() => {
let result = await app.models.Client.summary(1102); const clientId = 1102;
const tx = await models.Client.beginTransaction({});
expect(result.recovery.id).toEqual(3); try {
const options = {transaction: tx};
const result = await models.Client.summary(clientId, options);
expect(result.recovery.id).toEqual(3);
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
}); });

View File

@ -1,12 +0,0 @@
const app = require('vn-loopback/server/server');
describe('client lastActiveTickets()', () => {
it('should return the last three active tickets', async() => {
const clientId = 1109;
const ticketId = 19;
let result = await app.models.Client.lastActiveTickets(clientId, ticketId);
expect(result.length).toEqual(3);
});
});

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('Address updateAddress', () => { describe('Address updateAddress', () => {
const clientId = 1101; const clientId = 1101;
@ -8,93 +8,105 @@ describe('Address updateAddress', () => {
const customAgentOneId = 1; const customAgentOneId = 1;
it('should throw the non uee member error if no incoterms is defined', async() => { it('should throw the non uee member error if no incoterms is defined', async() => {
let err; const tx = await models.Client.beginTransaction({});
const ctx = {
args: { let error;
provinceFk: provinceId,
customsAgentFk: customAgentOneId
}
};
try { try {
await app.models.Client.updateAddress(ctx, clientId, addressId); const options = {transaction: tx};
const ctx = {
args: {
provinceFk: provinceId,
customsAgentFk: customAgentOneId
}
};
await models.Client.updateAddress(ctx, clientId, addressId, options);
await tx.rollback();
} catch (e) { } catch (e) {
err = e; await tx.rollback();
error = e;
} }
expect(err).toBeDefined(); expect(error).toBeDefined();
expect(err.message).toEqual('Incoterms is required for a non UEE member'); expect(error.message).toEqual('Incoterms is required for a non UEE member');
}); });
it('should throw a non uee member error if no customsAgent is defined', async() => { it('should throw a non uee member error if no customsAgent is defined', async() => {
let err; const tx = await models.Client.beginTransaction({});
const ctx = {
args: { let error;
provinceFk: provinceId,
incotermsFk: incotermsId
}
};
try { try {
await app.models.Client.updateAddress(ctx, clientId, addressId); const options = {transaction: tx};
const ctx = {
args: {
provinceFk: provinceId,
incotermsFk: incotermsId
}
};
await models.Client.updateAddress(ctx, clientId, addressId, options);
await tx.rollback();
} catch (e) { } catch (e) {
err = e; await tx.rollback();
error = e;
} }
expect(err).toBeDefined(); expect(error).toBeDefined();
expect(err.message).toEqual('Customs agent is required for a non UEE member'); expect(error.message).toEqual('Customs agent is required for a non UEE member');
}); });
it('should update the adress from a non uee member with no error thrown', async() => { it('should update the adress from a non uee member with no error thrown', async() => {
const expectedResult = 'My edited address'; const tx = await models.Client.beginTransaction({});
const ctx = {
args: {
provinceFk: provinceId,
nickname: expectedResult,
incotermsFk: incotermsId,
customsAgentFk: customAgentOneId
}
};
let oldAddress = await app.models.Address.findById(addressId); try {
const options = {transaction: tx};
const ctx = {
args: {
provinceFk: provinceId,
nickname: expectedResult,
incotermsFk: incotermsId,
customsAgentFk: customAgentOneId
}
};
const expectedResult = 'My edited address';
await app.models.Client.updateAddress(ctx, clientId, addressId); await models.Client.updateAddress(ctx, clientId, addressId, options);
let address = await app.models.Address.findById(addressId); const address = await models.Address.findById(addressId, null, options);
expect(address.nickname).toEqual(expectedResult); expect(address.nickname).toEqual(expectedResult);
// restores await tx.rollback();
await address.updateAttributes({ } catch (e) {
nickname: oldAddress.nickname, await tx.rollback();
provinceFk: oldAddress.provinceFk, }
customsAgentFk: null,
incotermsFk: null
});
}); });
it('should update the address', async() => { it('should update the address', async() => {
const expectedResult = 'My second time edited address'; const tx = await models.Client.beginTransaction({});
const ctx = {
args: {
nickname: expectedResult
}
};
oldAddress = await app.models.Address.findById(addressId); try {
const options = {transaction: tx};
const ctx = {
args: {
nickname: expectedResult
}
};
const expectedResult = 'My second time edited address';
await app.models.Client.updateAddress(ctx, clientId, addressId); await models.Client.updateAddress(ctx, clientId, addressId, options);
address = await app.models.Address.findById(addressId); const address = await models.Address.findById(addressId, null, options);
expect(address.nickname).toEqual(expectedResult); expect(address.nickname).toEqual(expectedResult);
// restores await tx.rollback();
await address.updateAttributes({ } catch (e) {
nickname: oldAddress.nickname, await tx.rollback();
provinceFk: oldAddress.provinceFk, }
customsAgentFk: null,
incotermsFk: null
});
}); });
}); });

View File

@ -1,61 +1,76 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('Client updateFiscalData', () => { describe('Client updateFiscalData', () => {
const clientId = 1101; const clientId = 1101;
const employeeId = 1; const employeeId = 1;
const salesAssistantId = 21; const salesAssistantId = 21;
const administrativeId = 5; const administrativeId = 5;
afterAll(async done => {
const ctx = {req: {accessToken: {userId: administrativeId}}};
ctx.args = {postcode: 46460};
await app.models.Client.updateFiscalData(ctx, clientId);
done();
});
it('should return an error if the user is not salesAssistant and the isTaxDataChecked value is true', async() => { it('should return an error if the user is not salesAssistant and the isTaxDataChecked value is true', async() => {
const ctx = {req: {accessToken: {userId: employeeId}}}; const tx = await models.Client.beginTransaction({});
ctx.args = {};
let error; let error;
await app.models.Client.updateFiscalData(ctx, clientId)
.catch(e => { try {
error = e; const options = {transaction: tx};
}); const ctx = {req: {accessToken: {userId: employeeId}}};
ctx.args = {};
await models.Client.updateFiscalData(ctx, clientId, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
expect(error.message).toEqual(`You can't make changes on a client with verified data`); expect(error.message).toEqual(`You can't make changes on a client with verified data`);
}); });
it('should return an error if the salesAssistant did not fill the sage data before checking verified data', async() => { it('should return an error if the salesAssistant did not fill the sage data before checking verified data', async() => {
const client = await app.models.Client.findById(clientId); const tx = await models.Client.beginTransaction({});
await client.updateAttribute('isTaxDataChecked', false);
const ctx = {req: {accessToken: {userId: salesAssistantId}}};
ctx.args = {isTaxDataChecked: true};
let error; let error;
await app.models.Client.updateFiscalData(ctx, clientId)
.catch(e => { try {
error = e; const options = {transaction: tx};
});
const client = await models.Client.findById(clientId, options);
await client.updateAttribute('isTaxDataChecked', false, options);
const ctx = {req: {accessToken: {userId: salesAssistantId}}};
ctx.args = {isTaxDataChecked: true};
await models.Client.updateFiscalData(ctx, clientId, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
expect(error.message).toEqual('You need to fill sage information before you check verified data'); expect(error.message).toEqual('You need to fill sage information before you check verified data');
// Restores
await client.updateAttribute('isTaxDataChecked', true);
}); });
it('should update the client fiscal data and return the count if changes made', async() => { it('should update the client fiscal data', async() => {
const ctx = {req: {accessToken: {userId: administrativeId}}}; const tx = await models.Client.beginTransaction({});
ctx.args = {postcode: 46680};
const client = await app.models.Client.findById(clientId); try {
const options = {transaction: tx};
const ctx = {req: {accessToken: {userId: administrativeId}}};
ctx.args = {postcode: 46680};
expect(client.postcode).toEqual('46460'); const client = await models.Client.findById(clientId, null, options);
const result = await app.models.Client.updateFiscalData(ctx, clientId); expect(client.postcode).toEqual('46460');
expect(result.postcode).toEqual('46680'); const result = await models.Client.updateFiscalData(ctx, clientId, options);
expect(result.postcode).toEqual('46680');
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
}); });

View File

@ -1,19 +1,26 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('Client uploadFile()', () => { describe('Client uploadFile()', () => {
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.Client.beginTransaction({});
let currentUserId = 1102;
let paymentLawTypeId = 12;
let ctx = {req: {accessToken: {userId: currentUserId}}, args: {dmsTypeId: paymentLawTypeId}};
let error; let error;
await app.models.Client.uploadFile(ctx, clientId).catch(e => {
error = e;
}).finally(() => {
expect(error.message).toEqual(`You don't have enough privileges`);
});
expect(error).toBeDefined(); try {
const options = {transaction: tx};
const clientId = 1101;
const currentUserId = 1102;
const paymentLawTypeId = 12;
const ctx = {req: {accessToken: {userId: currentUserId}}, args: {dmsTypeId: paymentLawTypeId}};
await models.Client.uploadFile(ctx, clientId, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
expect(error.message).toEqual(`You don't have enough privileges`);
}); });
}); });

View File

@ -19,21 +19,26 @@ module.exports = Self => {
} }
}); });
Self.summary = async clientFk => { Self.summary = async(clientFk, options) => {
let models = Self.app.models; const models = Self.app.models;
let summaryObj = await getSummary(models.Client, clientFk); const myOptions = {};
summaryObj.mana = await models.Client.getMana(clientFk); if (typeof options == 'object')
summaryObj.debt = await models.Client.getDebt(clientFk); Object.assign(myOptions, options);
summaryObj.averageInvoiced = await models.Client.getAverageInvoiced(clientFk);
summaryObj.totalGreuge = await models.Greuge.sumAmount(clientFk); const summaryObj = await getSummary(models.Client, clientFk, myOptions);
summaryObj.recovery = await getRecoveries(models.Recovery, clientFk);
summaryObj.mana = await models.Client.getMana(clientFk, myOptions);
summaryObj.debt = await models.Client.getDebt(clientFk, myOptions);
summaryObj.averageInvoiced = await models.Client.getAverageInvoiced(clientFk, myOptions);
summaryObj.totalGreuge = await models.Greuge.sumAmount(clientFk, myOptions);
summaryObj.recovery = await getRecoveries(models.Recovery, clientFk, myOptions);
return summaryObj; return summaryObj;
}; };
async function getSummary(client, clientId) { async function getSummary(clientModel, clientId, options) {
let filter = { const filter = {
include: [ include: [
{ {
relation: 'account', relation: 'account',
@ -115,17 +120,17 @@ module.exports = Self => {
where: {id: clientId} where: {id: clientId}
}; };
return await client.findOne(filter); return clientModel.findOne(filter, options);
} }
async function getRecoveries(recovery, clientId) { async function getRecoveries(recoveryModel, clientId, options) {
let filter = { const filter = {
where: { where: {
and: [{clientFk: clientId}, {or: [{finished: null}, {finished: {gt: Date.now()}}]}] and: [{clientFk: clientId}, {or: [{finished: null}, {finished: {gt: Date.now()}}]}]
}, },
limit: 1 limit: 1
}; };
return await recovery.findOne(filter); return recoveryModel.findOne(filter, options);
} }
}; };

View File

@ -3,71 +3,73 @@ const UserError = require('vn-loopback/util/user-error');
module.exports = function(Self) { module.exports = function(Self) {
Self.remoteMethod('updateAddress', { Self.remoteMethod('updateAddress', {
description: 'Updates a client address updating default address', description: 'Updates a client address updating default address',
accepts: [{ accepts: [
arg: 'ctx', {
type: 'object', arg: 'ctx',
http: {source: 'context'} type: 'object',
}, http: {source: 'context'}
{ },
arg: 'clientId', {
type: 'number', arg: 'clientId',
description: 'The client id', type: 'number',
http: {source: 'path'} description: 'The client id',
}, http: {source: 'path'}
{ },
arg: 'addressId', {
type: 'number', arg: 'addressId',
description: 'The address id', type: 'number',
http: {source: 'path'} description: 'The address id',
}, http: {source: 'path'}
{ },
arg: 'nickname', {
type: 'string' arg: 'nickname',
}, type: 'string'
{ },
arg: 'city', {
type: 'string' arg: 'city',
}, type: 'string'
{ },
arg: 'street', {
type: 'string' arg: 'street',
}, type: 'string'
{ },
arg: 'phone', {
type: 'any' arg: 'phone',
}, type: 'any'
{ },
arg: 'mobile', {
type: 'any' arg: 'mobile',
}, type: 'any'
{ },
arg: 'postalCode', {
type: 'any' arg: 'postalCode',
}, type: 'any'
{ },
arg: 'provinceFk', {
type: 'any' arg: 'provinceFk',
}, type: 'any'
{ },
arg: 'agencyModeFk', {
type: 'any' arg: 'agencyModeFk',
}, type: 'any'
{ },
arg: 'incotermsFk', {
type: 'any' arg: 'incotermsFk',
}, type: 'any'
{ },
arg: 'customsAgentFk', {
type: 'any' arg: 'customsAgentFk',
}, type: 'any'
{ },
arg: 'isActive', {
type: 'boolean' arg: 'isActive',
}, type: 'boolean'
{ },
arg: 'isEqualizated', {
type: 'boolean' arg: 'isEqualizated',
}], type: 'boolean'
}
],
returns: { returns: {
root: true, root: true,
type: 'object' type: 'object'
@ -78,44 +80,44 @@ module.exports = function(Self) {
} }
}); });
Self.updateAddress = async(ctx, clientId, addressId) => { Self.updateAddress = async(ctx, clientId, addressId, options) => {
const models = Self.app.models; const models = Self.app.models;
const args = ctx.args; const args = ctx.args;
const tx = await models.Address.beginTransaction({}); const myOptions = {};
try {
const options = {transaction: tx};
const address = await models.Address.findOne({
where: {
id: addressId,
clientFk: clientId
}
});
const provinceId = args.provinceFk || address.provinceFk;
if (provinceId) {
const province = await models.Province.findById(provinceId, {
include: {
relation: 'country'
}
}, options);
const isUeeMember = province.country().isUeeMember; if (typeof options == 'object')
const incotermsId = args.incotermsFk || address.incotermsFk; Object.assign(myOptions, options);
if (!isUeeMember && !incotermsId)
throw new UserError(`Incoterms is required for a non UEE member`);
const customsAgentId = args.customsAgentFk || address.customsAgentFk; const address = await models.Address.findOne({
if (!isUeeMember && !customsAgentId) where: {
throw new UserError(`Customs agent is required for a non UEE member`); id: addressId,
clientFk: clientId
} }
}, myOptions);
delete args.ctx; // Remove unwanted properties const provinceId = args.provinceFk || address.provinceFk;
const updatedAddress = await address.updateAttributes(ctx.args, options); if (provinceId) {
const province = await models.Province.findById(provinceId, {
include: {
relation: 'country'
}
}, myOptions);
await tx.commit(); const isUeeMember = province.country().isUeeMember;
return updatedAddress; const incotermsId = args.incotermsFk || address.incotermsFk;
} catch (e) {
await tx.rollback(); if (!isUeeMember && !incotermsId)
throw e; throw new UserError(`Incoterms is required for a non UEE member`);
const customsAgentId = args.customsAgentFk || address.customsAgentFk;
if (!isUeeMember && !customsAgentId)
throw new UserError(`Customs agent is required for a non UEE member`);
} }
delete args.ctx; // Remove unwanted properties
const updatedAddress = await address.updateAttributes(ctx.args, myOptions);
return updatedAddress;
}; };
}; };

View File

@ -4,97 +4,99 @@ module.exports = Self => {
Self.remoteMethod('updateFiscalData', { Self.remoteMethod('updateFiscalData', {
description: 'Updates fiscal data of a client', description: 'Updates fiscal data of a client',
accessType: 'WRITE', accessType: 'WRITE',
accepts: [{ accepts: [
arg: 'ctx', {
type: 'Object', arg: 'ctx',
http: {source: 'context'} type: 'object',
}, http: {source: 'context'}
{ },
arg: 'id', {
type: 'Number', arg: 'id',
description: 'The client id', type: 'number',
http: {source: 'path'} description: 'The client id',
}, http: {source: 'path'}
{ },
arg: 'socialName', {
type: 'string' arg: 'socialName',
}, type: 'string'
{ },
arg: 'fi', {
type: 'string' arg: 'fi',
}, type: 'string'
{ },
arg: 'street', {
type: 'string' arg: 'street',
}, type: 'string'
{ },
arg: 'postcode', {
type: 'string' arg: 'postcode',
}, type: 'string'
{ },
arg: 'city', {
type: 'string' arg: 'city',
}, type: 'string'
{ },
arg: 'countryFk', {
type: 'number' arg: 'countryFk',
}, type: 'number'
{ },
arg: 'provinceFk', {
type: 'number' arg: 'provinceFk',
}, type: 'number'
{ },
arg: 'sageTaxTypeFk', {
type: 'any' arg: 'sageTaxTypeFk',
}, type: 'any'
{ },
arg: 'sageTransactionTypeFk', {
type: 'any' arg: 'sageTransactionTypeFk',
}, type: 'any'
{ },
arg: 'transferorFk', {
type: 'any' arg: 'transferorFk',
}, type: 'any'
{ },
arg: 'hasToInvoiceByAddress', {
type: 'boolean' arg: 'hasToInvoiceByAddress',
}, type: 'boolean'
{ },
arg: 'hasToInvoice', {
type: 'boolean' arg: 'hasToInvoice',
}, type: 'boolean'
{ },
arg: 'isActive', {
type: 'boolean' arg: 'isActive',
}, type: 'boolean'
{ },
arg: 'isFreezed', {
type: 'boolean' arg: 'isFreezed',
}, type: 'boolean'
{ },
arg: 'isVies', {
type: 'boolean' arg: 'isVies',
}, type: 'boolean'
{ },
arg: 'isToBeMailed', {
type: 'boolean' arg: 'isToBeMailed',
}, type: 'boolean'
{ },
arg: 'isEqualizated', {
type: 'boolean' arg: 'isEqualizated',
}, type: 'boolean'
{ },
arg: 'isTaxDataVerified', {
type: 'boolean' arg: 'isTaxDataVerified',
}, type: 'boolean'
{ },
arg: 'isTaxDataChecked', {
type: 'boolean' arg: 'isTaxDataChecked',
}, type: 'boolean'
{ },
arg: 'despiteOfClient', {
type: 'number' arg: 'despiteOfClient',
}], type: 'number'
}
],
returns: { returns: {
arg: 'res', arg: 'res',
type: 'string', type: 'string',
@ -106,46 +108,65 @@ module.exports = Self => {
} }
}); });
Self.updateFiscalData = async(ctx, clientId) => { Self.updateFiscalData = async(ctx, clientId, options) => {
let tx;
const myOptions = {};
const models = Self.app.models; const models = Self.app.models;
const args = ctx.args; const args = ctx.args;
const userId = ctx.req.accessToken.userId; const userId = ctx.req.accessToken.userId;
const isSalesAssistant = await models.Account.hasRole(userId, 'salesAssistant');
const $t = ctx.req.__; const $t = ctx.req.__;
const client = await models.Client.findById(clientId); if (typeof options == 'object')
Object.assign(myOptions, options);
if (!isSalesAssistant && client.isTaxDataChecked) if (!myOptions.transaction) {
throw new UserError(`You can't make changes on a client with verified data`); tx = await Self.beginTransaction({});
myOptions.transaction = tx;
// Sage data validation
const taxDataChecked = args.isTaxDataChecked;
const sageTaxChecked = client.sageTaxTypeFk || args.sageTaxTypeFk;
const sageTransactionChecked = client.sageTransactionTypeFk || args.sageTransactionTypeFk;
const hasSageData = sageTaxChecked && sageTransactionChecked;
if (taxDataChecked && !hasSageData)
throw new UserError(`You need to fill sage information before you check verified data`);
if (args.despiteOfClient) {
const logRecord = {
originFk: clientId,
userFk: userId,
action: 'update',
changedModel: 'Client',
changedModelId: clientId,
description: $t(`Client checked as validated despite of duplication`, {
clientId: args.despiteOfClient
})
};
await models.ClientLog.create(logRecord);
} }
// Remove unwanted properties try {
delete args.ctx; const isSalesAssistant = await models.Account.hasRole(userId, 'salesAssistant', myOptions);
delete args.id; const client = await models.Client.findById(clientId, null, myOptions);
return client.updateAttributes(args); if (!isSalesAssistant && client.isTaxDataChecked)
throw new UserError(`You can't make changes on a client with verified data`);
// Sage data validation
const taxDataChecked = args.isTaxDataChecked;
const sageTaxChecked = client.sageTaxTypeFk || args.sageTaxTypeFk;
const sageTransactionChecked = client.sageTransactionTypeFk || args.sageTransactionTypeFk;
const hasSageData = sageTaxChecked && sageTransactionChecked;
if (taxDataChecked && !hasSageData)
throw new UserError(`You need to fill sage information before you check verified data`);
if (args.despiteOfClient) {
const logRecord = {
originFk: clientId,
userFk: userId,
action: 'update',
changedModel: 'Client',
changedModelId: clientId,
description: $t(`Client checked as validated despite of duplication`, {
clientId: args.despiteOfClient
})
};
await models.ClientLog.create(logRecord, myOptions);
}
// Remove unwanted properties
delete args.ctx;
delete args.id;
const updatedClient = await client.updateAttributes(args, myOptions);
if (tx) await tx.commit();
return updatedClient;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
}; };
}; };

View File

@ -2,42 +2,50 @@ module.exports = Self => {
Self.remoteMethodCtx('uploadFile', { Self.remoteMethodCtx('uploadFile', {
description: 'Upload and attach a file to a client', description: 'Upload and attach a file to a client',
accessType: 'WRITE', accessType: 'WRITE',
accepts: [{ accepts: [
arg: 'id', {
type: 'Number', arg: 'id',
description: 'The client id', type: 'number',
http: {source: 'path'} description: 'The client id',
}, { http: {source: 'path'}
arg: 'warehouseId', },
type: 'Number', {
description: 'The warehouse id', arg: 'warehouseId',
required: true type: 'number',
}, { description: 'The warehouse id',
arg: 'companyId', required: true
type: 'Number', },
description: 'The company id', {
required: true arg: 'companyId',
}, { type: 'number',
arg: 'dmsTypeId', description: 'The company id',
type: 'Number', required: true
description: 'The dms type id', },
required: true {
}, { arg: 'dmsTypeId',
arg: 'reference', type: 'number',
type: 'String', description: 'The dms type id',
required: true required: true
}, { },
arg: 'description', {
type: 'String', arg: 'reference',
required: true type: 'string',
}, { required: true
arg: 'hasFile', },
type: 'Boolean', {
description: 'True if has an attached file', arg: 'description',
required: true type: 'string',
}], required: true
},
{
arg: 'hasFile',
type: 'boolean',
description: 'True if has an attached file',
required: true
}
],
returns: { returns: {
type: 'Object', type: 'object',
root: true root: true
}, },
http: { http: {
@ -46,31 +54,39 @@ module.exports = Self => {
} }
}); });
Self.uploadFile = async(ctx, id) => { Self.uploadFile = async(ctx, id, options) => {
const models = Self.app.models; const models = Self.app.models;
let tx;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
const promises = []; const promises = [];
const tx = await Self.beginTransaction({});
try { try {
const options = {transaction: tx}; const uploadedFiles = await models.Dms.uploadFile(ctx, myOptions);
const uploadedFiles = await models.Dms.uploadFile(ctx, options);
uploadedFiles.forEach(dms => { uploadedFiles.forEach(dms => {
const newClientDms = models.ClientDms.create({ const newClientDms = models.ClientDms.create({
clientFk: id, clientFk: id,
dmsFk: dms.id dmsFk: dms.id
}, options); }, myOptions);
promises.push(newClientDms); promises.push(newClientDms);
}); });
const resolvedPromises = await Promise.all(promises); const resolvedPromises = await Promise.all(promises);
await tx.commit(); if (tx) await tx.commit();
return resolvedPromises; return resolvedPromises;
} catch (err) { } catch (e) {
await tx.rollback(); if (tx) await tx.rollback();
throw err; throw e;
} }
}; };
}; };

View File

@ -1,17 +1,13 @@
module.exports = Self => { module.exports = Self => {
Self.remoteMethod('createWithInsurance', { Self.remoteMethod('createWithInsurance', {
description: 'Creates both classification and one insurance', description: 'Creates both classification and one insurance',
accepts: [{ accepts: [
arg: 'data', {
type: 'object', arg: 'data',
http: {source: 'body'} type: 'object',
}, { http: {source: 'body'}
arg: 'context',
type: 'object',
http: function(ctx) {
return ctx;
} }
}], ],
returns: { returns: {
root: true, root: true,
type: 'boolean' type: 'boolean'
@ -22,29 +18,36 @@ module.exports = Self => {
} }
}); });
Self.createWithInsurance = async(data, ctx) => { Self.createWithInsurance = async(data, options) => {
const tx = await Self.beginTransaction({});
const models = Self.app.models; const models = Self.app.models;
let tx;
const 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};
const newClassification = await Self.create({ const newClassification = await Self.create({
client: data.clientFk, client: data.clientFk,
started: data.started started: data.started
}, options); }, myOptions);
await models.CreditInsurance.create({ await models.CreditInsurance.create({
creditClassification: newClassification.id, creditClassification: newClassification.id,
credit: data.credit, credit: data.credit,
grade: data.grade grade: data.grade
}, options); }, myOptions);
await tx.commit(); if (tx) await tx.commit();
return newClassification; return newClassification;
} catch (e) { } catch (e) {
await tx.rollback(); if (tx) await tx.rollback();
throw e; throw e;
} }
}; };

View File

@ -1,64 +1,26 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
const LoopBackContext = require('loopback-context');
describe('Client createWithInsurance', () => { describe('Client createWithInsurance', () => {
const activeCtx = {
accessToken: {userId: 1101},
http: {
req: {
headers: {origin: 'http://localhost'}
}
}
};
const ctx = {req: activeCtx};
activeCtx.http.req.__ = value => {
return value;
};
it('should verify the classifications and insurances are untainted', async() => {
let classifications = await app.models.CreditClassification.find();
let insurances = await app.models.CreditInsurance.find();
expect(classifications.length).toEqual(5);
expect(insurances.length).toEqual(3);
});
it('should not create the insurance if couldnt create the classification', async() => {
let error;
let data = {clientFk: null, started: Date.now(), credit: 999, grade: 255};
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
active: activeCtx
});
await app.models.CreditClassification.createWithInsurance(data, ctx)
.catch(e => {
error = e;
});
expect(error.toString()).toBe('Error: ER_BAD_NULL_ERROR: Column \'client\' cannot be null');
let classifications = await app.models.CreditClassification.find();
let insurances = await app.models.CreditInsurance.find();
expect(classifications.length).toEqual(5);
expect(insurances.length).toEqual(3);
});
it('should create a new client credit classification with insurance', async() => { it('should create a new client credit classification with insurance', async() => {
let data = {clientFk: 1101, started: Date.now(), credit: 999, grade: 255}; const tx = await models.Client.beginTransaction({});
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
active: activeCtx
});
let result = await app.models.CreditClassification.createWithInsurance(data, ctx);
expect(result.client).toEqual(1101); try {
const options = {transaction: tx};
const data = {clientFk: 1101, started: Date.now(), credit: 999, grade: 255};
let classifications = await app.models.CreditClassification.find(); const result = await models.CreditClassification.createWithInsurance(data, options);
let insurances = await app.models.CreditInsurance.find();
expect(classifications.length).toEqual(6); expect(result.client).toEqual(1101);
expect(insurances.length).toEqual(4);
// restore const classifications = await models.CreditClassification.find();
await app.models.CreditClassification.destroyById(result.id); const insurances = await models.CreditInsurance.find();
expect(classifications.length).toEqual(6);
expect(insurances.length).toEqual(4);
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
}); });

View File

@ -1,14 +1,21 @@
const totalGreuge = require('../sumAmount'); const models = require('vn-loopback/server/server').models;
describe('Greuge totalGreuge()', () => { describe('Greuge totalGreuge()', () => {
it('should call the sumAmount method', async() => { it('should call the sumAmount method', async() => {
let clientFk = 1; const tx = await models.Client.beginTransaction({});
let self = jasmine.createSpyObj('self', ['remoteMethod', 'rawSql']);
self.rawSql.and.returnValue(Promise.resolve([{sumAmount: 6000}]));
totalGreuge(self);
let result = await self.sumAmount(clientFk); try {
const options = {transaction: tx};
expect(result).toBe(6000); const clientId = 1;
const result = await models.Client.sumAmount(clientId, options);
expect(result).toBe(6000);
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
}); });

View File

@ -18,10 +18,15 @@ module.exports = Self => {
} }
}); });
Self.sumAmount = async clientFk => { Self.sumAmount = async(clientFk, options) => {
let query = `SELECT SUM(amount) AS sumAmount FROM vn.greuge WHERE clientFk = ?`; const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const query = `SELECT SUM(amount) AS sumAmount FROM vn.greuge WHERE clientFk = ?`;
try { try {
let [response] = await Self.rawSql(query, [clientFk]); const [response] = await Self.rawSql(query, [clientFk], myOptions);
return response ? response.sumAmount : 0; return response ? response.sumAmount : 0;
} catch (e) { } catch (e) {

View File

@ -7,23 +7,25 @@ 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: 'clientId', arg: 'clientId',
type: 'Number', type: 'number',
description: 'The client id', description: 'The client id',
required: true, required: true,
}, { },
{
arg: 'companyId', arg: 'companyId',
type: 'Number', type: 'number',
description: 'The company id', description: 'The company id',
required: true, required: true,
} }
], ],
returns: { returns: {
type: ['Object'], type: ['object'],
root: true root: true
}, },
http: { http: {
@ -32,51 +34,56 @@ module.exports = Self => {
} }
}); });
Self.filter = async(filter, clientId, companyId) => { Self.filter = async(filter, clientId, companyId, options) => {
let stmt = new ParameterizedSQL( const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const stmt = new ParameterizedSQL(
`SELECT * FROM ( `SELECT * FROM (
SELECT SELECT
r.id, r.id,
r.isConciliate, r.isConciliate,
r.payed, r.payed,
r.workerFk, r.workerFk,
c.code company, c.code company,
r.created, r.created,
r.invoiceFk description, r.invoiceFk description,
NULL debit, NULL debit,
r.amountPaid credit, r.amountPaid credit,
r.bankFk, r.bankFk,
u.name userName, u.name userName,
r.clientFk, r.clientFk,
FALSE hasPdf, FALSE hasPdf,
FALSE isInvoice FALSE isInvoice
FROM vn.receipt r FROM vn.receipt r
LEFT JOIN vn.worker w ON w.id = r.workerFk LEFT JOIN vn.worker w ON w.id = r.workerFk
LEFT JOIN account.user u ON u.id = w.userFk LEFT JOIN account.user u ON u.id = w.userFk
JOIN vn.company c ON c.id = r.companyFk JOIN vn.company c ON c.id = r.companyFk
WHERE r.clientFk = ? AND r.companyFk = ? WHERE r.clientFk = ? AND r.companyFk = ?
UNION ALL UNION ALL
SELECT SELECT
i.id, i.id,
TRUE, TRUE,
i.issued, i.issued,
NULL, NULL,
c.code, c.code,
i.created, i.created,
i.ref, i.ref,
i.amount, i.amount,
NULL, NULL,
NULL, NULL,
NULL, NULL,
i.clientFk, i.clientFk,
i.hasPdf, i.hasPdf,
TRUE isInvoice TRUE isInvoice
FROM vn.invoiceOut i FROM vn.invoiceOut i
JOIN vn.company c ON c.id = i.companyFk JOIN vn.company c ON c.id = i.companyFk
WHERE i.clientFk = ? AND i.companyFk = ? WHERE i.clientFk = ? AND i.companyFk = ?
ORDER BY payed DESC, created DESC ORDER BY payed DESC, created DESC
) t ) t ORDER BY payed DESC, created DESC`,
ORDER BY payed DESC, created DESC`, [ [
clientId, clientId,
companyId, companyId,
clientId, clientId,
@ -85,6 +92,7 @@ module.exports = Self => {
); );
stmt.merge(Self.makeLimit(filter)); stmt.merge(Self.makeLimit(filter));
return await Self.rawStmt(stmt);
return Self.rawStmt(stmt, myOptions);
}; };
}; };

View File

@ -1,12 +1,22 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('receipt filter()', () => { describe('receipt filter()', () => {
it('should return the receipts', async() => { it('should return the receipts', async() => {
const filter = {limit: 20}; const tx = await models.Client.beginTransaction({});
const clientId = 1101;
const companyId = 442;
let result = await app.models.Receipt.filter(filter, clientId, companyId);
expect(result.length).toBeGreaterThan(0); try {
const options = {transaction: tx};
const filter = {limit: 20};
const clientId = 1101;
const companyId = 442;
const result = await models.Receipt.filter(filter, clientId, companyId, options);
expect(result.length).toBeGreaterThan(0);
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
}); });

View File

@ -21,14 +21,20 @@ module.exports = Self => {
} }
}); });
Self.hasActiveRecovery = async id => { Self.hasActiveRecovery = async(id, options) => {
let result = await Self.rawSql( const myOptions = {};
`SELECT count(*) AS hasActiveRecovery
FROM vn.recovery if (typeof options == 'object')
WHERE clientFk = ? Object.assign(myOptions, options);
AND IFNULL(finished,CURDATE()) >= CURDATE();`,
[id] const query = `
); SELECT count(*) AS hasActiveRecovery
return result[0].hasActiveRecovery != 0; FROM vn.recovery
WHERE clientFk = ?
AND IFNULL(finished,CURDATE()) >= CURDATE();
`;
const [result] = await Self.rawSql(query, [id], myOptions);
return result.hasActiveRecovery != 0;
}; };
}; };

View File

@ -1,15 +1,35 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('client hasActiveRecovery', () => { describe('client hasActiveRecovery', () => {
it(`should return false if the client doesn't owes`, async() => { it(`should return false if the client doesn't owes`, async() => {
let hasActiveRecovery = await app.models.Recovery.hasActiveRecovery(1101); const tx = await models.Client.beginTransaction({});
expect(hasActiveRecovery).toBeFalsy(); try {
const options = {transaction: tx};
const hasActiveRecovery = await models.Recovery.hasActiveRecovery(1101, options);
expect(hasActiveRecovery).toBeFalsy();
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
it('should return true if the client owes', async() => { it('should return true if the client owes', async() => {
let hasActiveRecovery = await app.models.Recovery.hasActiveRecovery(1102); const tx = await models.Client.beginTransaction({});
expect(hasActiveRecovery).toBeTruthy(); try {
const options = {transaction: tx};
const hasActiveRecovery = await models.Recovery.hasActiveRecovery(1102, options);
expect(hasActiveRecovery).toBeTruthy();
await tx.rollback();
} catch (e) {
await tx.rollback();
}
}); });
}); });

View File

@ -6,22 +6,24 @@ module.exports = Self => {
Self.remoteMethod('send', { Self.remoteMethod('send', {
description: 'Sends SMS to a destination phone', description: 'Sends SMS to a destination phone',
accessType: 'WRITE', accessType: 'WRITE',
accepts: [{ accepts: [
arg: 'destinationFk', {
type: 'Integer' arg: 'destinationFk',
}, type: 'integer'
{ },
arg: 'destination', {
type: 'String', arg: 'destination',
required: true, type: 'string',
}, required: true,
{ },
arg: 'message', {
type: 'String', arg: 'message',
required: true, type: 'string',
}], required: true,
}
],
returns: { returns: {
type: 'Object', type: 'object',
root: true root: true
}, },
http: { http: {
@ -82,6 +84,7 @@ module.exports = Self => {
}; };
const sms = await Self.create(newSms); const sms = await Self.create(newSms);
if (statusCode != 200) if (statusCode != 200)
throw new UserError(`We weren't able to send this SMS`); throw new UserError(`We weren't able to send this SMS`);

View File

@ -66,7 +66,7 @@ module.exports = Self => {
const model = models[modelName]; const model = models[modelName];
try { try {
let promises = []; const promises = [];
const targets = lines.map(line => { const targets = lines.map(line => {
return line[identifier]; return line[identifier];
@ -78,7 +78,7 @@ module.exports = Self => {
for (let target of targets) for (let target of targets)
promises.push(model.upsertWithWhere({id: target}, value, myOptions)); promises.push(model.upsertWithWhere({id: target}, value, myOptions));
const result = await Promise.all(promises, myOptions); const result = await Promise.all(promises);
if (tx) await tx.commit(); if (tx) await tx.commit();

View File

@ -1,8 +1,8 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('InvoiceIn filter()', () => { describe('InvoiceIn filter()', () => {
it('should return the invoice in matching supplier name', async() => { it('should return the invoice in matching supplier name', async() => {
const tx = await app.models.Entry.beginTransaction({}); const tx = await models.InvoiceIn.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
@ -12,7 +12,7 @@ describe('InvoiceIn filter()', () => {
} }
}; };
const result = await app.models.InvoiceIn.filter(ctx, {}, options); const result = await models.InvoiceIn.filter(ctx, {}, options);
expect(result.length).toEqual(5); expect(result.length).toEqual(5);
expect(result[0].supplierName).toEqual('Plants SL'); expect(result[0].supplierName).toEqual('Plants SL');
@ -25,7 +25,7 @@ describe('InvoiceIn filter()', () => {
}); });
it('should return the invoice in matching supplier reference', async() => { it('should return the invoice in matching supplier reference', async() => {
const tx = await app.models.Entry.beginTransaction({}); const tx = await models.InvoiceIn.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
@ -35,7 +35,7 @@ describe('InvoiceIn filter()', () => {
} }
}; };
const result = await app.models.InvoiceIn.filter(ctx, {}, options); const result = await models.InvoiceIn.filter(ctx, {}, options);
expect(result.length).toEqual(1); expect(result.length).toEqual(1);
expect(result[0].supplierRef).toEqual('1241'); expect(result[0].supplierRef).toEqual('1241');
@ -48,7 +48,7 @@ describe('InvoiceIn filter()', () => {
}); });
it('should return the invoice in matching the serial number', async() => { it('should return the invoice in matching the serial number', async() => {
const tx = await app.models.Entry.beginTransaction({}); const tx = await models.InvoiceIn.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
@ -58,7 +58,7 @@ describe('InvoiceIn filter()', () => {
} }
}; };
const result = await app.models.InvoiceIn.filter(ctx, {}, options); const result = await models.InvoiceIn.filter(ctx, {}, options);
expect(result.length).toEqual(1); expect(result.length).toEqual(1);
expect(result[0].serialNumber).toEqual(1002); expect(result[0].serialNumber).toEqual(1002);
@ -71,7 +71,7 @@ describe('InvoiceIn filter()', () => {
}); });
it('should return the invoice in matching the account', async() => { it('should return the invoice in matching the account', async() => {
const tx = await app.models.Entry.beginTransaction({}); const tx = await models.InvoiceIn.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
@ -81,7 +81,7 @@ describe('InvoiceIn filter()', () => {
} }
}; };
const result = await app.models.InvoiceIn.filter(ctx, {}, options); const result = await models.InvoiceIn.filter(ctx, {}, options);
expect(result.length).toEqual(5); expect(result.length).toEqual(5);
expect(result[0].account).toEqual('4000020002'); expect(result[0].account).toEqual('4000020002');
@ -94,7 +94,7 @@ describe('InvoiceIn filter()', () => {
}); });
it('should return the invoice in matching the awb code', async() => { it('should return the invoice in matching the awb code', async() => {
const tx = await app.models.Entry.beginTransaction({}); const tx = await models.InvoiceIn.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
@ -104,7 +104,7 @@ describe('InvoiceIn filter()', () => {
} }
}; };
const result = await app.models.InvoiceIn.filter(ctx, {}, options); const result = await models.InvoiceIn.filter(ctx, {}, options);
const firstRow = result[0]; const firstRow = result[0];
expect(result.length).toEqual(1); expect(result.length).toEqual(1);
@ -119,7 +119,7 @@ describe('InvoiceIn filter()', () => {
}); });
it('should return the invoice in matching the amount', async() => { it('should return the invoice in matching the amount', async() => {
const tx = await app.models.Entry.beginTransaction({}); const tx = await models.InvoiceIn.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
@ -129,7 +129,7 @@ describe('InvoiceIn filter()', () => {
} }
}; };
const result = await app.models.InvoiceIn.filter(ctx, {}, options); const result = await models.InvoiceIn.filter(ctx, {}, options);
expect(result.length).toEqual(1); expect(result.length).toEqual(1);
expect(result[0].amount).toEqual(64.23); expect(result[0].amount).toEqual(64.23);
@ -142,7 +142,7 @@ describe('InvoiceIn filter()', () => {
}); });
it('should return the invoice in matching "from" and "to"', async() => { it('should return the invoice in matching "from" and "to"', async() => {
const tx = await app.models.Entry.beginTransaction({}); const tx = await models.InvoiceIn.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
@ -155,7 +155,7 @@ describe('InvoiceIn filter()', () => {
args: {from, to} args: {from, to}
}; };
const result = await app.models.InvoiceIn.filter(ctx, {}, options); const result = await models.InvoiceIn.filter(ctx, {}, options);
expect(result.length).toEqual(6); expect(result.length).toEqual(6);
@ -167,7 +167,7 @@ describe('InvoiceIn filter()', () => {
}); });
it('should return the booked invoice in', async() => { it('should return the booked invoice in', async() => {
const tx = await app.models.Entry.beginTransaction({}); const tx = await models.InvoiceIn.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
@ -177,7 +177,7 @@ describe('InvoiceIn filter()', () => {
} }
}; };
const result = await app.models.InvoiceIn.filter(ctx, {}, options); const result = await models.InvoiceIn.filter(ctx, {}, options);
expect(result.length).toEqual(6); expect(result.length).toEqual(6);
expect(result[0].isBooked).toBeTruthy(); expect(result[0].isBooked).toBeTruthy();

View File

@ -1,12 +1,12 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('invoiceIn summary()', () => { describe('invoiceIn summary()', () => {
it('should return a summary object containing data from one invoiceIn', async() => { it('should return a summary object containing data from one invoiceIn', async() => {
const tx = await app.models.Entry.beginTransaction({}); const tx = await models.InvoiceIn.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
const summary = await app.models.InvoiceIn.summary(1, options); const summary = await models.InvoiceIn.summary(1, options);
expect(summary.supplierRef).toEqual('1234'); expect(summary.supplierRef).toEqual('1234');

View File

@ -22,7 +22,7 @@ module.exports = Self => {
Self.delete = async(id, options) => { Self.delete = async(id, options) => {
let tx; let tx;
let myOptions = {}; const myOptions = {};
if (typeof options == 'object') if (typeof options == 'object')
Object.assign(myOptions, options); Object.assign(myOptions, options);
@ -42,7 +42,7 @@ module.exports = Self => {
promises.push(ticket.updateAttribute('refFk', null, myOptions)); promises.push(ticket.updateAttribute('refFk', null, myOptions));
}); });
await Promise.all(promises, myOptions); await Promise.all(promises);
await invoiceOut.destroy(myOptions); await invoiceOut.destroy(myOptions);

View File

@ -1,20 +1,20 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('invoiceOut book()', () => { describe('invoiceOut book()', () => {
const invoiceOutId = 5; const invoiceOutId = 5;
it('should update the booked property', async() => { it('should update the booked property', async() => {
const tx = await app.models.InvoiceOut.beginTransaction({}); const tx = await models.InvoiceOut.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
const originalInvoiceOut = await app.models.InvoiceOut.findById(invoiceOutId, {}, options); const originalInvoiceOut = await models.InvoiceOut.findById(invoiceOutId, {}, options);
const bookedDate = originalInvoiceOut.booked; const bookedDate = originalInvoiceOut.booked;
const invoiceOutRef = originalInvoiceOut.ref; const invoiceOutRef = originalInvoiceOut.ref;
await app.models.InvoiceOut.book(invoiceOutRef, options); await models.InvoiceOut.book(invoiceOutRef, options);
const updatedInvoiceOut = await app.models.InvoiceOut.findById(invoiceOutId, {}, options); const updatedInvoiceOut = await models.InvoiceOut.findById(invoiceOutId, {}, options);
expect(updatedInvoiceOut.booked).not.toEqual(bookedDate); expect(updatedInvoiceOut.booked).not.toEqual(bookedDate);
expect(updatedInvoiceOut.hasPdf).toBeFalsy(); expect(updatedInvoiceOut.hasPdf).toBeFalsy();

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
const got = require('got'); const got = require('got');
describe('InvoiceOut createPdf()', () => { describe('InvoiceOut createPdf()', () => {
@ -19,7 +19,7 @@ describe('InvoiceOut createPdf()', () => {
}; };
spyOn(got, 'stream').and.returnValue(response); spyOn(got, 'stream').and.returnValue(response);
let result = await app.models.InvoiceOut.createPdf(ctx, invoiceId); const result = await models.InvoiceOut.createPdf(ctx, invoiceId);
expect(result.hasPdf).toBe(true); expect(result.hasPdf).toBe(true);
}); });

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'); const LoopBackContext = require('loopback-context');
describe('invoiceOut delete()', () => { describe('invoiceOut delete()', () => {
@ -9,12 +9,12 @@ describe('invoiceOut delete()', () => {
}; };
it('should check that there is one ticket in the target invoiceOut', async() => { it('should check that there is one ticket in the target invoiceOut', async() => {
const tx = await app.models.InvoiceOut.beginTransaction({}); const tx = await models.InvoiceOut.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
const invoiceOut = await app.models.InvoiceOut.findById(invoiceOutId, {}, options); const invoiceOut = await models.InvoiceOut.findById(invoiceOutId, {}, options);
const tickets = await app.models.Ticket.find({where: {refFk: invoiceOut.ref}}, options); const tickets = await models.Ticket.find({where: {refFk: invoiceOut.ref}}, options);
expect(tickets.length).toEqual(1); expect(tickets.length).toEqual(1);
expect(tickets[0].id).toEqual(3); expect(tickets[0].id).toEqual(3);
@ -27,7 +27,7 @@ describe('invoiceOut delete()', () => {
}); });
it(`should delete the target invoiceOut then check the ticket doesn't have a refFk anymore`, async() => { it(`should delete the target invoiceOut then check the ticket doesn't have a refFk anymore`, async() => {
const tx = await app.models.InvoiceOut.beginTransaction({}); const tx = await models.InvoiceOut.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
@ -35,11 +35,11 @@ describe('invoiceOut delete()', () => {
active: activeCtx active: activeCtx
}); });
await app.models.InvoiceOut.delete(invoiceOutId, options); await models.InvoiceOut.delete(invoiceOutId, options);
const originalTicket = await app.models.Ticket.findById(3, {}, options); const originalTicket = await models.Ticket.findById(3, {}, options);
const deletedInvoiceOut = await app.models.InvoiceOut.findById(invoiceOutId, {}, options); const deletedInvoiceOut = await models.InvoiceOut.findById(invoiceOutId, {}, options);
expect(deletedInvoiceOut).toBeNull(); expect(deletedInvoiceOut).toBeNull();
expect(originalTicket.refFk).toBeNull(); expect(originalTicket.refFk).toBeNull();

View File

@ -1,8 +1,8 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('InvoiceOut download()', () => { describe('InvoiceOut download()', () => {
it('should return the downloaded fine name', async() => { it('should return the downloaded fine name', async() => {
let result = await app.models.InvoiceOut.download(1); const result = await models.InvoiceOut.download(1);
expect(result[1]).toEqual('text/plain'); expect(result[1]).toEqual('text/plain');
expect(result[2]).toEqual('filename="README.md"'); expect(result[2]).toEqual('filename="README.md"');

View File

@ -1,11 +1,11 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('InvoiceOut filter()', () => { describe('InvoiceOut filter()', () => {
let today = new Date(); let today = new Date();
today.setHours(2, 0, 0, 0); today.setHours(2, 0, 0, 0);
it('should return the invoice out matching ref', async() => { it('should return the invoice out matching ref', async() => {
const tx = await app.models.InvoiceOut.beginTransaction({}); const tx = await models.InvoiceOut.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
@ -15,7 +15,7 @@ describe('InvoiceOut filter()', () => {
} }
}; };
const result = await app.models.InvoiceOut.filter(ctx, {}, options); const result = await models.InvoiceOut.filter(ctx, {}, options);
expect(result.length).toEqual(1); expect(result.length).toEqual(1);
expect(result[0].ref).toEqual('T4444444'); expect(result[0].ref).toEqual('T4444444');
@ -28,7 +28,7 @@ describe('InvoiceOut filter()', () => {
}); });
it('should return the invoice out matching clientFk', async() => { it('should return the invoice out matching clientFk', async() => {
const tx = await app.models.InvoiceOut.beginTransaction({}); const tx = await models.InvoiceOut.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
@ -38,7 +38,7 @@ describe('InvoiceOut filter()', () => {
} }
}; };
const result = await app.models.InvoiceOut.filter(ctx, {}, options); const result = await models.InvoiceOut.filter(ctx, {}, options);
expect(result.length).toEqual(1); expect(result.length).toEqual(1);
expect(result[0].ref).toEqual('T2222222'); expect(result[0].ref).toEqual('T2222222');
@ -51,7 +51,7 @@ describe('InvoiceOut filter()', () => {
}); });
it('should return the invoice out matching hasPdf', async() => { it('should return the invoice out matching hasPdf', async() => {
const tx = await app.models.InvoiceOut.beginTransaction({}); const tx = await models.InvoiceOut.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
@ -61,7 +61,7 @@ describe('InvoiceOut filter()', () => {
} }
}; };
const result = await app.models.InvoiceOut.filter(ctx, {}, options); const result = await models.InvoiceOut.filter(ctx, {}, options);
expect(result.length).toEqual(5); expect(result.length).toEqual(5);
@ -73,7 +73,7 @@ describe('InvoiceOut filter()', () => {
}); });
it('should return the invoice out matching amount', async() => { it('should return the invoice out matching amount', async() => {
const tx = await app.models.InvoiceOut.beginTransaction({}); const tx = await models.InvoiceOut.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
@ -83,7 +83,7 @@ describe('InvoiceOut filter()', () => {
} }
}; };
const result = await app.models.InvoiceOut.filter(ctx, {}, options); const result = await models.InvoiceOut.filter(ctx, {}, options);
expect(result.length).toEqual(1); expect(result.length).toEqual(1);
expect(result[0].ref).toEqual('T2222222'); expect(result[0].ref).toEqual('T2222222');
@ -96,7 +96,7 @@ describe('InvoiceOut filter()', () => {
}); });
it('should return the invoice out matching min and max', async() => { it('should return the invoice out matching min and max', async() => {
const tx = await app.models.InvoiceOut.beginTransaction({}); const tx = await models.InvoiceOut.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
@ -107,7 +107,7 @@ describe('InvoiceOut filter()', () => {
} }
}; };
let result = await app.models.InvoiceOut.filter(ctx, {}, options); let result = await models.InvoiceOut.filter(ctx, {}, options);
expect(result.length).toEqual(3); expect(result.length).toEqual(3);

View File

@ -1,13 +1,13 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('entry getTickets()', () => { describe('entry getTickets()', () => {
const invoiceOutId = 4; const invoiceOutId = 4;
it('should get the ticket of an invoiceOut', async() => { it('should get the ticket of an invoiceOut', async() => {
const tx = await app.models.InvoiceOut.beginTransaction({}); const tx = await models.InvoiceOut.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
const result = await app.models.InvoiceOut.getTickets(invoiceOutId, {}, options); const result = await models.InvoiceOut.getTickets(invoiceOutId, {}, options);
expect(result.length).toEqual(1); expect(result.length).toEqual(1);

View File

@ -1,12 +1,12 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('invoiceOut summary()', () => { describe('invoiceOut summary()', () => {
it('should return a summary object containing data from one invoiceOut', async() => { it('should return a summary object containing data from one invoiceOut', async() => {
const tx = await app.models.InvoiceOut.beginTransaction({}); const tx = await models.InvoiceOut.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
const result = await app.models.InvoiceOut.summary(1, options); const result = await models.InvoiceOut.summary(1, options);
expect(result.invoiceOut.id).toEqual(1); expect(result.invoiceOut.id).toEqual(1);
@ -18,11 +18,11 @@ describe('invoiceOut summary()', () => {
}); });
it(`should return a summary object containing it's supplier country`, async() => { it(`should return a summary object containing it's supplier country`, async() => {
const tx = await app.models.InvoiceOut.beginTransaction({}); const tx = await models.InvoiceOut.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
const summary = await app.models.InvoiceOut.summary(1, options); const summary = await models.InvoiceOut.summary(1, options);
const supplier = summary.invoiceOut.supplier(); const supplier = summary.invoiceOut.supplier();
expect(summary.invoiceOut.ref).toEqual('T1111111'); expect(summary.invoiceOut.ref).toEqual('T1111111');
@ -37,11 +37,11 @@ describe('invoiceOut summary()', () => {
}); });
it(`should return a summary object containing idata from it's tax types`, async() => { it(`should return a summary object containing idata from it's tax types`, async() => {
const tx = await app.models.InvoiceOut.beginTransaction({}); const tx = await models.InvoiceOut.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
const summary = await app.models.InvoiceOut.summary(1, options); const summary = await models.InvoiceOut.summary(1, options);
expect(summary.invoiceOut.ref).toEqual('T1111111'); expect(summary.invoiceOut.ref).toEqual('T1111111');
expect(summary.invoiceOut.taxesBreakdown.length).toEqual(2); expect(summary.invoiceOut.taxesBreakdown.length).toEqual(2);

View File

@ -80,12 +80,12 @@ module.exports = Self => {
}, },
{ {
arg: 'mine', arg: 'mine',
type: 'Boolean', type: 'boolean',
description: `Search requests attended by the current user` description: `Search requests attended by the current user`
} }
], ],
returns: { returns: {
type: ['Object'], type: ['object'],
root: true root: true
}, },
http: { http: {
@ -94,9 +94,13 @@ module.exports = Self => {
} }
}); });
Self.filter = async(ctx, filter) => { Self.filter = async(ctx, filter, options) => {
const 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.buyerFk = userId; ctx.args.buyerFk = userId;
@ -128,36 +132,35 @@ module.exports = Self => {
filter = mergeFilters(filter, {where}); filter = mergeFilters(filter, {where});
const stmts = []; const stmts = [];
let stmt;
stmt = new ParameterizedSQL( const stmt = new ParameterizedSQL(`
`SELECT fp.id, SELECT fp.id,
fp.itemFk, fp.itemFk,
fp.warehouseFk, fp.warehouseFk,
fp.rate2, fp.rate2,
fp.rate3, fp.rate3,
fp.started, fp.started,
fp.ended, fp.ended,
i.minPrice, i.minPrice,
i.hasMinPrice, i.hasMinPrice,
i.name, i.name,
i.subName, i.subName,
i.tag5, i.tag5,
i.value5, i.value5,
i.tag6, i.tag6,
i.value6, i.value6,
i.tag7, i.tag7,
i.value7, i.value7,
i.tag8, i.tag8,
i.value8, i.value8,
i.tag9, i.tag9,
i.value9, i.value9,
i.tag10, i.tag10,
i.value10 i.value10
FROM priceFixed fp FROM priceFixed fp
JOIN item i ON i.id = fp.itemFk JOIN item i ON i.id = fp.itemFk
JOIN itemType it ON it.id = i.typeFk` JOIN itemType it ON it.id = i.typeFk
); `);
if (ctx.args.tags) { if (ctx.args.tags) {
let i = 1; let i = 1;
@ -186,7 +189,8 @@ module.exports = Self => {
const fixedPriceIndex = stmts.push(stmt) - 1; const fixedPriceIndex = stmts.push(stmt) - 1;
const sql = ParameterizedSQL.join(stmts, ';'); const sql = ParameterizedSQL.join(stmts, ';');
const result = await conn.executeStmt(sql); const result = await conn.executeStmt(sql, myOptions);
return fixedPriceIndex === 0 ? result : result[fixedPriceIndex]; return fixedPriceIndex === 0 ? result : result[fixedPriceIndex];
}; };
}; };

View File

@ -1,86 +1,136 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('fixed price filter()', () => { describe('fixed price filter()', () => {
it('should return 1 result filtering by item ID', async() => { it('should return 1 result filtering by item ID', async() => {
const itemID = 3; const tx = await models.FixedPrice.beginTransaction({});
const ctx = {
req: {accessToken: {userId: 1}},
args: {
search: itemID
}
};
const result = await app.models.FixedPrice.filter(ctx);
expect(result.length).toEqual(1); try {
expect(result[0].id).toEqual(2); const options = {transaction: tx};
expect(result[0].itemFk).toEqual(itemID); const itemID = 3;
const ctx = {
req: {accessToken: {userId: 1}},
args: {
search: itemID
}
};
const result = await models.FixedPrice.filter(ctx, null, options);
expect(result.length).toEqual(1);
expect(result[0].id).toEqual(2);
expect(result[0].itemFk).toEqual(itemID);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should return 1 result filtering by item type code', async() => { it('should return 1 result filtering by item type code', async() => {
const itemCode = 'CRI'; const tx = await models.FixedPrice.beginTransaction({});
const ctx = {
req: {accessToken: {userId: 1}},
args: {
search: itemCode
}
};
const itemType = await app.models.ItemType.findOne({
where: {code: itemCode},
fields: ['id']
});
const items = await app.models.Item.find({
where: {typeFk: itemType.id},
fields: ['id']
});
const IDs = items.map(item => {
return item.id;
});
const result = await app.models.FixedPrice.filter(ctx); try {
const firstResult = result[0]; const options = {transaction: tx};
const itemCode = 'CRI';
const ctx = {
req: {accessToken: {userId: 1}},
args: {
search: itemCode
}
};
const itemType = await models.ItemType.findOne({
where: {code: itemCode},
fields: ['id']
}, options);
const items = await models.Item.find({
where: {typeFk: itemType.id},
fields: ['id']
}, options);
const IDs = items.map(item => {
return item.id;
});
expect(result.length).toEqual(1); const result = await models.FixedPrice.filter(ctx, null, options);
expect(firstResult.id).toEqual(2); const firstResult = result[0];
expect(IDs).toContain(firstResult.itemFk);
expect(result.length).toEqual(1);
expect(firstResult.id).toEqual(2);
expect(IDs).toContain(firstResult.itemFk);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should return 2 results filtering by warehouse', async() => { it('should return 2 results filtering by warehouse', async() => {
const warehouseID = 1; const tx = await models.FixedPrice.beginTransaction({});
const ctx = {
req: {accessToken: {userId: 1}},
args: {
warehouseFk: warehouseID
}
};
const result = await app.models.FixedPrice.filter(ctx);
const length = result.length;
const anyResult = result[Math.floor(Math.random() * Math.floor(length))];
expect(result.length).toEqual(2); try {
expect(anyResult.warehouseFk).toEqual(warehouseID); const options = {transaction: tx};
const warehouseID = 1;
const ctx = {
req: {accessToken: {userId: 1}},
args: {
warehouseFk: warehouseID
}
};
const result = await models.FixedPrice.filter(ctx, null, options);
const length = result.length;
const anyResult = result[Math.floor(Math.random() * Math.floor(length))];
expect(result.length).toEqual(2);
expect(anyResult.warehouseFk).toEqual(warehouseID);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should return no results filtering by hasMinPrice', async() => { it('should return no results filtering by hasMinPrice', async() => {
const ctx = { const tx = await models.FixedPrice.beginTransaction({});
req: {accessToken: {userId: 1}},
args: {
hasMinPrice: true
}
};
const result = await app.models.FixedPrice.filter(ctx);
expect(result.length).toEqual(0); try {
const options = {transaction: tx};
const ctx = {
req: {accessToken: {userId: 1}},
args: {
hasMinPrice: true
}
};
const result = await models.FixedPrice.filter(ctx, null, options);
expect(result.length).toEqual(0);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should return no results filtering by typeFk', async() => { it('should return no results filtering by typeFk', async() => {
const ctx = { const tx = await models.FixedPrice.beginTransaction({});
req: {accessToken: {userId: 1}},
args: {
typeFk: 1
}
};
const result = await app.models.FixedPrice.filter(ctx);
expect(result.length).toEqual(1); try {
const options = {transaction: tx};
const ctx = {
req: {accessToken: {userId: 1}},
args: {
typeFk: 1
}
};
const result = await models.FixedPrice.filter(ctx, null, options);
expect(result.length).toEqual(1);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -1,62 +1,75 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('upsertFixedPrice()', () => { describe('upsertFixedPrice()', () => {
const now = new Date(); const now = new Date();
const fixedPriceId = 1; const fixedPriceId = 1;
let originalFixedPrice; let originalFixedPrice;
let originalItem;
beforeAll(async() => { beforeAll(async() => {
originalFixedPrice = await app.models.FixedPrice.findById(fixedPriceId); originalFixedPrice = await models.FixedPrice.findById(fixedPriceId);
originalItem = await app.models.Item.findById(originalFixedPrice.itemFk);
});
afterAll(async() => {
await originalFixedPrice.save();
await originalItem.save();
}); });
it(`should toggle the hasMinPrice boolean if there's a minPrice and update the rest of the data`, async() => { it(`should toggle the hasMinPrice boolean if there's a minPrice and update the rest of the data`, async() => {
const ctx = {args: { const tx = await models.FixedPrice.beginTransaction({});
id: fixedPriceId,
itemFk: originalFixedPrice.itemFk,
warehouseFk: 1,
rate2: 100,
rate3: 300,
started: now,
ended: now,
minPrice: 100,
hasMinPrice: false
}};
const result = await app.models.FixedPrice.upsertFixedPrice(ctx, ctx.args.id); try {
const options = {transaction: tx};
const ctx = {args: {
id: fixedPriceId,
itemFk: originalFixedPrice.itemFk,
warehouseFk: 1,
rate2: 100,
rate3: 300,
started: now,
ended: now,
minPrice: 100,
hasMinPrice: false
}};
delete ctx.args.started; const result = await models.FixedPrice.upsertFixedPrice(ctx, options);
delete ctx.args.ended;
ctx.args.hasMinPrice = true;
expect(result).toEqual(jasmine.objectContaining(ctx.args)); delete ctx.args.started;
delete ctx.args.ended;
ctx.args.hasMinPrice = true;
expect(result).toEqual(jasmine.objectContaining(ctx.args));
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it(`should toggle the hasMinPrice boolean if there's no minPrice and update the rest of the data`, async() => { it(`should toggle the hasMinPrice boolean if there's no minPrice and update the rest of the data`, async() => {
const ctx = {args: { const tx = await models.FixedPrice.beginTransaction({});
id: fixedPriceId,
itemFk: originalFixedPrice.itemFk,
warehouseFk: 1,
rate2: 2.5,
rate3: 2,
started: now,
ended: now,
minPrice: 0,
hasMinPrice: true
}};
const result = await app.models.FixedPrice.upsertFixedPrice(ctx, ctx.args.id); try {
const options = {transaction: tx};
const ctx = {args: {
id: fixedPriceId,
itemFk: originalFixedPrice.itemFk,
warehouseFk: 1,
rate2: 2.5,
rate3: 2,
started: now,
ended: now,
minPrice: 0,
hasMinPrice: true
}};
delete ctx.args.started; const result = await models.FixedPrice.upsertFixedPrice(ctx, options);
delete ctx.args.ended;
ctx.args.hasMinPrice = false;
expect(result).toEqual(jasmine.objectContaining(ctx.args)); delete ctx.args.started;
delete ctx.args.ended;
ctx.args.hasMinPrice = false;
expect(result).toEqual(jasmine.objectContaining(ctx.args));
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -2,48 +2,50 @@ module.exports = Self => {
Self.remoteMethod('upsertFixedPrice', { Self.remoteMethod('upsertFixedPrice', {
description: 'Inserts or updates a fixed price for an item', description: 'Inserts or updates a fixed price for an item',
accessType: 'WRITE', accessType: 'WRITE',
accepts: [{ accepts: [
arg: 'ctx', {
type: 'object', arg: 'ctx',
http: {source: 'context'} type: 'object',
}, http: {source: 'context'}
{ },
arg: 'id', {
type: 'number', arg: 'id',
description: 'The fixed price id' type: 'number',
}, description: 'The fixed price id'
{ },
arg: 'itemFk', {
type: 'number' arg: 'itemFk',
}, type: 'number'
{ },
arg: 'warehouseFk', {
type: 'number' arg: 'warehouseFk',
}, type: 'number'
{ },
arg: 'started', {
type: 'date' arg: 'started',
}, type: 'date'
{ },
arg: 'ended', {
type: 'date' arg: 'ended',
}, type: 'date'
{ },
arg: 'rate2', {
type: 'number' arg: 'rate2',
}, type: 'number'
{ },
arg: 'rate3', {
type: 'number' arg: 'rate3',
}, type: 'number'
{ },
arg: 'minPrice', {
type: 'number' arg: 'minPrice',
}, type: 'number'
{ },
arg: 'hasMinPrice', {
type: 'any' arg: 'hasMinPrice',
}], type: 'any'
}
],
returns: { returns: {
type: 'object', type: 'object',
root: true root: true
@ -54,21 +56,29 @@ module.exports = Self => {
} }
}); });
Self.upsertFixedPrice = async ctx => { Self.upsertFixedPrice = async(ctx, options) => {
const models = Self.app.models; const models = Self.app.models;
const args = ctx.args; const args = ctx.args;
const tx = await models.Address.beginTransaction({}); let tx;
try { const myOptions = {};
const options = {transaction: tx};
delete args.ctx; // removed unwanted data if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
delete args.ctx; // removed unwanted data
const fixedPrice = await models.FixedPrice.upsert(args, myOptions);
const targetItem = await models.Item.findById(args.itemFk, null, myOptions);
const fixedPrice = await models.FixedPrice.upsert(args, options);
const targetItem = await models.Item.findById(args.itemFk, null, options);
await targetItem.updateAttributes({ await targetItem.updateAttributes({
minPrice: args.minPrice, minPrice: args.minPrice,
hasMinPrice: args.minPrice ? true : false hasMinPrice: args.minPrice ? true : false
}, options); }, myOptions);
const itemFields = [ const itemFields = [
'minPrice', 'minPrice',
@ -99,16 +109,17 @@ module.exports = Self => {
} }
}; };
const result = await models.FixedPrice.findById(fixedPrice.id, filter, options); const result = await models.FixedPrice.findById(fixedPrice.id, filter, myOptions);
const item = result.item(); const item = result.item();
for (let key of itemFields) for (let key of itemFields)
result[key] = item[key]; result[key] = item[key];
await tx.commit(); if (tx) await tx.commit();
return result; return result;
} catch (e) { } catch (e) {
await tx.rollback(); if (tx) await tx.rollback();
throw e; throw e;
} }
}; };

View File

@ -1,10 +1,20 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('item-barcode toItem()', () => { describe('item-barcode toItem()', () => {
it('should return the same number if there is a barcode and a item with the same ID', async() => { it('should return the same number if there is a barcode and a item with the same ID', async() => {
let barcode = 3; const tx = await models.Item.beginTransaction({});
let result = await app.models.ItemBarcode.toItem(barcode); const options = {transaction: tx};
expect(result).toBe(3); try {
const barcode = 3;
const result = await models.ItemBarcode.toItem(barcode, options);
expect(result).toBe(3);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -4,12 +4,12 @@ module.exports = Self => {
accessType: 'READ', accessType: 'READ',
accepts: [{ accepts: [{
arg: 'barcode', arg: 'barcode',
type: 'Number', type: 'number',
required: true, required: true,
description: 'barcode' description: 'barcode'
}], }],
returns: { returns: {
type: 'Number', type: 'number',
root: true root: true
}, },
http: { http: {
@ -18,11 +18,18 @@ module.exports = Self => {
} }
}); });
Self.toItem = async barcode => { Self.toItem = async(barcode, options) => {
let query = `SELECT vn.barcodeToItem(?)`; const myOptions = {};
let [item] = await Self.rawSql(query, [barcode]);
if (typeof options == 'object')
Object.assign(myOptions, options);
const query = `SELECT vn.barcodeToItem(?)`;
let [item] = await Self.rawSql(query, [barcode], myOptions);
if (item) if (item)
item = Object.values(item); item = Object.values(item)[0];
return item[0];
return item;
}; };
}; };

View File

@ -5,17 +5,19 @@ module.exports = Self => {
Self.remoteMethod('filterItemTags', { Self.remoteMethod('filterItemTags', {
description: 'Returns the distinct values of a tag property', description: 'Returns the distinct values of a tag property',
accessType: 'READ', accessType: 'READ',
accepts: [{ accepts: [
arg: 'tagFk', {
type: 'number', arg: 'tagFk',
required: true, type: 'number',
description: 'The foreign key from tag table', required: true,
http: {source: 'path'} description: 'The foreign key from tag table',
}, { http: {source: 'path'}
arg: 'filter', }, {
type: 'Object', arg: 'filter',
description: `Filter defining where, order, offset, and limit - must be a JSON-encoded string` type: 'object',
}], description: `Filter defining where, order, offset, and limit - must be a JSON-encoded string`
}
],
returns: { returns: {
root: true, root: true,
type: ['object'] type: ['object']
@ -26,16 +28,21 @@ module.exports = Self => {
} }
}); });
Self.filterItemTags = async(tagFk, filter) => { Self.filterItemTags = async(tagFk, filter, options) => {
let conn = Self.dataSource.connector; const conn = Self.dataSource.connector;
let where = {tagFk: tagFk}; const myOptions = {};
myFilter = mergeFilters(filter, {where});
if (typeof options == 'object')
Object.assign(myOptions, options);
const where = {tagFk: tagFk};
const myFilter = mergeFilters(filter, {where});
stmt = new ParameterizedSQL( stmt = new ParameterizedSQL(
`SELECT DISTINCT(value) `SELECT DISTINCT(value)
FROM itemTag`); FROM itemTag`);
stmt.merge(conn.makeSuffix(myFilter)); stmt.merge(conn.makeSuffix(myFilter));
return await conn.executeStmt(stmt); return conn.executeStmt(stmt, myOptions);
}; };
}; };

View File

@ -1,9 +1,19 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('item filterItemTags()', () => { describe('item filterItemTags()', () => {
it('should filter ItemTags table', async() => { it('should filter ItemTags table', async() => {
let [result] = await app.models.ItemTag.filterItemTags(1, {}); const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
expect(result.value).toEqual('Black'); try {
const [result] = await models.ItemTag.filterItemTags(1, null, options);
expect(result.value).toEqual('Black');
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -12,7 +12,7 @@ module.exports = Self => {
http: {source: 'path'} http: {source: 'path'}
}], }],
returns: { returns: {
type: 'Object', type: 'object',
description: 'new cloned itemId', description: 'new cloned itemId',
root: true, root: true,
}, },
@ -22,13 +22,21 @@ module.exports = Self => {
} }
}); });
Self.clone = async itemId => { Self.clone = async(itemId, options) => {
let tx = await Self.beginTransaction({}); let tx;
const 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}; const origin = await Self.findById(itemId, null, myOptions);
const origin = await Self.findById(itemId, null, options);
if (!origin) if (!origin)
throw new UserError(`This item doesn't exists`); throw new UserError(`This item doesn't exists`);
@ -38,16 +46,17 @@ module.exports = Self => {
origin.comment = undefined; origin.comment = undefined;
origin.size = undefined; origin.size = undefined;
const newItem = await Self.create(origin, options); const newItem = await Self.create(origin, myOptions);
await cloneTaxes(origin.id, newItem.id, options); await cloneTaxes(origin.id, newItem.id, myOptions);
await cloneBotanical(origin.id, newItem.id, options); await cloneBotanical(origin.id, newItem.id, myOptions);
await cloneTags(origin.id, newItem.id, options); await cloneTags(origin.id, newItem.id, myOptions);
if (tx) await tx.commit();
await tx.commit();
return newItem; return newItem;
} catch (e) { } catch (e) {
await tx.rollback(); if (tx) await tx.rollback();
throw e; throw e;
} }
}; };

View File

@ -2,23 +2,25 @@ module.exports = Self => {
Self.remoteMethod('createIntrastat', { Self.remoteMethod('createIntrastat', {
description: 'Creates a new item intrastat', description: 'Creates a new item intrastat',
accessType: 'WRITE', accessType: 'WRITE',
accepts: [{ accepts: [
arg: 'id', {
type: 'number', arg: 'id',
required: true, type: 'number',
description: 'The item id', required: true,
http: {source: 'path'} description: 'The item id',
}, http: {source: 'path'}
{ },
arg: 'intrastatId', {
type: 'number', arg: 'intrastatId',
required: true type: 'number',
}, required: true
{ },
arg: 'description', {
type: 'string', arg: 'description',
required: true type: 'string',
}], required: true
}
],
returns: { returns: {
type: 'boolean', type: 'boolean',
root: true root: true
@ -29,11 +31,16 @@ module.exports = Self => {
} }
}); });
Self.createIntrastat = async(id, intrastatId, description) => { Self.createIntrastat = async(id, intrastatId, description, options) => {
const models = Self.app.models; const models = Self.app.models;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const country = await models.Country.findOne({ const country = await models.Country.findOne({
where: {code: 'ES'} where: {code: 'ES'}
}); }, myOptions);
const itemTaxCountry = await models.ItemTaxCountry.findOne({ const itemTaxCountry = await models.ItemTaxCountry.findOne({
where: { where: {
@ -41,19 +48,22 @@ module.exports = Self => {
countryFk: country.id countryFk: country.id
}, },
order: 'effectived DESC' order: 'effectived DESC'
}); }, myOptions);
const taxClassCode = await models.TaxClassCode.findOne({ const taxClassCode = await models.TaxClassCode.findOne({
where: { where: {
taxClassFk: itemTaxCountry.taxClassFk taxClassFk: itemTaxCountry.taxClassFk
}, },
order: 'effectived DESC' order: 'effectived DESC'
}); }, myOptions);
return models.Intrastat.create({ const intrastat = await models.Intrastat.create({
id: intrastatId, id: intrastatId,
description: description, description: description,
taxClassFk: itemTaxCountry.taxClassFk, taxClassFk: itemTaxCountry.taxClassFk,
taxCodeFk: taxClassCode.taxCodeFk taxCodeFk: taxClassCode.taxCodeFk
}); }, myOptions);
return intrastat;
}; };
}; };

View File

@ -71,7 +71,7 @@ module.exports = Self => {
Self.filter = async(ctx, filter, options) => { Self.filter = async(ctx, filter, options) => {
const conn = Self.dataSource.connector; const conn = Self.dataSource.connector;
let myOptions = {}; const myOptions = {};
if (typeof options == 'object') if (typeof options == 'object')
Object.assign(myOptions, options); Object.assign(myOptions, options);
@ -83,7 +83,9 @@ module.exports = Self => {
where: {code: ctx.args.search}, where: {code: ctx.args.search},
fields: ['itemFk'] fields: ['itemFk']
}, myOptions); }, myOptions);
const itemIds = []; const itemIds = [];
for (const item of items) for (const item of items)
itemIds.push(item.itemFk); itemIds.push(item.itemFk);
@ -116,12 +118,11 @@ module.exports = Self => {
return {'intr.description': value}; return {'intr.description': value};
} }
}); });
filter = mergeFilters(filter, {where}); filter = mergeFilters(filter, {where});
const stmts = []; const stmts = [];
let stmt; const stmt = new ParameterizedSQL(
stmt = new ParameterizedSQL(
`SELECT `SELECT
i.id, i.id,
i.image, i.image,

View File

@ -19,9 +19,15 @@ module.exports = Self => {
} }
}); });
Self.getBalance = async filter => { Self.getBalance = async(filter, options) => {
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const where = filter.where; const where = filter.where;
let [diary] = await Self.rawSql(`CALL vn.item_getBalance(?, ?)`, [where.itemFk, where.warehouseFk]); const query = 'CALL vn.item_getBalance(?, ?)';
const [diary] = await Self.rawSql(query, [where.itemFk, where.warehouseFk], myOptions);
for (const entry of diary) for (const entry of diary)
if (entry.clientType === 'loses') entry.highlighted = true; if (entry.clientType === 'loses') entry.highlighted = true;

View File

@ -19,12 +19,13 @@ module.exports = Self => {
} }
}); });
Self.getCard = async id => { Self.getCard = async(id, options) => {
let item = {}; const myOptions = {};
// Item basic data if (typeof options == 'object')
let filter = { Object.assign(myOptions, options);
where: {id: id},
const filter = {
include: [ include: [
{ {
relation: 'itemType', relation: 'itemType',
@ -58,8 +59,8 @@ module.exports = Self => {
} }
] ]
}; };
[item] = await Self.app.models.Item.find(filter); const item = await Self.app.models.Item.findById(id, filter, myOptions);
return item; return item ? item : {};
}; };
}; };

View File

@ -19,14 +19,18 @@ module.exports = Self => {
} }
}); });
Self.getSummary = async(ctx, id) => { Self.getSummary = async(ctx, id, options) => {
let promises = [];
let summary = {};
const models = Self.app.models; const models = Self.app.models;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const promises = [];
const summary = {};
// Item basic data and taxes // Item basic data and taxes
let filter = { let filter = {
where: {id: id},
include: [ include: [
{relation: 'itemType', {relation: 'itemType',
scope: { scope: {
@ -67,7 +71,7 @@ module.exports = Self => {
} }
] ]
}; };
promises.push(models.Item.find(filter)); promises.push(models.Item.findById(id, filter, myOptions));
// Tags // Tags
filter = { filter = {
@ -79,35 +83,36 @@ module.exports = Self => {
relation: 'tag' relation: 'tag'
} }
}; };
promises.push(models.ItemTag.find(filter)); promises.push(models.ItemTag.find(filter, myOptions));
// Botanical // Botanical
filter = { filter = {
where: {itemFk: id}, where: {itemFk: id},
include: [{relation: 'genus'}, {relation: 'specie'}] include: [{relation: 'genus'}, {relation: 'specie'}]
}; };
promises.push(models.ItemBotanical.find(filter)); promises.push(models.ItemBotanical.find(filter, myOptions));
// Niches // Niches
filter = { filter = {
where: {itemFk: id}, where: {itemFk: id},
include: {relation: 'warehouse'} include: {relation: 'warehouse'}
}; };
promises.push(models.ItemNiche.find(filter)); promises.push(models.ItemNiche.find(filter, myOptions));
let res = await Promise.all(promises); let res = await Promise.all(promises);
[summary.item] = res[0]; summary.item = res[0];
summary.tags = res[1]; summary.tags = res[1];
[summary.botanical] = res[2]; [summary.botanical] = res[2];
summary.niches = res[3]; summary.niches = res[3];
const userConfig = await models.UserConfig.getUserConfig(ctx); const userConfig = await models.UserConfig.getUserConfig(ctx, myOptions);
res = await models.Item.getVisibleAvailable(summary.item.id, userConfig.warehouseFk); res = await models.Item.getVisibleAvailable(summary.item.id, userConfig.warehouseFk, null, myOptions);
summary.available = res.available; summary.available = res.available;
summary.visible = res.visible; summary.visible = res.visible;
return summary; return summary;
}; };
}; };

View File

@ -5,19 +5,20 @@ module.exports = Self => {
accepts: [ accepts: [
{ {
arg: 'id', arg: 'id',
type: 'Number', type: 'number',
required: true, required: true,
}, },
{ {
arg: 'warehouseFk', arg: 'warehouseFk',
type: 'Number', type: 'number',
required: true, required: true,
}, },
{ {
arg: 'dated', arg: 'dated',
type: 'Date', type: 'date',
required: false, required: false,
}], }
],
returns: { returns: {
type: ['object'], type: ['object'],
root: true root: true
@ -28,32 +29,43 @@ module.exports = Self => {
} }
}); });
Self.getVisibleAvailable = async(id, warehouseFk, dated = new Date()) => { Self.getVisibleAvailable = async(id, warehouseFk, dated = new Date(), options) => {
let stmts = []; const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const stmts = [];
stmts.push(new ParameterizedSQL( stmts.push(new ParameterizedSQL(
'CALL cache.available_refresh(@availableCalc, FALSE, ?, ?)', [ 'CALL cache.available_refresh(@availableCalc, FALSE, ?, ?)',
[
warehouseFk, warehouseFk,
dated dated
] ],
myOptions
)); ));
stmts.push(new ParameterizedSQL( stmts.push(new ParameterizedSQL(
'CALL cache.visible_refresh(@visibleCalc, FALSE,?)', [ 'CALL cache.visible_refresh(@visibleCalc, FALSE,?)', [
warehouseFk warehouseFk
] ]
)); ));
const visibleIndex = stmts.push(new ParameterizedSQL( const visibleIndex = stmts.push(new ParameterizedSQL(
'SELECT visible FROM cache.visible WHERE calc_id = @visibleCalc AND item_id = ?', [ 'SELECT visible FROM cache.visible WHERE calc_id = @visibleCalc AND item_id = ?',
id [id],
] myOptions
)) - 1; )) - 1;
const availableIndex = stmts.push(new ParameterizedSQL( const availableIndex = stmts.push(new ParameterizedSQL(
'SELECT available FROM cache.available WHERE calc_id = @availableCalc AND item_id = ?', [ 'SELECT available FROM cache.available WHERE calc_id = @availableCalc AND item_id = ?',
id [id],
] myOptions
)) - 1; )) - 1;
const sql = ParameterizedSQL.join(stmts, ';'); const sql = ParameterizedSQL.join(stmts, ';');
let res = await Self.rawStmt(sql); const res = await Self.rawStmt(sql, myOptions);
return { return {
available: res[availableIndex][0] ? res[availableIndex][0].available : 0, available: res[availableIndex][0] ? res[availableIndex][0].available : 0,

View File

@ -17,7 +17,7 @@ module.exports = Self => {
} }
], ],
returns: { returns: {
type: ['Object'], type: ['object'],
root: true root: true
}, },
http: { http: {
@ -26,7 +26,12 @@ module.exports = Self => {
} }
}); });
Self.getWasteByItem = async(buyer, family) => { Self.getWasteByItem = async(buyer, family, options) => {
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const wastes = await Self.rawSql(` const wastes = await Self.rawSql(`
SELECT *, 100 * dwindle / total AS percentage SELECT *, 100 * dwindle / total AS percentage
FROM ( FROM (
@ -41,7 +46,7 @@ module.exports = Self => {
AND week = WEEK(TIMESTAMPADD(WEEK,-1,CURDATE()), 1) AND week = WEEK(TIMESTAMPADD(WEEK,-1,CURDATE()), 1)
GROUP BY buyer, itemFk GROUP BY buyer, itemFk
) sub ) sub
ORDER BY family, percentage DESC`, [buyer, family]); ORDER BY family, percentage DESC`, [buyer, family], myOptions);
const details = []; const details = [];

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,7 +13,12 @@ module.exports = Self => {
} }
}); });
Self.getWasteByWorker = async() => { Self.getWasteByWorker = async options => {
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const wastes = await Self.rawSql(` const wastes = await Self.rawSql(`
SELECT *, 100 * dwindle / total AS percentage SELECT *, 100 * dwindle / total AS percentage
FROM ( FROM (
@ -26,7 +31,7 @@ module.exports = Self => {
AND week = WEEK(TIMESTAMPADD(WEEK,-1,CURDATE()), 1) AND week = WEEK(TIMESTAMPADD(WEEK,-1,CURDATE()), 1)
GROUP BY buyer, family GROUP BY buyer, family
) sub ) sub
ORDER BY percentage DESC`); ORDER BY percentage DESC`, null, myOptions);
const details = []; const details = [];

View File

@ -21,8 +21,13 @@ module.exports = Self => {
} }
}); });
Self.lastEntriesFilter = async filter => { Self.lastEntriesFilter = async(filter, options) => {
const conn = Self.dataSource.connector; const conn = Self.dataSource.connector;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const stmt = new ParameterizedSQL( const stmt = new ParameterizedSQL(
`SELECT `SELECT
w.id AS warehouseFk, w.id AS warehouseFk,
@ -64,6 +69,6 @@ module.exports = Self => {
LEFT JOIN edi.ekt ek ON b.ektFk = ek.id`); LEFT JOIN edi.ekt ek ON b.ektFk = ek.id`);
stmt.merge(conn.makeSuffix(filter)); stmt.merge(conn.makeSuffix(filter));
return conn.executeStmt(stmt); return conn.executeStmt(stmt, myOptions);
}; };
}; };

View File

@ -2,7 +2,7 @@ let UserError = require('vn-loopback/util/user-error');
module.exports = Self => { module.exports = Self => {
Self.remoteMethod('new', { Self.remoteMethod('new', {
description: 'Create a new item and returns the new ID', description: 'returns the created item',
accessType: 'WRITE', accessType: 'WRITE',
accepts: [{ accepts: [{
arg: 'params', arg: 'params',
@ -19,8 +19,20 @@ module.exports = Self => {
} }
}); });
Self.new = async params => { Self.new = async(params, options) => {
let validUpdateParams = [ const models = Self.app.models;
const myOptions = {};
let tx;
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
const validUpdateParams = [
'provisionalName', 'provisionalName',
'typeFk', 'typeFk',
'intrastatFk', 'intrastatFk',
@ -33,20 +45,21 @@ module.exports = Self => {
throw new UserError(`You don't have enough privileges to do that`); throw new UserError(`You don't have enough privileges to do that`);
} }
let tx = await Self.beginTransaction({});
try { try {
let options = {transaction: tx}; const provisionalName = params.provisionalName;
let provisionalName = params.provisionalName;
delete params.provisionalName; delete params.provisionalName;
let item = await Self.app.models.Item.create(params, options); const item = await models.Item.create(params, myOptions);
const typeTags = await models.ItemTypeTag.find({
where: {itemTypeFk: item.typeFk}
}, myOptions);
let typeTags = await Self.app.models.ItemTypeTag.find({where: {itemTypeFk: item.typeFk}});
let query = `SET @isTriggerDisabled = TRUE`; let query = `SET @isTriggerDisabled = TRUE`;
await Self.rawSql(query, null, options);
let nameTag = await Self.app.models.Tag.findOne({where: {name: 'Nombre temporal'}}); await Self.rawSql(query, null, myOptions);
let nameTag = await models.Tag.findOne({where: {name: 'Nombre temporal'}});
let newTags = []; let newTags = [];
@ -55,17 +68,19 @@ module.exports = Self => {
newTags.push({itemFk: item.id, tagFk: typeTag.tagFk, value: '', priority: typeTag.priority}); newTags.push({itemFk: item.id, tagFk: typeTag.tagFk, value: '', priority: typeTag.priority});
}); });
await Self.app.models.ItemTag.create(newTags, options); await models.ItemTag.create(newTags, myOptions);
query = `SET @isTriggerDisabled = FALSE`; query = `SET @isTriggerDisabled = FALSE`;
await Self.rawSql(query, null, options); await Self.rawSql(query, null, myOptions);
query = `CALL vn.itemRefreshTags(?)`; query = `CALL vn.itemRefreshTags(?)`;
await Self.rawSql(query, [item.id], options); await Self.rawSql(query, [item.id], myOptions);
await tx.commit();
if (tx) await tx.commit();
return item; return item;
} catch (e) { } catch (e) {
await tx.rollback(); if (tx) await tx.rollback();
throw e; throw e;
} }
}; };

View File

@ -2,22 +2,26 @@ module.exports = Self => {
Self.remoteMethodCtx('regularize', { Self.remoteMethodCtx('regularize', {
description: 'Sends items to the trash', description: 'Sends items to the trash',
accessType: 'WRITE', accessType: 'WRITE',
accepts: [{ accepts: [
arg: 'itemFk', {
type: 'number', arg: 'itemFk',
required: true, type: 'number',
description: 'The item id', required: true,
}, { description: 'The item id',
arg: 'quantity', },
type: 'number', {
required: true, arg: 'quantity',
description: 'The visible quantity', type: 'number',
}, { required: true,
arg: 'warehouseFk', description: 'The visible quantity',
type: 'number', },
required: true, {
description: 'The id of the warehouse where the inventory happened', arg: 'warehouseFk',
}], type: 'number',
required: true,
description: 'The id of the warehouse where the inventory happened',
}
],
returns: { returns: {
type: 'boolean', type: 'boolean',
root: true root: true
@ -28,37 +32,44 @@ module.exports = Self => {
} }
}); });
Self.regularize = async(ctx, itemFk, quantity, warehouseFk) => { Self.regularize = async(ctx, itemFk, quantity, warehouseFk, options) => {
const models = Self.app.models; const models = Self.app.models;
const myOptions = {};
let tx;
const itemDestination = await models.ClaimDestination.findOne({ if (typeof options == 'object')
include: { Object.assign(myOptions, options);
relation: 'address',
scope: { if (!myOptions.transaction) {
fields: ['clientFk'] tx = await Self.beginTransaction({});
} myOptions.transaction = tx;
}, }
where: {description: 'Corregido'}
});
let tx = await Self.beginTransaction({});
try { try {
let options = {transaction: tx}; const itemDestination = await models.ClaimDestination.findOne({
include: {
relation: 'address',
scope: {
fields: ['clientFk']
}
},
where: {description: 'Corregido'}
}, myOptions);
let item = await models.Item.findById(itemFk); const item = await models.Item.findById(itemFk, null, myOptions);
let ticketFk = await getTicketId({ let ticketId = await getTicketId({
clientFk: itemDestination.address.clientFk, clientFk: itemDestination.address.clientFk,
addressFk: itemDestination.addressFk, addressFk: itemDestination.addressFk,
warehouseFk: warehouseFk warehouseFk: warehouseFk
}, options); }, myOptions);
if (!ticketFk) { if (!ticketId) {
ticketFk = await createTicket(ctx, { ticketId = await createTicket(ctx, {
clientId: itemDestination.address().clientFk, clientId: itemDestination.address().clientFk,
warehouseId: warehouseFk, warehouseId: warehouseFk,
addressId: itemDestination.addressFk addressId: itemDestination.addressFk
}, options); }, myOptions);
} }
res = await models.Item.getVisibleAvailable(itemFk, warehouseFk); res = await models.Item.getVisibleAvailable(itemFk, warehouseFk);
@ -66,17 +77,18 @@ module.exports = Self => {
let newQuantity = res.visible - quantity; let newQuantity = res.visible - quantity;
await models.Sale.create({ await models.Sale.create({
ticketFk: ticketFk, ticketFk: ticketId,
itemFk: itemFk, itemFk: itemFk,
concept: item.name, concept: item.name,
quantity: newQuantity, quantity: newQuantity,
discount: 100 discount: 100
}, options); }, myOptions);
await tx.commit(); if (tx) await tx.commit();
return ticketFk;
return ticketId;
} catch (e) { } catch (e) {
await tx.rollback(); if (tx) await tx.rollback();
throw e; throw e;
} }

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('item clone()', () => { describe('item clone()', () => {
let nextItemId; let nextItemId;
@ -8,30 +8,47 @@ describe('item clone()', () => {
LEFT JOIN vn.item i2 ON i1.id + 1 = i2.id LEFT JOIN vn.item i2 ON i1.id + 1 = i2.id
WHERE i2.id IS NULL ORDER BY i1.id LIMIT 1`; WHERE i2.id IS NULL ORDER BY i1.id LIMIT 1`;
[nextAvailableId] = await app.models.Item.rawSql(query); [nextAvailableId] = await models.Item.rawSql(query);
nextItemId = nextAvailableId.id; nextItemId = nextAvailableId.id;
}); });
it('should clone the given item and it should have the expected id', async() => { it('should clone the given item and it should have the expected id', async() => {
let itemFk = 1; const tx = await models.FixedPrice.beginTransaction({});
let result = await app.models.Item.clone(itemFk);
expect(result.id).toEqual(nextItemId); try {
expect(result.image).toBeUndefined(); const options = {transaction: tx};
expect(result.itemTag).toBeUndefined(); const itemFk = 1;
expect(result.comment).toBeUndefined(); const result = await models.Item.clone(itemFk, options);
expect(result.description).toBeUndefined();
expect(result.id).toEqual(nextItemId);
expect(result.image).toBeUndefined();
expect(result.itemTag).toBeUndefined();
expect(result.comment).toBeUndefined();
expect(result.description).toBeUndefined();
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should attempt to clone the given item but give an error as it doesnt exist', async() => { it('should attempt to clone the given item but give an error as it doesnt exist', async() => {
let error; const tx = await models.FixedPrice.beginTransaction({});
let itemFk = 999;
await app.models.Item.clone(itemFk)
.catch(e => {
expect(e.message).toContain(`This item doesn't exists`);
error = e;
});
expect(error).toBeDefined(); let error;
try {
const options = {transaction: tx};
const itemFk = 999;
await models.Item.clone(itemFk, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
expect(error.message).toContain(`This item doesn't exists`);
}); });
}); });

View File

@ -1,22 +1,25 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('createIntrastat()', () => { describe('createIntrastat()', () => {
let newIntrastat;
afterAll(async done => {
await app.models.Intrastat.destroyById(newIntrastat.id);
done();
});
it('should create a new intrastat', async() => { it('should create a new intrastat', async() => {
const intrastatId = 588420239; const tx = await models.FixedPrice.beginTransaction({});
const description = 'Tropical Flowers';
const itemId = 9;
newIntrastat = await app.models.Item.createIntrastat(itemId, intrastatId, description);
expect(newIntrastat.description).toEqual(description); try {
expect(newIntrastat.taxClassFk).toEqual(1); const options = {transaction: tx};
expect(newIntrastat.taxCodeFk).toEqual(21); const intrastatId = 588420239;
const description = 'Tropical Flowers';
const itemId = 9;
const newIntrastat = await models.Item.createIntrastat(itemId, intrastatId, description, options);
expect(newIntrastat.description).toEqual(description);
expect(newIntrastat.taxClassFk).toEqual(1);
expect(newIntrastat.taxCodeFk).toEqual(21);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -1,14 +1,14 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('item filter()', () => { describe('item filter()', () => {
it('should return 1 result filtering by id', async() => { it('should return 1 result filtering by id', async() => {
const tx = await app.models.Item.beginTransaction({}); const tx = await models.Item.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
const filter = {}; const filter = {};
const ctx = {args: {filter: filter, search: 1}}; const ctx = {args: {filter: filter, search: 1}};
const result = await app.models.Item.filter(ctx, filter, options); const result = await models.Item.filter(ctx, filter, options);
expect(result.length).toEqual(1); expect(result.length).toEqual(1);
expect(result[0].id).toEqual(1); expect(result[0].id).toEqual(1);
@ -21,13 +21,13 @@ describe('item filter()', () => {
}); });
it('should return 1 result filtering by barcode', async() => { it('should return 1 result filtering by barcode', async() => {
const tx = await app.models.Item.beginTransaction({}); const tx = await models.Item.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
const filter = {}; const filter = {};
const ctx = {args: {filter: filter, search: 4444444444}}; const ctx = {args: {filter: filter, search: 4444444444}};
const result = await app.models.Item.filter(ctx, filter, options); const result = await models.Item.filter(ctx, filter, options);
expect(result.length).toEqual(1); expect(result.length).toEqual(1);
expect(result[0].id).toEqual(2); expect(result[0].id).toEqual(2);
@ -40,7 +40,7 @@ describe('item filter()', () => {
}); });
it('should return 2 results using filter and tags', async() => { it('should return 2 results using filter and tags', async() => {
const tx = await app.models.Item.beginTransaction({}); const tx = await models.Item.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
try { try {
@ -50,7 +50,7 @@ describe('item filter()', () => {
}; };
const tags = [{value: 'medical box', tagFk: 58}]; const tags = [{value: 'medical box', tagFk: 58}];
const ctx = {args: {filter: filter, typeFk: 5, tags: tags}}; const ctx = {args: {filter: filter, typeFk: 5, tags: tags}};
const result = await app.models.Item.filter(ctx, filter, options); const result = await models.Item.filter(ctx, filter, options);
expect(result.length).toEqual(2); expect(result.length).toEqual(2);

View File

@ -1,33 +1,39 @@
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('item getBalance()', () => { describe('item getBalance()', () => {
it('should return the balance lines of a client type loses in which one has highlighted true', async() => { it('should return the balance lines of a client type loses in which one has highlighted true', async() => {
const activeCtx = { const tx = await models.Item.beginTransaction({});
accessToken: {userId: 9}, const options = {transaction: tx};
};
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
active: activeCtx
});
const losesClientId = 1111; try {
const ticket = await app.models.Ticket.findById(7); const activeCtx = {
const originalClientId = ticket.clientFk; accessToken: {userId: 9},
await ticket.updateAttribute('clientFk', losesClientId); };
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
active: activeCtx
});
const losesClientId = 1111;
const ticket = await models.Ticket.findById(7, null, options);
const filter = { await ticket.updateAttribute('clientFk', losesClientId, options);
where: {
itemFk: 1,
warehouseFk: 1
}
};
const results = await app.models.Item.getBalance(filter);
const result = results.find(element => element.clientType == 'loses'); const filter = {
where: {
itemFk: 1,
warehouseFk: 1
}
};
const results = await models.Item.getBalance(filter, options);
expect(result.highlighted).toBe(true); const result = results.find(element => element.clientType == 'loses');
// restores expect(result.highlighted).toBe(true);
await ticket.updateAttribute('clientFk', originalClientId);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -0,0 +1,23 @@
const models = require('vn-loopback/server/server').models;
describe('item getCard()', () => {
it('should return the item', async() => {
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
try {
const itemId = 1;
const result = await models.Item.getCard(itemId, options);
expect(result.id).toEqual(itemId);
expect(result.itemType()).toEqual(jasmine.any(Object));
expect(result.tags()).toEqual(jasmine.any(Array));
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,12 +0,0 @@
const app = require('vn-loopback/server/server');
describe('item getBalance()', () => {
it('should check the property balance of the 4 resultant entries', async() => {
let params = {where: {itemFk: 1, warehouseFk: 2}};
let result = await app.models.Item.getBalance(params);
expect(result.length).toBe(2);
expect(result[0].balance).toBe(-100);
expect(result[1].balance).toBe(-200);
});
});

Some files were not shown because too many files have changed in this diff Show More