item module transactions
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Carlos Jimenez Ruiz 2021-07-12 12:54:59 +02:00
parent dd3473b93d
commit 21e34de1dd
37 changed files with 1012 additions and 621 deletions

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,10 +132,9 @@ 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,
@ -156,8 +159,8 @@ module.exports = Self => {
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,7 +1,11 @@
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 tx = await models.FixedPrice.beginTransaction({});
try {
const options = {transaction: tx};
const itemID = 3; const itemID = 3;
const ctx = { const ctx = {
req: {accessToken: {userId: 1}}, req: {accessToken: {userId: 1}},
@ -9,14 +13,24 @@ describe('fixed price filter()', () => {
search: itemID search: itemID
} }
}; };
const result = await app.models.FixedPrice.filter(ctx); const result = await models.FixedPrice.filter(ctx, null, options);
expect(result.length).toEqual(1); expect(result.length).toEqual(1);
expect(result[0].id).toEqual(2); expect(result[0].id).toEqual(2);
expect(result[0].itemFk).toEqual(itemID); 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 tx = await models.FixedPrice.beginTransaction({});
try {
const options = {transaction: tx};
const itemCode = 'CRI'; const itemCode = 'CRI';
const ctx = { const ctx = {
req: {accessToken: {userId: 1}}, req: {accessToken: {userId: 1}},
@ -24,27 +38,37 @@ describe('fixed price filter()', () => {
search: itemCode search: itemCode
} }
}; };
const itemType = await app.models.ItemType.findOne({ const itemType = await models.ItemType.findOne({
where: {code: itemCode}, where: {code: itemCode},
fields: ['id'] fields: ['id']
}); }, options);
const items = await app.models.Item.find({ const items = await models.Item.find({
where: {typeFk: itemType.id}, where: {typeFk: itemType.id},
fields: ['id'] fields: ['id']
}); }, options);
const IDs = items.map(item => { const IDs = items.map(item => {
return item.id; return item.id;
}); });
const result = await app.models.FixedPrice.filter(ctx); const result = await models.FixedPrice.filter(ctx, null, options);
const firstResult = result[0]; const firstResult = result[0];
expect(result.length).toEqual(1); expect(result.length).toEqual(1);
expect(firstResult.id).toEqual(2); expect(firstResult.id).toEqual(2);
expect(IDs).toContain(firstResult.itemFk); 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 tx = await models.FixedPrice.beginTransaction({});
try {
const options = {transaction: tx};
const warehouseID = 1; const warehouseID = 1;
const ctx = { const ctx = {
req: {accessToken: {userId: 1}}, req: {accessToken: {userId: 1}},
@ -52,35 +76,61 @@ describe('fixed price filter()', () => {
warehouseFk: warehouseID warehouseFk: warehouseID
} }
}; };
const result = await app.models.FixedPrice.filter(ctx); const result = await models.FixedPrice.filter(ctx, null, options);
const length = result.length; const length = result.length;
const anyResult = result[Math.floor(Math.random() * Math.floor(length))]; const anyResult = result[Math.floor(Math.random() * Math.floor(length))];
expect(result.length).toEqual(2); expect(result.length).toEqual(2);
expect(anyResult.warehouseFk).toEqual(warehouseID); 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 tx = await models.FixedPrice.beginTransaction({});
try {
const options = {transaction: tx};
const ctx = { const ctx = {
req: {accessToken: {userId: 1}}, req: {accessToken: {userId: 1}},
args: { args: {
hasMinPrice: true hasMinPrice: true
} }
}; };
const result = await app.models.FixedPrice.filter(ctx); const result = await models.FixedPrice.filter(ctx, null, options);
expect(result.length).toEqual(0); 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 tx = await models.FixedPrice.beginTransaction({});
try {
const options = {transaction: tx};
const ctx = { const ctx = {
req: {accessToken: {userId: 1}}, req: {accessToken: {userId: 1}},
args: { args: {
typeFk: 1 typeFk: 1
} }
}; };
const result = await app.models.FixedPrice.filter(ctx); const result = await models.FixedPrice.filter(ctx, null, options);
expect(result.length).toEqual(1); expect(result.length).toEqual(1);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -1,22 +1,19 @@
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 tx = await models.FixedPrice.beginTransaction({});
try {
const options = {transaction: tx};
const ctx = {args: { const ctx = {args: {
id: fixedPriceId, id: fixedPriceId,
itemFk: originalFixedPrice.itemFk, itemFk: originalFixedPrice.itemFk,
@ -29,16 +26,26 @@ describe('upsertFixedPrice()', () => {
hasMinPrice: false hasMinPrice: false
}}; }};
const result = await app.models.FixedPrice.upsertFixedPrice(ctx, ctx.args.id); const result = await models.FixedPrice.upsertFixedPrice(ctx, options);
delete ctx.args.started; delete ctx.args.started;
delete ctx.args.ended; delete ctx.args.ended;
ctx.args.hasMinPrice = true; ctx.args.hasMinPrice = true;
expect(result).toEqual(jasmine.objectContaining(ctx.args)); 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 tx = await models.FixedPrice.beginTransaction({});
try {
const options = {transaction: tx};
const ctx = {args: { const ctx = {args: {
id: fixedPriceId, id: fixedPriceId,
itemFk: originalFixedPrice.itemFk, itemFk: originalFixedPrice.itemFk,
@ -51,12 +58,18 @@ describe('upsertFixedPrice()', () => {
hasMinPrice: true hasMinPrice: true
}}; }};
const result = await app.models.FixedPrice.upsertFixedPrice(ctx, ctx.args.id); const result = await models.FixedPrice.upsertFixedPrice(ctx, options);
delete ctx.args.started; delete ctx.args.started;
delete ctx.args.ended; delete ctx.args.ended;
ctx.args.hasMinPrice = false; ctx.args.hasMinPrice = false;
expect(result).toEqual(jasmine.objectContaining(ctx.args)); expect(result).toEqual(jasmine.objectContaining(ctx.args));
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -2,7 +2,8 @@ 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', arg: 'ctx',
type: 'object', type: 'object',
http: {source: 'context'} http: {source: 'context'}
@ -43,7 +44,8 @@ module.exports = Self => {
{ {
arg: 'hasMinPrice', arg: 'hasMinPrice',
type: 'any' 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, options); const fixedPrice = await models.FixedPrice.upsert(args, options);
const targetItem = await models.Item.findById(args.itemFk, null, 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};
try {
const barcode = 3;
const result = await models.ItemBarcode.toItem(barcode, options);
expect(result).toBe(3); 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,7 +5,8 @@ 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', arg: 'tagFk',
type: 'number', type: 'number',
required: true, required: true,
@ -13,9 +14,10 @@ module.exports = Self => {
http: {source: 'path'} http: {source: 'path'}
}, { }, {
arg: 'filter', arg: 'filter',
type: 'Object', type: 'object',
description: `Filter defining where, order, offset, and limit - must be a JSON-encoded string` description: `Filter defining where, order, offset, and limit - must be a JSON-encoded string`
}], }
],
returns: { returns: {
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};
try {
const [result] = await models.ItemTag.filterItemTags(1, null, options);
expect(result.value).toEqual('Black'); 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,7 +2,8 @@ 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', arg: 'id',
type: 'number', type: 'number',
required: true, required: true,
@ -18,7 +19,8 @@ module.exports = Self => {
arg: 'description', arg: 'description',
type: 'string', type: 'string',
required: true required: true
}], }
],
returns: { returns: {
type: 'boolean', type: 'boolean',
root: true root: true
@ -29,11 +31,23 @@ 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 = {};
let tx;
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
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 +55,28 @@ 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);
if (tx) await tx.commit();
return intrastat;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
}; };
}; };

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', arg: 'itemFk',
type: 'number', type: 'number',
required: true, required: true,
description: 'The item id', description: 'The item id',
}, { },
{
arg: 'quantity', arg: 'quantity',
type: 'number', type: 'number',
required: true, required: true,
description: 'The visible quantity', description: 'The visible quantity',
}, { },
{
arg: 'warehouseFk', arg: 'warehouseFk',
type: 'number', type: 'number',
required: true, required: true,
description: 'The id of the warehouse where the inventory happened', description: 'The id of the warehouse where the inventory happened',
}], }
],
returns: { returns: {
type: 'boolean', type: 'boolean',
root: true root: true
@ -28,9 +32,20 @@ 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;
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const itemDestination = await models.ClaimDestination.findOne({ const itemDestination = await models.ClaimDestination.findOne({
include: { include: {
relation: 'address', relation: 'address',
@ -39,26 +54,22 @@ module.exports = Self => {
} }
}, },
where: {description: 'Corregido'} where: {description: 'Corregido'}
}); }, myOptions);
let tx = await Self.beginTransaction({}); const item = await models.Item.findById(itemFk, null, myOptions);
try {
let options = {transaction: tx};
let item = await models.Item.findById(itemFk); let ticketId = await getTicketId({
let ticketFk = 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);
try {
const options = {transaction: tx};
const itemFk = 1;
const result = await models.Item.clone(itemFk, options);
expect(result.id).toEqual(nextItemId); expect(result.id).toEqual(nextItemId);
expect(result.image).toBeUndefined(); expect(result.image).toBeUndefined();
expect(result.itemTag).toBeUndefined(); expect(result.itemTag).toBeUndefined();
expect(result.comment).toBeUndefined(); expect(result.comment).toBeUndefined();
expect(result.description).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 tx = await models.FixedPrice.beginTransaction({});
try {
const options = {transaction: tx};
const intrastatId = 588420239; const intrastatId = 588420239;
const description = 'Tropical Flowers'; const description = 'Tropical Flowers';
const itemId = 9; const itemId = 9;
newIntrastat = await app.models.Item.createIntrastat(itemId, intrastatId, description);
const newIntrastat = await models.Item.createIntrastat(itemId, intrastatId, description, options);
expect(newIntrastat.description).toEqual(description); expect(newIntrastat.description).toEqual(description);
expect(newIntrastat.taxClassFk).toEqual(1); expect(newIntrastat.taxClassFk).toEqual(1);
expect(newIntrastat.taxCodeFk).toEqual(21); 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,19 +1,22 @@
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 tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
try {
const activeCtx = { const activeCtx = {
accessToken: {userId: 9}, accessToken: {userId: 9},
}; };
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
active: activeCtx active: activeCtx
}); });
const losesClientId = 1111; const losesClientId = 1111;
const ticket = await app.models.Ticket.findById(7); const ticket = await models.Ticket.findById(7, null, options);
const originalClientId = ticket.clientFk;
await ticket.updateAttribute('clientFk', losesClientId); await ticket.updateAttribute('clientFk', losesClientId, options);
const filter = { const filter = {
where: { where: {
@ -21,13 +24,16 @@ describe('item getBalance()', () => {
warehouseFk: 1 warehouseFk: 1
} }
}; };
const results = await app.models.Item.getBalance(filter); const results = await models.Item.getBalance(filter, options);
const result = results.find(element => element.clientType == 'loses'); const result = results.find(element => element.clientType == 'loses');
expect(result.highlighted).toBe(true); expect(result.highlighted).toBe(true);
// restores await tx.rollback();
await ticket.updateAttribute('clientFk', originalClientId); } 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);
});
});

View File

@ -1,10 +1,15 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('item getSummary()', () => { describe('item getSummary()', () => {
it('should return summary with item, tags, botanical, niches, available and visible defined ', async() => { it('should return summary with item, tags, botanical, niches, available and visible defined ', async() => {
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
try {
const ctx = {req: {accessToken: {userId: 1}}}; const ctx = {req: {accessToken: {userId: 1}}};
let result = await app.models.Item.getSummary(ctx, 1);
let keys = Object.keys(result); const result = await models.Item.getSummary(ctx, 1, options);
const keys = Object.keys(result);
expect(keys).toContain('item'); expect(keys).toContain('item');
expect(keys).toContain('tags'); expect(keys).toContain('tags');
@ -12,5 +17,11 @@ describe('item getSummary()', () => {
expect(keys).toContain('niches'); expect(keys).toContain('niches');
expect(keys).toContain('available'); expect(keys).toContain('available');
expect(keys).toContain('visible'); expect(keys).toContain('visible');
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -1,33 +1,46 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('item getVisibleAvailable()', () => { describe('item getVisibleAvailable()', () => {
it('should check available visible for today', async() => { it('should check available visible for today', async() => {
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
try {
const itemFk = 1; const itemFk = 1;
const warehouseFk = 1; const warehouseFk = 1;
const dated = new Date(); const dated = new Date();
let result = await app.models.Item.getVisibleAvailable(itemFk, warehouseFk, dated);
const result = await models.Item.getVisibleAvailable(itemFk, warehouseFk, dated, options);
expect(result.available).toEqual(187); expect(result.available).toEqual(187);
expect(result.visible).toEqual(92); expect(result.visible).toEqual(92);
});
it('should check available visible for no dated', async() => { await tx.rollback();
const itemFk = 1; } catch (e) {
const warehouseFk = 1; await tx.rollback();
let result = await app.models.Item.getVisibleAvailable(itemFk, warehouseFk); throw e;
}
expect(result.available).toEqual(187);
expect(result.visible).toEqual(92);
}); });
it('should check available visible for yesterday', async() => { it('should check available visible for yesterday', async() => {
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
try {
const itemFk = 1; const itemFk = 1;
const warehouseFk = 1; const warehouseFk = 1;
let dated = new Date(); const dated = new Date();
dated.setDate(dated.getDate() - 1); dated.setDate(dated.getDate() - 1);
let result = await app.models.Item.getVisibleAvailable(itemFk, warehouseFk, dated);
const result = await models.Item.getVisibleAvailable(itemFk, warehouseFk, dated, options);
expect(result.available).toEqual(0); expect(result.available).toEqual(0);
expect(result.visible).toEqual(92); expect(result.visible).toEqual(92);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -1,8 +1,12 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('Item getWasteByItem()', () => { describe('Item getWasteByItem()', () => {
it('should check for the waste breakdown by worker and item', async() => { it('should check for the waste breakdown by worker and item', async() => {
const result = await app.models.Item.getWasteByItem('CharlesXavier', 'Cymbidium'); const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
try {
const result = await models.Item.getWasteByItem('CharlesXavier', 'Cymbidium', options);
const length = result.length; const length = result.length;
const anyResult = result[Math.floor(Math.random() * Math.floor(length))]; const anyResult = result[Math.floor(Math.random() * Math.floor(length))];
@ -10,5 +14,11 @@ describe('Item getWasteByItem()', () => {
expect(anyResult.buyer).toEqual('CharlesXavier'); expect(anyResult.buyer).toEqual('CharlesXavier');
expect(anyResult.family).toEqual('Cymbidium'); expect(anyResult.family).toEqual('Cymbidium');
expect(anyResult.lines.length).toBeGreaterThanOrEqual(2); expect(anyResult.lines.length).toBeGreaterThanOrEqual(2);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -1,13 +1,23 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('Item getWasteByWorker()', () => { describe('Item getWasteByWorker()', () => {
it('should check for the waste breakdown for every worker', async() => { it('should check for the waste breakdown for every worker', async() => {
const result = await app.models.Item.getWasteByWorker(); const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
try {
const result = await models.Item.getWasteByWorker(options);
const length = result.length; const length = result.length;
const anyResult = result[Math.floor(Math.random() * Math.floor(length))]; const anyResult = result[Math.floor(Math.random() * Math.floor(length))];
expect(anyResult.buyer).toMatch(/(CharlesXavier|HankPym|DavidCharlesHaller)/); expect(anyResult.buyer).toMatch(/(CharlesXavier|HankPym|DavidCharlesHaller)/);
expect(anyResult.lines.length).toBeGreaterThanOrEqual(3); expect(anyResult.lines.length).toBeGreaterThanOrEqual(3);
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;
describe('item lastEntriesFilter()', () => { describe('item lastEntriesFilter()', () => {
const minDate = new Date(value); const minDate = new Date(value);
@ -7,18 +7,38 @@ describe('item lastEntriesFilter()', () => {
maxHour.setHours(23, 59, 59, 59); maxHour.setHours(23, 59, 59, 59);
it('should return one entry for a given item', async() => { it('should return one entry for a given item', async() => {
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
try {
const filter = {where: {itemFk: 1, landed: {between: [minDate, maxDate]}}}; const filter = {where: {itemFk: 1, landed: {between: [minDate, maxDate]}}};
const result = await app.models.Item.lastEntriesFilter(filter); const result = await models.Item.lastEntriesFilter(filter, options);
expect(result.length).toEqual(1); expect(result.length).toEqual(1);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should return five entries for a given item', async() => { it('should return five entries for a given item', async() => {
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
try {
minDate.setMonth(minDate.getMonth() - 2, 1); minDate.setMonth(minDate.getMonth() - 2, 1);
const filter = {where: {itemFk: 1, landed: {between: [minDate, maxDate]}}}; const filter = {where: {itemFk: 1, landed: {between: [minDate, maxDate]}}};
const result = await app.models.Item.lastEntriesFilter(filter); const result = await models.Item.lastEntriesFilter(filter, options);
expect(result.length).toEqual(5); expect(result.length).toEqual(5);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -1,45 +1,41 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('item new()', () => { describe('item new()', () => {
let item;
afterAll(async done => {
try {
let sql = 'DELETE FROM vn.itemLog WHERE originFk = ?';
await app.models.Item.rawSql(sql, [item.id]);
sql = 'DELETE FROM vn.item WHERE id = ?';
await app.models.Item.rawSql(sql, [item.id]);
} catch (error) {
console.error(error);
}
done();
});
it('should create a new item, adding the name as a tag', async() => { it('should create a new item, adding the name as a tag', async() => {
let itemParams = { const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
try {
const itemParams = {
intrastatFk: 5080000, intrastatFk: 5080000,
originFk: 1, originFk: 1,
provisionalName: 'planta', provisionalName: 'planta',
typeFk: 2, typeFk: 2,
relevancy: 0 relevancy: 0
}; };
item = await app.models.Item.new(itemParams);
let temporalNameTag = await app.models.Tag.findOne({where: {name: 'Nombre temporal'}});
let temporalName = await app.models.ItemTag.findOne({ let item = await models.Item.new(itemParams, options);
const temporalNameTag = await models.Tag.findOne({where: {name: 'Nombre temporal'}}, options);
const temporalName = await models.ItemTag.findOne({
where: { where: {
itemFk: item.id, itemFk: item.id,
tagFk: temporalNameTag.id, tagFk: temporalNameTag.id,
} }
}); }, options);
item = await app.models.Item.findById(item.id);
item = await models.Item.findById(item.id, null, options);
expect(item.intrastatFk).toEqual(5080000); expect(item.intrastatFk).toEqual(5080000);
expect(item.originFk).toEqual(1); expect(item.originFk).toEqual(1);
expect(item.typeFk).toEqual(2); expect(item.typeFk).toEqual(2);
expect(item.name).toEqual('planta'); expect(item.name).toEqual('planta');
expect(temporalName.value).toEqual('planta'); expect(temporalName.value).toEqual('planta');
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -1,29 +1,32 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('regularize()', () => { describe('regularize()', () => {
const itemFk = 1;
const warehouseFk = 1;
const trashAddress = 11;
let trashTicket;
afterAll(async done => {
await app.models.Ticket.destroyById(trashTicket.id);
done();
});
it('should create a new ticket and add a line', async() => { it('should create a new ticket and add a line', async() => {
let ctx = {req: {accessToken: {userId: 18}}}; const tx = await models.Item.beginTransaction({});
let res = await app.models.Item.getVisibleAvailable(itemFk, warehouseFk); const options = {transaction: tx};
let visible = res.visible;
let saleQuantity = visible - 11;
let ticketFk = await app.models.Item.regularize(ctx, itemFk, 11, warehouseFk); try {
let sale = await app.models.Sale.findOne({where: {ticketFk: ticketFk}}); const ctx = {req: {accessToken: {userId: 18}}};
trashTicket = await app.models.Ticket.findById(ticketFk); const itemId = 1;
const warehouseId = 1;
const quantity = 11;
const date = undefined;
expect(sale.quantity).toEqual(saleQuantity); const res = await models.Item.getVisibleAvailable(itemId, warehouseId, date, options);
const visible = res.visible;
const expectedQuantity = visible - quantity;
const ticketId = await models.Item.regularize(ctx, itemId, quantity, warehouseId, options);
const sale = await models.Sale.findOne({where: {ticketFk: ticketId}}, options);
expect(sale.quantity).toEqual(expectedQuantity);
expect(sale.discount).toEqual(100); expect(sale.discount).toEqual(100);
expect(trashTicket.addressFk).toEqual(trashAddress);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -1,34 +1,47 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('item updateTaxes()', () => { describe('item updateTaxes()', () => {
let taxesInFixtures = [{id: 3, taxClassFk: 1}];
it('should throw an error if the taxClassFk is blank', async() => { it('should throw an error if the taxClassFk is blank', async() => {
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
let error; let error;
let taxes = [{id: 3, taxClassFk: undefined}];
await app.models.Item.updateTaxes(taxes) try {
.catch(err => { const taxes = [{id: 3, taxClassFk: undefined}];
expect(err.message).toEqual('Tax class cannot be blank');
error = err;
});
expect(error).toBeDefined(); await models.Item.updateTaxes(taxes, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
expect(error.message).toEqual('Tax class cannot be blank');
}); });
it('should update the tax of a given country of an item', async() => { it('should update the tax of a given country of an item', async() => {
let taxCountry = await app.models.ItemTaxCountry.findById(3); const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
try {
let taxCountry = await models.ItemTaxCountry.findById(3, null, options);
expect(taxCountry.taxClassFk).toEqual(1); expect(taxCountry.taxClassFk).toEqual(1);
let taxes = [{id: 3, taxClassFk: 2}]; const taxes = [{id: 3, taxClassFk: 2}];
await app.models.Item.updateTaxes(taxes); await models.Item.updateTaxes(taxes, options);
taxCountry = await app.models.ItemTaxCountry.findById(3);
taxCountry = await models.ItemTaxCountry.findById(3, null, options);
expect(taxCountry.taxClassFk).toEqual(2); expect(taxCountry.taxClassFk).toEqual(2);
// restores await tx.rollback();
await app.models.Item.updateTaxes(taxesInFixtures); } catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -21,8 +21,21 @@ module.exports = Self => {
} }
}); });
Self.updateTaxes = async taxes => { Self.updateTaxes = async(taxes, options) => {
let promises = []; const myOptions = {};
let tx;
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const promises = [];
for (let tax of taxes) { for (let tax of taxes) {
if (!tax.taxClassFk) if (!tax.taxClassFk)
throw new UserError('Tax class cannot be blank'); throw new UserError('Tax class cannot be blank');
@ -30,9 +43,16 @@ module.exports = Self => {
promises.push(Self.app.models.ItemTaxCountry.update( promises.push(Self.app.models.ItemTaxCountry.update(
{id: tax.id}, {id: tax.id},
{taxClassFk: tax.taxClassFk} {taxClassFk: tax.taxClassFk}
)); ), myOptions);
} }
await Promise.all(promises); await Promise.all(promises);
if (tx) await tx.commit();
return true; return true;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
}; };
}; };

View File

@ -3,17 +3,20 @@ const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
module.exports = Self => { module.exports = Self => {
Self.remoteMethod('filterValue', { Self.remoteMethod('filterValue', {
description: 'Returns a list of tag values', description: 'Returns a list of tag values',
accepts: [{ accepts: [
{
arg: 'id', arg: 'id',
type: 'Number', type: 'number',
required: true, required: true,
description: 'The tag id', description: 'The tag id',
http: {source: 'path'} http: {source: 'path'}
}, { },
{
arg: 'filter', arg: 'filter',
type: 'Object', type: 'object',
description: `Filter defining where, order, offset, and limit - must be a JSON-encoded string` description: `Filter defining where, order, offset, and limit - must be a JSON-encoded string`
}], }
],
returns: { returns: {
type: ['object'], type: ['object'],
root: true root: true
@ -24,11 +27,16 @@ module.exports = Self => {
} }
}); });
Self.filterValue = async(id, filter) => { Self.filterValue = async(id, filter, options) => {
const conn = Self.dataSource.connector; const conn = Self.dataSource.connector;
const tag = await Self.findById(id); const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const tag = await Self.findById(id);
let stmt; let stmt;
if (!tag.isFree && tag.sourceTable) { if (!tag.isFree && tag.sourceTable) {
stmt = new ParameterizedSQL( stmt = new ParameterizedSQL(
`SELECT value FROM ( `SELECT value FROM (
@ -36,7 +44,7 @@ module.exports = Self => {
} else } else
stmt = new ParameterizedSQL(`SELECT value FROM itemTag`); stmt = new ParameterizedSQL(`SELECT value FROM itemTag`);
let where = filter.where; const where = filter.where;
if (where && where.value) { if (where && where.value) {
stmt.merge(conn.makeWhere({value: {like: `%${where.value}%`}})); stmt.merge(conn.makeWhere({value: {like: `%${where.value}%`}}));
stmt.merge(` stmt.merge(`
@ -46,6 +54,6 @@ module.exports = Self => {
stmt.merge(conn.makeLimit(filter)); stmt.merge(conn.makeLimit(filter));
return conn.executeStmt(stmt); return conn.executeStmt(stmt, myOptions);
}; };
}; };

View File

@ -1,37 +1,76 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('tag filterValue()', () => { describe('tag filterValue()', () => {
const colorTagId = 1; const colorTagId = 1;
it('should return a list of color values', async() => { it('should return a list of color values', async() => {
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
try {
const filter = {limit: 5}; const filter = {limit: 5};
const result = await app.models.Tag.filterValue(colorTagId, filter); const result = await models.Tag.filterValue(colorTagId, filter, options);
expect(result.length).toEqual(5); expect(result.length).toEqual(5);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should return the values matching color "Blue"', async() => { it('should return the values matching color "Blue"', async() => {
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
try {
const filter = {where: {value: 'Blue'}, limit: 5}; const filter = {where: {value: 'Blue'}, limit: 5};
const result = await app.models.Tag.filterValue(colorTagId, filter); const result = await models.Tag.filterValue(colorTagId, filter, options);
expect(result.length).toEqual(2); expect(result.length).toEqual(2);
expect(result[0].value).toEqual('Blue'); expect(result[0].value).toEqual('Blue');
expect(result[1].value).toEqual('Blue/Silver'); expect(result[1].value).toEqual('Blue/Silver');
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should return the values matching color "Blue/Silver"', async() => { it('should return the values matching color "Blue/Silver"', async() => {
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
try {
const filter = {where: {value: 'Blue/Silver'}, limit: 5}; const filter = {where: {value: 'Blue/Silver'}, limit: 5};
const result = await app.models.Tag.filterValue(colorTagId, filter); const result = await models.Tag.filterValue(colorTagId, filter, options);
expect(result.length).toEqual(1); expect(result.length).toEqual(1);
expect(result[0].value).toEqual('Blue/Silver'); expect(result[0].value).toEqual('Blue/Silver');
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should return the values matching color "Silver"', async() => { it('should return the values matching color "Silver"', async() => {
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
try {
const filter = {where: {value: 'Silver'}, limit: 5}; const filter = {where: {value: 'Silver'}, limit: 5};
const result = await app.models.Tag.filterValue(colorTagId, filter); const result = await models.Tag.filterValue(colorTagId, filter, options);
expect(result.length).toEqual(2); expect(result.length).toEqual(2);
expect(result[0].value).toEqual('Silver'); expect(result[0].value).toEqual('Silver');
expect(result[1].value).toEqual('Blue/Silver'); expect(result[1].value).toEqual('Blue/Silver');
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });