Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5472-user_passExpired
gitea/salix/pipeline/head There was a failure building this commit
Details
gitea/salix/pipeline/head There was a failure building this commit
Details
This commit is contained in:
commit
ac0e7ae32b
|
@ -0,0 +1,28 @@
|
||||||
|
CREATE TABLE `vn`.`buyConfig` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`monthsAgo` int(11) NOT NULL DEFAULT 6 COMMENT 'Meses desde la última compra',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||||
|
|
||||||
|
CREATE TABLE `vn`.`travelConfig` (
|
||||||
|
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`warehouseInFk` smallint(6) unsigned NOT NULL DEFAULT 8 COMMENT 'Warehouse de origen',
|
||||||
|
`warehouseOutFk` smallint(6) unsigned NOT NULL DEFAULT 60 COMMENT 'Warehouse destino',
|
||||||
|
`agencyFk` int(11) NOT NULL DEFAULT 1378 COMMENT 'Agencia por defecto',
|
||||||
|
`companyFk` smallint(5) unsigned NOT NULL DEFAULT 442 COMMENT 'Compañía por defecto',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `travelConfig_FK` (`warehouseInFk`),
|
||||||
|
KEY `travelConfig_FK_1` (`warehouseOutFk`),
|
||||||
|
KEY `travelConfig_FK_2` (`agencyFk`),
|
||||||
|
KEY `travelConfig_FK_3` (`companyFk`),
|
||||||
|
CONSTRAINT `travelConfig_FK` FOREIGN KEY (`warehouseInFk`) REFERENCES `warehouse` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||||
|
CONSTRAINT `travelConfig_FK_1` FOREIGN KEY (`warehouseOutFk`) REFERENCES `warehouse` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||||
|
CONSTRAINT `travelConfig_FK_2` FOREIGN KEY (`agencyFk`) REFERENCES `agencyMode` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||||
|
CONSTRAINT `travelConfig_FK_3` FOREIGN KEY (`companyFk`) REFERENCES `company` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||||
|
|
||||||
|
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||||
|
VALUES
|
||||||
|
('Entry', 'addFromPackaging', 'WRITE', 'ALLOW', 'ROLE', 'production'),
|
||||||
|
('Entry', 'addFromBuy', 'WRITE', 'ALLOW', 'ROLE', 'production'),
|
||||||
|
('Supplier', 'getItemsPackaging', 'READ', 'ALLOW', 'ROLE', 'production');
|
|
@ -909,7 +909,7 @@ INSERT INTO `vn`.`itemFamily`(`code`, `description`)
|
||||||
INSERT INTO `vn`.`item`(`id`, `typeFk`, `size`, `inkFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `expenceFk`,
|
INSERT INTO `vn`.`item`(`id`, `typeFk`, `size`, `inkFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `expenceFk`,
|
||||||
`comment`, `relevancy`, `image`, `subName`, `minPrice`, `stars`, `family`, `isFloramondo`, `genericFk`, `itemPackingTypeFk`, `hasMinPrice`, `packingShelve`, `weightByPiece`)
|
`comment`, `relevancy`, `image`, `subName`, `minPrice`, `stars`, `family`, `isFloramondo`, `genericFk`, `itemPackingTypeFk`, `hasMinPrice`, `packingShelve`, `weightByPiece`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '1', NULL, 0, 1, 'VT', 0, NULL, 'V', 0, 15,3),
|
(1, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '1', NULL, 0, 1, 'EMB', 0, NULL, 'V', 0, 15,3),
|
||||||
(2, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '2', NULL, 0, 2, 'VT', 0, NULL, 'H', 0, 10,2),
|
(2, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '2', NULL, 0, 2, 'VT', 0, NULL, 'H', 0, 10,2),
|
||||||
(3, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '3', NULL, 0, 5, 'VT', 0, NULL, NULL, 0, 5,5),
|
(3, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '3', NULL, 0, 5, 'VT', 0, NULL, NULL, 0, 5,5),
|
||||||
(4, 1, 60, 'YEL', 1, 1, 'Increases block', 1, 05080000, 4751000000, NULL, 0, '4', NULL, 0, 3, 'VT', 0, NULL, NULL, 0, NULL,NULL),
|
(4, 1, 60, 'YEL', 1, 1, 'Increases block', 1, 05080000, 4751000000, NULL, 0, '4', NULL, 0, 3, 'VT', 0, NULL, NULL, 0, NULL,NULL),
|
||||||
|
@ -2890,6 +2890,10 @@ INSERT INTO `vn`.`wagonTypeTray` (`id`, `typeFk`, `height`, `colorFk`)
|
||||||
(2, 1, 50, 2),
|
(2, 1, 50, 2),
|
||||||
(3, 1, 0, 3);
|
(3, 1, 0, 3);
|
||||||
|
|
||||||
|
INSERT INTO `vn`.`travelConfig` (`id`, `warehouseInFk`, `warehouseOutFk`, `agencyFk`, `companyFk`)
|
||||||
|
VALUES
|
||||||
|
(1, 1, 1, 1, 442);
|
||||||
|
|
||||||
|
INSERT INTO `vn`.`buyConfig` (`id`, `monthsAgo`)
|
||||||
|
VALUES
|
||||||
|
(1, 6);
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
|
||||||
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||||
const UserError = require('vn-loopback/util/user-error');
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
const utils = require('loopback/lib/utils');
|
||||||
|
const {util} = require('webpack');
|
||||||
|
|
||||||
module.exports = function(Self) {
|
module.exports = function(Self) {
|
||||||
Self.ParameterizedSQL = ParameterizedSQL;
|
Self.ParameterizedSQL = ParameterizedSQL;
|
||||||
|
@ -164,23 +166,21 @@ module.exports = function(Self) {
|
||||||
|
|
||||||
function rewriteMethod(methodName) {
|
function rewriteMethod(methodName) {
|
||||||
const realMethod = this[methodName];
|
const realMethod = this[methodName];
|
||||||
return async(data, options, cb) => {
|
return function(...args) {
|
||||||
if (options instanceof Function) {
|
let cb;
|
||||||
cb = options;
|
const lastArg = args[args.length - 1];
|
||||||
options = null;
|
if (lastArg instanceof Function) {
|
||||||
}
|
cb = lastArg;
|
||||||
|
args.pop();
|
||||||
|
} else
|
||||||
|
cb = utils.createPromiseCallback();
|
||||||
|
|
||||||
try {
|
args.push(function(err, res) {
|
||||||
const result = await realMethod.call(this, data, options);
|
if (err) err = replaceErr(err, replaceErrFunc);
|
||||||
|
cb(err, res);
|
||||||
if (cb) cb(null, result);
|
});
|
||||||
else return result;
|
realMethod.apply(this, args);
|
||||||
} catch (err) {
|
return cb.promise;
|
||||||
let myErr = replaceErr(err, replaceErrFunc);
|
|
||||||
if (cb) cb(myErr);
|
|
||||||
else
|
|
||||||
throw myErr;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('addFromBuy', {
|
||||||
|
description: 'Modify a field of a buy or creates a new one with default values',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [{
|
||||||
|
arg: 'id',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
description: 'The entry id',
|
||||||
|
http: {source: 'path'}
|
||||||
|
}, {
|
||||||
|
arg: 'item',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
description: 'The item id',
|
||||||
|
}, {
|
||||||
|
arg: 'printedStickers',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
description: 'The field to modify',
|
||||||
|
}],
|
||||||
|
returns: {
|
||||||
|
type: 'object',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/:id/addFromBuy`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.addFromBuy = async(ctx, options) => {
|
||||||
|
const args = ctx.args;
|
||||||
|
const models = Self.app.models;
|
||||||
|
const userId = ctx.req.accessToken.userId;
|
||||||
|
const myOptions = {userId};
|
||||||
|
let tx;
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
let buy = await models.Buy.findOne({where: {entryFk: args.id}}, myOptions);
|
||||||
|
if (buy)
|
||||||
|
await buy.updateAttribute('printedStickers', args.printedStickers);
|
||||||
|
else {
|
||||||
|
const userConfig = await models.UserConfig.findById(userId, {fields: ['warehouseFk']}, myOptions);
|
||||||
|
await Self.rawSql(
|
||||||
|
'CALL vn.buyUltimate(?,?)',
|
||||||
|
[userConfig.warehouseFk, null],
|
||||||
|
myOptions
|
||||||
|
);
|
||||||
|
let buyUltimate = await Self.rawSql(
|
||||||
|
`SELECT buyFk
|
||||||
|
FROM tmp.buyUltimate
|
||||||
|
WHERE itemFk = ?`,
|
||||||
|
[args.item],
|
||||||
|
myOptions
|
||||||
|
);
|
||||||
|
buyUltimate = await models.Buy.findById(buyUltimate[0].buyFk, null, myOptions);
|
||||||
|
buy = await models.Buy.create({
|
||||||
|
entryFk: args.id,
|
||||||
|
itemFk: args.item,
|
||||||
|
quantity: 0,
|
||||||
|
dispatched: buyUltimate.dispatched,
|
||||||
|
buyingValue: buyUltimate.buyingValue,
|
||||||
|
freightValue: buyUltimate.freightValue,
|
||||||
|
isIgnored: buyUltimate.isIgnored,
|
||||||
|
stickers: buyUltimate.stickers,
|
||||||
|
packing: buyUltimate.packing,
|
||||||
|
grouping: buyUltimate.grouping,
|
||||||
|
groupingMode: buyUltimate.groupingMode,
|
||||||
|
containerFk: buyUltimate.containerFk,
|
||||||
|
comissionValue: buyUltimate.comissionValue,
|
||||||
|
packageValue: buyUltimate.packageValue,
|
||||||
|
location: buyUltimate.location,
|
||||||
|
packageFk: buyUltimate.packageFk,
|
||||||
|
price1: buyUltimate.price1,
|
||||||
|
price2: buyUltimate.price2,
|
||||||
|
price3: buyUltimate.price3,
|
||||||
|
minPrice: buyUltimate.minPrice,
|
||||||
|
printedStickers: args.printedStickers,
|
||||||
|
workerFk: buyUltimate.workerFk,
|
||||||
|
isChecked: buyUltimate.isChecked,
|
||||||
|
isPickedOff: buyUltimate.isPickedOff,
|
||||||
|
created: buyUltimate.created,
|
||||||
|
ektFk: buyUltimate.ektFk,
|
||||||
|
weight: buyUltimate.weight,
|
||||||
|
deliveryFk: buyUltimate.deliveryFk,
|
||||||
|
itemOriginalFk: buyUltimate.itemOriginalFk
|
||||||
|
}, myOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tx) await tx.commit();
|
||||||
|
return buy;
|
||||||
|
} catch (e) {
|
||||||
|
if (tx) await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,72 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('addFromPackaging', {
|
||||||
|
description: 'Create a receipt or return entry for a supplier with a specific travel',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [{
|
||||||
|
arg: 'supplier',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
description: 'The supplier id',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'isTravelReception',
|
||||||
|
type: 'boolean',
|
||||||
|
required: true,
|
||||||
|
description: 'Indicates if the travel associated with the entry is a return or receipt travel'
|
||||||
|
}],
|
||||||
|
returns: {
|
||||||
|
type: 'object',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/addFromPackaging`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.addFromPackaging = async(ctx, options) => {
|
||||||
|
const args = ctx.args;
|
||||||
|
const models = Self.app.models;
|
||||||
|
let tx;
|
||||||
|
const myOptions = {};
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const travelConfig = await models.TravelConfig.findOne({}, myOptions);
|
||||||
|
|
||||||
|
const today = new Date();
|
||||||
|
const yesterday = new Date(today);
|
||||||
|
yesterday.setDate(today.getDate() - 1);
|
||||||
|
const tomorrow = new Date(today);
|
||||||
|
tomorrow.setDate(today.getDate() + 1);
|
||||||
|
|
||||||
|
const travel = await models.Travel.create({
|
||||||
|
shipped: args.isTravelReception ? yesterday : today,
|
||||||
|
landed: args.isTravelReception ? today : tomorrow,
|
||||||
|
agencyModeFk: travelConfig.agencyFk,
|
||||||
|
warehouseInFk: travelConfig.warehouseOutFk,
|
||||||
|
warehouseOutFk: travelConfig.warehouseInFk
|
||||||
|
}, myOptions);
|
||||||
|
|
||||||
|
const entry = await models.Entry.create({
|
||||||
|
supplierFk: args.supplier,
|
||||||
|
travelFk: travel.id,
|
||||||
|
companyFk: travelConfig.companyFk
|
||||||
|
}, myOptions);
|
||||||
|
|
||||||
|
if (tx) await tx.commit();
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
} catch (e) {
|
||||||
|
if (tx) await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,51 @@
|
||||||
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
|
||||||
|
describe('entry addFromBuy()', () => {
|
||||||
|
const ctx = {req: {accessToken: {userId: 18}}};
|
||||||
|
|
||||||
|
it('should change the printedStickers of an existent buy', async() => {
|
||||||
|
const id = 1;
|
||||||
|
const item = 1;
|
||||||
|
const buy = 1;
|
||||||
|
|
||||||
|
const tx = await models.Entry.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
try {
|
||||||
|
const currentBuy = await models.Buy.findById(buy, {fields: ['printedStickers']}, options);
|
||||||
|
const printedStickers = currentBuy.printedStickers + 10;
|
||||||
|
ctx.args = {id, item, printedStickers};
|
||||||
|
const newBuy = await models.Entry.addFromBuy(ctx, options);
|
||||||
|
|
||||||
|
expect(newBuy.printedStickers).toEqual(printedStickers);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create for an entry without a concrete item a new buy', async() => {
|
||||||
|
const id = 8;
|
||||||
|
const item = 1;
|
||||||
|
const printedStickers = 10;
|
||||||
|
|
||||||
|
const tx = await models.Entry.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
try {
|
||||||
|
const emptyBuy = await models.Buy.findOne({where: {entryFk: id}}, options);
|
||||||
|
ctx.args = {id, item, printedStickers};
|
||||||
|
const newBuy = await models.Entry.addFromBuy(ctx, options);
|
||||||
|
|
||||||
|
expect(emptyBuy).toEqual(null);
|
||||||
|
expect(newBuy.entryFk).toEqual(id);
|
||||||
|
expect(newBuy.printedStickers).toEqual(printedStickers);
|
||||||
|
expect(newBuy.itemFk).toEqual(item);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,49 @@
|
||||||
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
|
describe('entry addFromPackaging()', () => {
|
||||||
|
const supplier = 442;
|
||||||
|
const today = new Date();
|
||||||
|
const yesterday = new Date(today);
|
||||||
|
yesterday.setDate(today.getDate() - 1);
|
||||||
|
|
||||||
|
beforeAll(async() => {
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 49},
|
||||||
|
http: {
|
||||||
|
req: {
|
||||||
|
headers: {origin: 'http://localhost'},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create an incoming travel', async() => {
|
||||||
|
const ctx = {args: {isTravelReception: true, supplier}};
|
||||||
|
const tx = await models.Entry.beginTransaction({});
|
||||||
|
const options = {transaction: tx};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const entry = await models.Entry.addFromPackaging(ctx, options);
|
||||||
|
const travelConfig = await models.TravelConfig.findOne({}, options);
|
||||||
|
const travel = await models.Travel.findOne({order: 'id DESC'}, options);
|
||||||
|
|
||||||
|
expect(new Date(travel.shipped).getDate()).toEqual(yesterday.getDate());
|
||||||
|
expect(new Date(travel.landed).getDate()).toEqual(today.getDate());
|
||||||
|
expect(travel.agencyModeFk).toEqual(travelConfig.agencyFk);
|
||||||
|
expect(travel.warehouseInFk).toEqual(travelConfig.warehouseOutFk);
|
||||||
|
expect(travel.warehouseOutFk).toEqual(travelConfig.warehouseInFk);
|
||||||
|
expect(entry.supplierFk).toEqual(supplier);
|
||||||
|
expect(entry.travelFk).toEqual(travel.id);
|
||||||
|
expect(entry.companyFk).toEqual(travelConfig.companyFk);
|
||||||
|
|
||||||
|
await tx.rollback();
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -5,6 +5,9 @@
|
||||||
"Buy": {
|
"Buy": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"BuyConfig": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"ItemMatchProperties": {
|
"ItemMatchProperties": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"name": "BuyConfig",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "buyConfig"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "number",
|
||||||
|
"id": true
|
||||||
|
},
|
||||||
|
"showLastBuy": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,6 +39,9 @@
|
||||||
"packageValue": {
|
"packageValue": {
|
||||||
"type": "number"
|
"type": "number"
|
||||||
},
|
},
|
||||||
|
"price1": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
"price2": {
|
"price2": {
|
||||||
"type": "number"
|
"type": "number"
|
||||||
},
|
},
|
||||||
|
@ -47,7 +50,44 @@
|
||||||
},
|
},
|
||||||
"weight": {
|
"weight": {
|
||||||
"type": "number"
|
"type": "number"
|
||||||
|
},
|
||||||
|
"printedStickers": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"dispatched": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"isIgnored": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"containerFk": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"minPrice": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"isChecked": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"isPickedOff": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"created": {
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
"ektFk": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"itemOriginalFk": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"editorFk": {
|
||||||
|
"type": "number"
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
"relations": {
|
"relations": {
|
||||||
"entry": {
|
"entry": {
|
||||||
|
@ -64,6 +104,16 @@
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "Packaging",
|
"model": "Packaging",
|
||||||
"foreignKey": "packageFk"
|
"foreignKey": "packageFk"
|
||||||
|
},
|
||||||
|
"worker": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Worker",
|
||||||
|
"foreignKey": "workerFk"
|
||||||
|
},
|
||||||
|
"delivery": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Delivery",
|
||||||
|
"foreignKey": "deliveryFk"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@ module.exports = Self => {
|
||||||
require('../methods/entry/importBuysPreview')(Self);
|
require('../methods/entry/importBuysPreview')(Self);
|
||||||
require('../methods/entry/lastItemBuys')(Self);
|
require('../methods/entry/lastItemBuys')(Self);
|
||||||
require('../methods/entry/entryOrderPdf')(Self);
|
require('../methods/entry/entryOrderPdf')(Self);
|
||||||
|
require('../methods/entry/addFromPackaging')(Self);
|
||||||
|
require('../methods/entry/addFromBuy')(Self);
|
||||||
|
|
||||||
Self.observe('before save', async function(ctx, options) {
|
Self.observe('before save', async function(ctx, options) {
|
||||||
if (ctx.isNewInstance) return;
|
if (ctx.isNewInstance) return;
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('getItemsPackaging', {
|
||||||
|
description: 'Returns the list of items from the supplier of type packing',
|
||||||
|
accessType: 'READ',
|
||||||
|
accepts: [{
|
||||||
|
arg: 'id',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
description: 'The supplier id',
|
||||||
|
http: {source: 'path'}
|
||||||
|
}, {
|
||||||
|
arg: 'entry',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
description: 'The entry id',
|
||||||
|
}],
|
||||||
|
returns: {
|
||||||
|
type: 'object',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/:id/getItemsPackaging`,
|
||||||
|
verb: 'GET'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Self.getItemsPackaging = async(id, entry) => {
|
||||||
|
return Self.rawSql(`
|
||||||
|
WITH entryTmp AS (
|
||||||
|
SELECT i.id, SUM(b.quantity) quantity
|
||||||
|
FROM vn.entry e
|
||||||
|
JOIN vn.buy b ON b.entryFk = e.id
|
||||||
|
JOIN vn.supplier s ON s.id = e.supplierFk
|
||||||
|
JOIN vn.item i ON i.id = b.itemFk
|
||||||
|
WHERE e.id = ? AND e.supplierFk = ?
|
||||||
|
GROUP BY i.id
|
||||||
|
) SELECT i.id, i.name, et.quantity, SUM(b.quantity) quantityTotal
|
||||||
|
FROM vn.buy b
|
||||||
|
JOIN vn.item i ON i.id = b.itemFk
|
||||||
|
JOIN vn.entry e ON e.id = b.entryFk
|
||||||
|
JOIN vn.supplier s ON s.id = e.supplierFk
|
||||||
|
JOIN vn.buyConfig bc ON bc.monthsAgo
|
||||||
|
JOIN vn.travel t ON t.id = e.travelFk
|
||||||
|
LEFT JOIN entryTmp et ON et.id = i.id
|
||||||
|
WHERE e.supplierFk = ?
|
||||||
|
AND i.family IN ('EMB', 'CONT')
|
||||||
|
AND b.created > (util.VN_CURDATE() - INTERVAL bc.monthsAgo MONTH)
|
||||||
|
GROUP BY b.itemFk
|
||||||
|
ORDER BY et.quantity DESC, quantityTotal DESC`, [entry, id, id]);
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,12 @@
|
||||||
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('Supplier getItemsPackaging()', () => {
|
||||||
|
it('should return a summary of the list of items from a specific supplier', async() => {
|
||||||
|
const [item] = await app.models.Supplier.getItemsPackaging(1, 1);
|
||||||
|
|
||||||
|
expect(item.id).toEqual(1);
|
||||||
|
expect(item.name).toEqual('Ranged weapon longbow 2m');
|
||||||
|
expect(item.quantity).toEqual(5000);
|
||||||
|
expect(item.quantityTotal).toEqual(5100);
|
||||||
|
});
|
||||||
|
});
|
|
@ -11,6 +11,7 @@ module.exports = Self => {
|
||||||
require('../methods/supplier/campaignMetricsPdf')(Self);
|
require('../methods/supplier/campaignMetricsPdf')(Self);
|
||||||
require('../methods/supplier/campaignMetricsEmail')(Self);
|
require('../methods/supplier/campaignMetricsEmail')(Self);
|
||||||
require('../methods/supplier/newSupplier')(Self);
|
require('../methods/supplier/newSupplier')(Self);
|
||||||
|
require('../methods/supplier/getItemsPackaging')(Self);
|
||||||
|
|
||||||
Self.validatesPresenceOf('name', {
|
Self.validatesPresenceOf('name', {
|
||||||
message: 'The social name cannot be empty'
|
message: 'The social name cannot be empty'
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
"TravelThermograph": {
|
"TravelThermograph": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"TravelConfig": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"Temperature": {
|
"Temperature": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
{
|
||||||
|
"name": "TravelConfig",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "travelConfig"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "number",
|
||||||
|
"id": true
|
||||||
|
},
|
||||||
|
"warehouseInFk": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"warehouseOutFk": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"agencyFk": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"companyFk": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"warehouseIn": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Warehouse",
|
||||||
|
"foreignKey": "warehouseInFk"
|
||||||
|
},
|
||||||
|
"warehouseOut": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Warehouse",
|
||||||
|
"foreignKey": "warehouseOutFk"
|
||||||
|
},
|
||||||
|
"agency": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "AgencyMode",
|
||||||
|
"foreignKey": "agencyFk"
|
||||||
|
},
|
||||||
|
"company": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Company",
|
||||||
|
"foreignKey": "companyFk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue