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',
type: 'Boolean',
type: 'boolean',
description: `Search requests attended by the current user`
}
],
returns: {
type: ['Object'],
type: ['object'],
root: true
},
http: {
@ -94,9 +94,13 @@ module.exports = Self => {
}
});
Self.filter = async(ctx, filter) => {
Self.filter = async(ctx, filter, options) => {
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)
ctx.args.buyerFk = userId;
@ -128,36 +132,35 @@ module.exports = Self => {
filter = mergeFilters(filter, {where});
const stmts = [];
let stmt;
stmt = new ParameterizedSQL(
`SELECT fp.id,
fp.itemFk,
fp.warehouseFk,
fp.rate2,
fp.rate3,
fp.started,
fp.ended,
i.minPrice,
i.hasMinPrice,
i.name,
i.subName,
i.tag5,
i.value5,
i.tag6,
i.value6,
i.tag7,
i.value7,
i.tag8,
i.value8,
i.tag9,
i.value9,
i.tag10,
i.value10
FROM priceFixed fp
JOIN item i ON i.id = fp.itemFk
JOIN itemType it ON it.id = i.typeFk`
);
const stmt = new ParameterizedSQL(`
SELECT fp.id,
fp.itemFk,
fp.warehouseFk,
fp.rate2,
fp.rate3,
fp.started,
fp.ended,
i.minPrice,
i.hasMinPrice,
i.name,
i.subName,
i.tag5,
i.value5,
i.tag6,
i.value6,
i.tag7,
i.value7,
i.tag8,
i.value8,
i.tag9,
i.value9,
i.tag10,
i.value10
FROM priceFixed fp
JOIN item i ON i.id = fp.itemFk
JOIN itemType it ON it.id = i.typeFk
`);
if (ctx.args.tags) {
let i = 1;
@ -186,7 +189,8 @@ module.exports = Self => {
const fixedPriceIndex = stmts.push(stmt) - 1;
const sql = ParameterizedSQL.join(stmts, ';');
const result = await conn.executeStmt(sql);
const result = await conn.executeStmt(sql, myOptions);
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()', () => {
it('should return 1 result filtering by item ID', async() => {
const itemID = 3;
const ctx = {
req: {accessToken: {userId: 1}},
args: {
search: itemID
}
};
const result = await app.models.FixedPrice.filter(ctx);
const tx = await models.FixedPrice.beginTransaction({});
expect(result.length).toEqual(1);
expect(result[0].id).toEqual(2);
expect(result[0].itemFk).toEqual(itemID);
try {
const options = {transaction: tx};
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() => {
const itemCode = 'CRI';
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 tx = await models.FixedPrice.beginTransaction({});
const result = await app.models.FixedPrice.filter(ctx);
const firstResult = result[0];
try {
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);
expect(firstResult.id).toEqual(2);
expect(IDs).toContain(firstResult.itemFk);
const result = await models.FixedPrice.filter(ctx, null, options);
const firstResult = result[0];
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() => {
const warehouseID = 1;
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))];
const tx = await models.FixedPrice.beginTransaction({});
expect(result.length).toEqual(2);
expect(anyResult.warehouseFk).toEqual(warehouseID);
try {
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() => {
const ctx = {
req: {accessToken: {userId: 1}},
args: {
hasMinPrice: true
}
};
const result = await app.models.FixedPrice.filter(ctx);
const tx = await models.FixedPrice.beginTransaction({});
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() => {
const ctx = {
req: {accessToken: {userId: 1}},
args: {
typeFk: 1
}
};
const result = await app.models.FixedPrice.filter(ctx);
const tx = await models.FixedPrice.beginTransaction({});
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()', () => {
const now = new Date();
const fixedPriceId = 1;
let originalFixedPrice;
let originalItem;
beforeAll(async() => {
originalFixedPrice = await app.models.FixedPrice.findById(fixedPriceId);
originalItem = await app.models.Item.findById(originalFixedPrice.itemFk);
});
afterAll(async() => {
await originalFixedPrice.save();
await originalItem.save();
originalFixedPrice = await models.FixedPrice.findById(fixedPriceId);
});
it(`should toggle the hasMinPrice boolean if there's a minPrice and update the rest of the data`, async() => {
const ctx = {args: {
id: fixedPriceId,
itemFk: originalFixedPrice.itemFk,
warehouseFk: 1,
rate2: 100,
rate3: 300,
started: now,
ended: now,
minPrice: 100,
hasMinPrice: false
}};
const tx = await models.FixedPrice.beginTransaction({});
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;
delete ctx.args.ended;
ctx.args.hasMinPrice = true;
const result = await models.FixedPrice.upsertFixedPrice(ctx, options);
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() => {
const ctx = {args: {
id: fixedPriceId,
itemFk: originalFixedPrice.itemFk,
warehouseFk: 1,
rate2: 2.5,
rate3: 2,
started: now,
ended: now,
minPrice: 0,
hasMinPrice: true
}};
const tx = await models.FixedPrice.beginTransaction({});
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;
delete ctx.args.ended;
ctx.args.hasMinPrice = false;
const result = await models.FixedPrice.upsertFixedPrice(ctx, options);
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', {
description: 'Inserts or updates a fixed price for an item',
accessType: 'WRITE',
accepts: [{
arg: 'ctx',
type: 'object',
http: {source: 'context'}
},
{
arg: 'id',
type: 'number',
description: 'The fixed price id'
},
{
arg: 'itemFk',
type: 'number'
},
{
arg: 'warehouseFk',
type: 'number'
},
{
arg: 'started',
type: 'date'
},
{
arg: 'ended',
type: 'date'
},
{
arg: 'rate2',
type: 'number'
},
{
arg: 'rate3',
type: 'number'
},
{
arg: 'minPrice',
type: 'number'
},
{
arg: 'hasMinPrice',
type: 'any'
}],
accepts: [
{
arg: 'ctx',
type: 'object',
http: {source: 'context'}
},
{
arg: 'id',
type: 'number',
description: 'The fixed price id'
},
{
arg: 'itemFk',
type: 'number'
},
{
arg: 'warehouseFk',
type: 'number'
},
{
arg: 'started',
type: 'date'
},
{
arg: 'ended',
type: 'date'
},
{
arg: 'rate2',
type: 'number'
},
{
arg: 'rate3',
type: 'number'
},
{
arg: 'minPrice',
type: 'number'
},
{
arg: 'hasMinPrice',
type: 'any'
}
],
returns: {
type: 'object',
root: true
@ -54,21 +56,29 @@ module.exports = Self => {
}
});
Self.upsertFixedPrice = async ctx => {
Self.upsertFixedPrice = async(ctx, options) => {
const models = Self.app.models;
const args = ctx.args;
const tx = await models.Address.beginTransaction({});
try {
const options = {transaction: tx};
delete args.ctx; // removed unwanted data
let tx;
const myOptions = {};
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 targetItem = await models.Item.findById(args.itemFk, null, options);
await targetItem.updateAttributes({
minPrice: args.minPrice,
hasMinPrice: args.minPrice ? true : false
}, options);
}, myOptions);
const itemFields = [
'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();
for (let key of itemFields)
result[key] = item[key];
await tx.commit();
if (tx) await tx.commit();
return result;
} catch (e) {
await tx.rollback();
if (tx) await tx.rollback();
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()', () => {
it('should return the same number if there is a barcode and a item with the same ID', async() => {
let barcode = 3;
let result = await app.models.ItemBarcode.toItem(barcode);
const tx = await models.Item.beginTransaction({});
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',
accepts: [{
arg: 'barcode',
type: 'Number',
type: 'number',
required: true,
description: 'barcode'
}],
returns: {
type: 'Number',
type: 'number',
root: true
},
http: {
@ -18,11 +18,18 @@ module.exports = Self => {
}
});
Self.toItem = async barcode => {
let query = `SELECT vn.barcodeToItem(?)`;
let [item] = await Self.rawSql(query, [barcode]);
Self.toItem = async(barcode, options) => {
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const query = `SELECT vn.barcodeToItem(?)`;
let [item] = await Self.rawSql(query, [barcode], myOptions);
if (item)
item = Object.values(item);
return item[0];
item = Object.values(item)[0];
return item;
};
};

View File

@ -5,17 +5,19 @@ module.exports = Self => {
Self.remoteMethod('filterItemTags', {
description: 'Returns the distinct values of a tag property',
accessType: 'READ',
accepts: [{
arg: 'tagFk',
type: 'number',
required: true,
description: 'The foreign key from tag table',
http: {source: 'path'}
}, {
arg: 'filter',
type: 'Object',
description: `Filter defining where, order, offset, and limit - must be a JSON-encoded string`
}],
accepts: [
{
arg: 'tagFk',
type: 'number',
required: true,
description: 'The foreign key from tag table',
http: {source: 'path'}
}, {
arg: 'filter',
type: 'object',
description: `Filter defining where, order, offset, and limit - must be a JSON-encoded string`
}
],
returns: {
root: true,
type: ['object']
@ -26,16 +28,21 @@ module.exports = Self => {
}
});
Self.filterItemTags = async(tagFk, filter) => {
let conn = Self.dataSource.connector;
let where = {tagFk: tagFk};
myFilter = mergeFilters(filter, {where});
Self.filterItemTags = async(tagFk, filter, options) => {
const conn = Self.dataSource.connector;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const where = {tagFk: tagFk};
const myFilter = mergeFilters(filter, {where});
stmt = new ParameterizedSQL(
`SELECT DISTINCT(value)
FROM itemTag`);
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()', () => {
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'}
}],
returns: {
type: 'Object',
type: 'object',
description: 'new cloned itemId',
root: true,
},
@ -22,13 +22,21 @@ module.exports = Self => {
}
});
Self.clone = async itemId => {
let tx = await Self.beginTransaction({});
Self.clone = async(itemId, options) => {
let tx;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
let options = {transaction: tx};
const origin = await Self.findById(itemId, null, myOptions);
const origin = await Self.findById(itemId, null, options);
if (!origin)
throw new UserError(`This item doesn't exists`);
@ -38,16 +46,17 @@ module.exports = Self => {
origin.comment = 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 cloneBotanical(origin.id, newItem.id, options);
await cloneTags(origin.id, newItem.id, options);
await cloneTaxes(origin.id, newItem.id, myOptions);
await cloneBotanical(origin.id, newItem.id, myOptions);
await cloneTags(origin.id, newItem.id, myOptions);
if (tx) await tx.commit();
await tx.commit();
return newItem;
} catch (e) {
await tx.rollback();
if (tx) await tx.rollback();
throw e;
}
};

View File

@ -2,23 +2,25 @@ module.exports = Self => {
Self.remoteMethod('createIntrastat', {
description: 'Creates a new item intrastat',
accessType: 'WRITE',
accepts: [{
arg: 'id',
type: 'number',
required: true,
description: 'The item id',
http: {source: 'path'}
},
{
arg: 'intrastatId',
type: 'number',
required: true
},
{
arg: 'description',
type: 'string',
required: true
}],
accepts: [
{
arg: 'id',
type: 'number',
required: true,
description: 'The item id',
http: {source: 'path'}
},
{
arg: 'intrastatId',
type: 'number',
required: true
},
{
arg: 'description',
type: 'string',
required: true
}
],
returns: {
type: 'boolean',
root: true
@ -29,31 +31,52 @@ module.exports = Self => {
}
});
Self.createIntrastat = async(id, intrastatId, description) => {
Self.createIntrastat = async(id, intrastatId, description, options) => {
const models = Self.app.models;
const country = await models.Country.findOne({
where: {code: 'ES'}
});
const myOptions = {};
let tx;
const itemTaxCountry = await models.ItemTaxCountry.findOne({
where: {
itemFk: id,
countryFk: country.id
},
order: 'effectived DESC'
});
const taxClassCode = await models.TaxClassCode.findOne({
where: {
taxClassFk: itemTaxCountry.taxClassFk
},
order: 'effectived DESC'
});
if (typeof options == 'object')
Object.assign(myOptions, options);
return models.Intrastat.create({
id: intrastatId,
description: description,
taxClassFk: itemTaxCountry.taxClassFk,
taxCodeFk: taxClassCode.taxCodeFk
});
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const country = await models.Country.findOne({
where: {code: 'ES'}
}, myOptions);
const itemTaxCountry = await models.ItemTaxCountry.findOne({
where: {
itemFk: id,
countryFk: country.id
},
order: 'effectived DESC'
}, myOptions);
const taxClassCode = await models.TaxClassCode.findOne({
where: {
taxClassFk: itemTaxCountry.taxClassFk
},
order: 'effectived DESC'
}, myOptions);
const intrastat = await models.Intrastat.create({
id: intrastatId,
description: description,
taxClassFk: itemTaxCountry.taxClassFk,
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) => {
const conn = Self.dataSource.connector;
let myOptions = {};
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
@ -83,7 +83,9 @@ module.exports = Self => {
where: {code: ctx.args.search},
fields: ['itemFk']
}, myOptions);
const itemIds = [];
for (const item of items)
itemIds.push(item.itemFk);
@ -116,12 +118,11 @@ module.exports = Self => {
return {'intr.description': value};
}
});
filter = mergeFilters(filter, {where});
const stmts = [];
let stmt;
stmt = new ParameterizedSQL(
const stmt = new ParameterizedSQL(
`SELECT
i.id,
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;
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)
if (entry.clientType === 'loses') entry.highlighted = true;

View File

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

View File

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

View File

@ -17,7 +17,7 @@ module.exports = Self => {
}
],
returns: {
type: ['Object'],
type: ['object'],
root: true
},
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(`
SELECT *, 100 * dwindle / total AS percentage
FROM (
@ -41,7 +46,7 @@ module.exports = Self => {
AND week = WEEK(TIMESTAMPADD(WEEK,-1,CURDATE()), 1)
GROUP BY buyer, itemFk
) sub
ORDER BY family, percentage DESC`, [buyer, family]);
ORDER BY family, percentage DESC`, [buyer, family], myOptions);
const details = [];

View File

@ -4,7 +4,7 @@ module.exports = Self => {
accessType: 'READ',
accepts: [],
returns: {
type: ['Object'],
type: ['object'],
root: true
},
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(`
SELECT *, 100 * dwindle / total AS percentage
FROM (
@ -26,7 +31,7 @@ module.exports = Self => {
AND week = WEEK(TIMESTAMPADD(WEEK,-1,CURDATE()), 1)
GROUP BY buyer, family
) sub
ORDER BY percentage DESC`);
ORDER BY percentage DESC`, null, myOptions);
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 myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const stmt = new ParameterizedSQL(
`SELECT
w.id AS warehouseFk,
@ -64,6 +69,6 @@ module.exports = Self => {
LEFT JOIN edi.ekt ek ON b.ektFk = ek.id`);
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 => {
Self.remoteMethod('new', {
description: 'Create a new item and returns the new ID',
description: 'returns the created item',
accessType: 'WRITE',
accepts: [{
arg: 'params',
@ -19,8 +19,20 @@ module.exports = Self => {
}
});
Self.new = async params => {
let validUpdateParams = [
Self.new = async(params, options) => {
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',
'typeFk',
'intrastatFk',
@ -33,20 +45,21 @@ module.exports = Self => {
throw new UserError(`You don't have enough privileges to do that`);
}
let tx = await Self.beginTransaction({});
try {
let options = {transaction: tx};
let provisionalName = params.provisionalName;
const provisionalName = 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`;
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 = [];
@ -55,17 +68,19 @@ module.exports = Self => {
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`;
await Self.rawSql(query, null, options);
await Self.rawSql(query, null, myOptions);
query = `CALL vn.itemRefreshTags(?)`;
await Self.rawSql(query, [item.id], options);
await tx.commit();
await Self.rawSql(query, [item.id], myOptions);
if (tx) await tx.commit();
return item;
} catch (e) {
await tx.rollback();
if (tx) await tx.rollback();
throw e;
}
};

View File

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

View File

@ -1,4 +1,4 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('item clone()', () => {
let nextItemId;
@ -8,30 +8,47 @@ describe('item clone()', () => {
LEFT JOIN vn.item i2 ON i1.id + 1 = i2.id
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;
});
it('should clone the given item and it should have the expected id', async() => {
let itemFk = 1;
let result = await app.models.Item.clone(itemFk);
const tx = await models.FixedPrice.beginTransaction({});
expect(result.id).toEqual(nextItemId);
expect(result.image).toBeUndefined();
expect(result.itemTag).toBeUndefined();
expect(result.comment).toBeUndefined();
expect(result.description).toBeUndefined();
try {
const options = {transaction: tx};
const itemFk = 1;
const result = await models.Item.clone(itemFk, options);
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() => {
let error;
let itemFk = 999;
await app.models.Item.clone(itemFk)
.catch(e => {
expect(e.message).toContain(`This item doesn't exists`);
error = e;
});
const tx = await models.FixedPrice.beginTransaction({});
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()', () => {
let newIntrastat;
afterAll(async done => {
await app.models.Intrastat.destroyById(newIntrastat.id);
done();
});
it('should create a new intrastat', async() => {
const intrastatId = 588420239;
const description = 'Tropical Flowers';
const itemId = 9;
newIntrastat = await app.models.Item.createIntrastat(itemId, intrastatId, description);
const tx = await models.FixedPrice.beginTransaction({});
expect(newIntrastat.description).toEqual(description);
expect(newIntrastat.taxClassFk).toEqual(1);
expect(newIntrastat.taxCodeFk).toEqual(21);
try {
const options = {transaction: tx};
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()', () => {
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};
try {
const filter = {};
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[0].id).toEqual(1);
@ -21,13 +21,13 @@ describe('item filter()', () => {
});
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};
try {
const filter = {};
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[0].id).toEqual(2);
@ -40,7 +40,7 @@ describe('item filter()', () => {
});
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};
try {
@ -50,7 +50,7 @@ describe('item filter()', () => {
};
const tags = [{value: 'medical box', tagFk: 58}];
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);

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

View File

@ -1,16 +1,27 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('item getSummary()', () => {
it('should return summary with item, tags, botanical, niches, available and visible defined ', async() => {
const ctx = {req: {accessToken: {userId: 1}}};
let result = await app.models.Item.getSummary(ctx, 1);
let keys = Object.keys(result);
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
expect(keys).toContain('item');
expect(keys).toContain('tags');
expect(keys).toContain('botanical');
expect(keys).toContain('niches');
expect(keys).toContain('available');
expect(keys).toContain('visible');
try {
const ctx = {req: {accessToken: {userId: 1}}};
const result = await models.Item.getSummary(ctx, 1, options);
const keys = Object.keys(result);
expect(keys).toContain('item');
expect(keys).toContain('tags');
expect(keys).toContain('botanical');
expect(keys).toContain('niches');
expect(keys).toContain('available');
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()', () => {
it('should check available visible for today', async() => {
const itemFk = 1;
const warehouseFk = 1;
const dated = new Date();
let result = await app.models.Item.getVisibleAvailable(itemFk, warehouseFk, dated);
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
expect(result.available).toEqual(187);
expect(result.visible).toEqual(92);
});
try {
const itemFk = 1;
const warehouseFk = 1;
const dated = new Date();
it('should check available visible for no dated', async() => {
const itemFk = 1;
const warehouseFk = 1;
let result = await app.models.Item.getVisibleAvailable(itemFk, warehouseFk);
const result = await models.Item.getVisibleAvailable(itemFk, warehouseFk, dated, options);
expect(result.available).toEqual(187);
expect(result.visible).toEqual(92);
expect(result.available).toEqual(187);
expect(result.visible).toEqual(92);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should check available visible for yesterday', async() => {
const itemFk = 1;
const warehouseFk = 1;
let dated = new Date();
dated.setDate(dated.getDate() - 1);
let result = await app.models.Item.getVisibleAvailable(itemFk, warehouseFk, dated);
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
expect(result.available).toEqual(0);
expect(result.visible).toEqual(92);
try {
const itemFk = 1;
const warehouseFk = 1;
const dated = new Date();
dated.setDate(dated.getDate() - 1);
const result = await models.Item.getVisibleAvailable(itemFk, warehouseFk, dated, options);
expect(result.available).toEqual(0);
expect(result.visible).toEqual(92);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -1,14 +1,24 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('Item getWasteByItem()', () => {
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};
const length = result.length;
const anyResult = result[Math.floor(Math.random() * Math.floor(length))];
try {
const result = await models.Item.getWasteByItem('CharlesXavier', 'Cymbidium', options);
expect(anyResult.buyer).toEqual('CharlesXavier');
expect(anyResult.family).toEqual('Cymbidium');
expect(anyResult.lines.length).toBeGreaterThanOrEqual(2);
const length = result.length;
const anyResult = result[Math.floor(Math.random() * Math.floor(length))];
expect(anyResult.buyer).toEqual('CharlesXavier');
expect(anyResult.family).toEqual('Cymbidium');
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()', () => {
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};
const length = result.length;
const anyResult = result[Math.floor(Math.random() * Math.floor(length))];
try {
const result = await models.Item.getWasteByWorker(options);
expect(anyResult.buyer).toMatch(/(CharlesXavier|HankPym|DavidCharlesHaller)/);
expect(anyResult.lines.length).toBeGreaterThanOrEqual(3);
const length = result.length;
const anyResult = result[Math.floor(Math.random() * Math.floor(length))];
expect(anyResult.buyer).toMatch(/(CharlesXavier|HankPym|DavidCharlesHaller)/);
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()', () => {
const minDate = new Date(value);
@ -7,18 +7,38 @@ describe('item lastEntriesFilter()', () => {
maxHour.setHours(23, 59, 59, 59);
it('should return one entry for a given item', async() => {
const filter = {where: {itemFk: 1, landed: {between: [minDate, maxDate]}}};
const result = await app.models.Item.lastEntriesFilter(filter);
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
expect(result.length).toEqual(1);
try {
const filter = {where: {itemFk: 1, landed: {between: [minDate, maxDate]}}};
const result = await models.Item.lastEntriesFilter(filter, options);
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() => {
minDate.setMonth(minDate.getMonth() - 2, 1);
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
const filter = {where: {itemFk: 1, landed: {between: [minDate, maxDate]}}};
const result = await app.models.Item.lastEntriesFilter(filter);
try {
minDate.setMonth(minDate.getMonth() - 2, 1);
expect(result.length).toEqual(5);
const filter = {where: {itemFk: 1, landed: {between: [minDate, maxDate]}}};
const result = await models.Item.lastEntriesFilter(filter, options);
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()', () => {
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() => {
let itemParams = {
intrastatFk: 5080000,
originFk: 1,
provisionalName: 'planta',
typeFk: 2,
relevancy: 0
};
item = await app.models.Item.new(itemParams);
let temporalNameTag = await app.models.Tag.findOne({where: {name: 'Nombre temporal'}});
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
let temporalName = await app.models.ItemTag.findOne({
where: {
itemFk: item.id,
tagFk: temporalNameTag.id,
}
});
item = await app.models.Item.findById(item.id);
try {
const itemParams = {
intrastatFk: 5080000,
originFk: 1,
provisionalName: 'planta',
typeFk: 2,
relevancy: 0
};
expect(item.intrastatFk).toEqual(5080000);
expect(item.originFk).toEqual(1);
expect(item.typeFk).toEqual(2);
expect(item.name).toEqual('planta');
expect(temporalName.value).toEqual('planta');
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: {
itemFk: item.id,
tagFk: temporalNameTag.id,
}
}, options);
item = await models.Item.findById(item.id, null, options);
expect(item.intrastatFk).toEqual(5080000);
expect(item.originFk).toEqual(1);
expect(item.typeFk).toEqual(2);
expect(item.name).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()', () => {
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() => {
let ctx = {req: {accessToken: {userId: 18}}};
let res = await app.models.Item.getVisibleAvailable(itemFk, warehouseFk);
let visible = res.visible;
let saleQuantity = visible - 11;
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
let ticketFk = await app.models.Item.regularize(ctx, itemFk, 11, warehouseFk);
let sale = await app.models.Sale.findOne({where: {ticketFk: ticketFk}});
trashTicket = await app.models.Ticket.findById(ticketFk);
try {
const ctx = {req: {accessToken: {userId: 18}}};
const itemId = 1;
const warehouseId = 1;
const quantity = 11;
const date = undefined;
expect(sale.quantity).toEqual(saleQuantity);
expect(sale.discount).toEqual(100);
expect(trashTicket.addressFk).toEqual(trashAddress);
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);
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()', () => {
let taxesInFixtures = [{id: 3, taxClassFk: 1}];
it('should throw an error if the taxClassFk is blank', async() => {
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
let error;
let taxes = [{id: 3, taxClassFk: undefined}];
await app.models.Item.updateTaxes(taxes)
.catch(err => {
expect(err.message).toEqual('Tax class cannot be blank');
error = err;
});
try {
const taxes = [{id: 3, taxClassFk: undefined}];
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() => {
let taxCountry = await app.models.ItemTaxCountry.findById(3);
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
expect(taxCountry.taxClassFk).toEqual(1);
try {
let taxCountry = await models.ItemTaxCountry.findById(3, null, options);
let taxes = [{id: 3, taxClassFk: 2}];
expect(taxCountry.taxClassFk).toEqual(1);
await app.models.Item.updateTaxes(taxes);
taxCountry = await app.models.ItemTaxCountry.findById(3);
const taxes = [{id: 3, taxClassFk: 2}];
expect(taxCountry.taxClassFk).toEqual(2);
await models.Item.updateTaxes(taxes, options);
// restores
await app.models.Item.updateTaxes(taxesInFixtures);
taxCountry = await models.ItemTaxCountry.findById(3, null, options);
expect(taxCountry.taxClassFk).toEqual(2);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -21,18 +21,38 @@ module.exports = Self => {
}
});
Self.updateTaxes = async taxes => {
let promises = [];
for (let tax of taxes) {
if (!tax.taxClassFk)
throw new UserError('Tax class cannot be blank');
Self.updateTaxes = async(taxes, options) => {
const myOptions = {};
let tx;
promises.push(Self.app.models.ItemTaxCountry.update(
{id: tax.id},
{taxClassFk: tax.taxClassFk}
));
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) {
if (!tax.taxClassFk)
throw new UserError('Tax class cannot be blank');
promises.push(Self.app.models.ItemTaxCountry.update(
{id: tax.id},
{taxClassFk: tax.taxClassFk}
), myOptions);
}
await Promise.all(promises);
if (tx) await tx.commit();
return true;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
await Promise.all(promises);
return true;
};
};

View File

@ -3,17 +3,20 @@ const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
module.exports = Self => {
Self.remoteMethod('filterValue', {
description: 'Returns a list of tag values',
accepts: [{
arg: 'id',
type: 'Number',
required: true,
description: 'The tag id',
http: {source: 'path'}
}, {
arg: 'filter',
type: 'Object',
description: `Filter defining where, order, offset, and limit - must be a JSON-encoded string`
}],
accepts: [
{
arg: 'id',
type: 'number',
required: true,
description: 'The tag id',
http: {source: 'path'}
},
{
arg: 'filter',
type: 'object',
description: `Filter defining where, order, offset, and limit - must be a JSON-encoded string`
}
],
returns: {
type: ['object'],
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 tag = await Self.findById(id);
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
const tag = await Self.findById(id);
let stmt;
if (!tag.isFree && tag.sourceTable) {
stmt = new ParameterizedSQL(
`SELECT value FROM (
@ -36,7 +44,7 @@ module.exports = Self => {
} else
stmt = new ParameterizedSQL(`SELECT value FROM itemTag`);
let where = filter.where;
const where = filter.where;
if (where && where.value) {
stmt.merge(conn.makeWhere({value: {like: `%${where.value}%`}}));
stmt.merge(`
@ -46,6 +54,6 @@ module.exports = Self => {
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()', () => {
const colorTagId = 1;
it('should return a list of color values', async() => {
const filter = {limit: 5};
const result = await app.models.Tag.filterValue(colorTagId, filter);
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
expect(result.length).toEqual(5);
try {
const filter = {limit: 5};
const result = await models.Tag.filterValue(colorTagId, filter, options);
expect(result.length).toEqual(5);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the values matching color "Blue"', async() => {
const filter = {where: {value: 'Blue'}, limit: 5};
const result = await app.models.Tag.filterValue(colorTagId, filter);
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
expect(result.length).toEqual(2);
expect(result[0].value).toEqual('Blue');
expect(result[1].value).toEqual('Blue/Silver');
try {
const filter = {where: {value: 'Blue'}, limit: 5};
const result = await models.Tag.filterValue(colorTagId, filter, options);
expect(result.length).toEqual(2);
expect(result[0].value).toEqual('Blue');
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() => {
const filter = {where: {value: 'Blue/Silver'}, limit: 5};
const result = await app.models.Tag.filterValue(colorTagId, filter);
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
expect(result.length).toEqual(1);
expect(result[0].value).toEqual('Blue/Silver');
try {
const filter = {where: {value: 'Blue/Silver'}, limit: 5};
const result = await models.Tag.filterValue(colorTagId, filter, options);
expect(result.length).toEqual(1);
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() => {
const filter = {where: {value: 'Silver'}, limit: 5};
const result = await app.models.Tag.filterValue(colorTagId, filter);
const tx = await models.Item.beginTransaction({});
const options = {transaction: tx};
expect(result.length).toEqual(2);
expect(result[0].value).toEqual('Silver');
expect(result[1].value).toEqual('Blue/Silver');
try {
const filter = {where: {value: 'Silver'}, limit: 5};
const result = await models.Tag.filterValue(colorTagId, filter, options);
expect(result.length).toEqual(2);
expect(result[0].value).toEqual('Silver');
expect(result[1].value).toEqual('Blue/Silver');
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});