Merge pull request '7525-devToTest' (!2542) from 7525-devToTest into test
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
Reviewed-on: #2542 Reviewed-by: Carlos Satorres <carlossa@verdnatura.es>
This commit is contained in:
commit
f354fe1b1f
|
@ -24,6 +24,7 @@ node {
|
|||
FROM_GIT = env.JOB_NAME.startsWith('gitea/')
|
||||
RUN_TESTS = !PROTECTED_BRANCH && FROM_GIT
|
||||
RUN_BUILD = PROTECTED_BRANCH && FROM_GIT
|
||||
|
||||
// https://www.jenkins.io/doc/book/pipeline/jenkinsfile/#using-environment-variables
|
||||
echo "NODE_NAME: ${env.NODE_NAME}"
|
||||
echo "WORKSPACE: ${env.WORKSPACE}"
|
||||
|
@ -206,9 +207,6 @@ pipeline {
|
|||
when {
|
||||
expression { FROM_GIT }
|
||||
}
|
||||
environment {
|
||||
DOCKER_HOST = "${env.SWARM_HOST}"
|
||||
}
|
||||
steps {
|
||||
script {
|
||||
def packageJson = readJSON file: 'package.json'
|
||||
|
|
|
@ -11,11 +11,16 @@ Required applications.
|
|||
* Node.js
|
||||
* Docker
|
||||
* Git
|
||||
* MYT
|
||||
|
||||
You will need to install globally the following items.
|
||||
```
|
||||
$ sudo npm install -g jest gulp-cli
|
||||
```
|
||||
After installing MYT you will need the following item.
|
||||
```
|
||||
$ apt install libkrb5-dev libssl-dev
|
||||
```
|
||||
|
||||
## Installing dependencies and launching
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
const isProduction = require('vn-loopback/server/boot/isProduction');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('sendCheckingPresence', {
|
||||
description: 'Creates a message in the chat model checking the user status',
|
||||
|
@ -37,7 +39,7 @@ module.exports = Self => {
|
|||
if (!recipient)
|
||||
throw new Error(`Could not send message "${message}" to worker id ${recipientId} from user ${userId}`);
|
||||
|
||||
if (process.env.NODE_ENV == 'test')
|
||||
if (!isProduction())
|
||||
message = `[Test:Environment to user ${userId}] ` + message;
|
||||
|
||||
const chat = await models.Chat.create({
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
const axios = require('axios');
|
||||
const isProduction = require('vn-loopback/server/boot/isProduction');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('sendQueued', {
|
||||
description: 'Send a RocketChat message',
|
||||
|
@ -94,7 +96,7 @@ module.exports = Self => {
|
|||
* @return {Promise} - The request promise
|
||||
*/
|
||||
Self.sendMessage = async function sendMessage(senderFk, recipient, message) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (!isProduction(false)) {
|
||||
return new Promise(resolve => {
|
||||
return resolve({
|
||||
statusCode: 200,
|
||||
|
@ -149,7 +151,7 @@ module.exports = Self => {
|
|||
* @return {Promise} - The request promise
|
||||
*/
|
||||
Self.getUserStatus = async function getUserStatus(username) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
if (!isProduction(false)) {
|
||||
return new Promise(resolve => {
|
||||
return resolve({
|
||||
data: {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const isProduction = require('vn-loopback/server/boot/isProduction');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('deleteTrashFiles', {
|
||||
|
@ -22,7 +23,7 @@ module.exports = Self => {
|
|||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
if (process.env.NODE_ENV == 'test')
|
||||
if (!isProduction())
|
||||
throw new UserError(`Action not allowed on the test environment`);
|
||||
|
||||
const models = Self.app.models;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
const axios = require('axios');
|
||||
const isProduction = require('vn-loopback/server/boot/isProduction');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('upload', {
|
||||
|
@ -119,7 +120,7 @@ module.exports = Self => {
|
|||
]
|
||||
};
|
||||
|
||||
if (process.env.NODE_ENV != 'production')
|
||||
if (!isProduction(false))
|
||||
throw new UserError('Action not allowed on the test environment');
|
||||
|
||||
// delete old
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const UserError = require('vn-loopback/util/user-error');
|
||||
const isProduction = require('vn-loopback/server/boot/isProduction');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('scrub', {
|
||||
|
@ -43,8 +44,7 @@ module.exports = Self => {
|
|||
Self.scrub = async function(collection, remove, limit, dryRun, skipLock) {
|
||||
const $ = Self.app.models;
|
||||
|
||||
const env = process.env.NODE_ENV;
|
||||
dryRun = dryRun || (env && env !== 'production');
|
||||
dryRun = dryRun || !isProduction(false);
|
||||
|
||||
const instance = await $.ImageCollection.findOne({
|
||||
fields: ['id'],
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
const fs = require('fs/promises');
|
||||
const path = require('path');
|
||||
const isProduction = require('vn-loopback/server/boot/isProduction');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('upload', {
|
||||
|
@ -41,7 +42,7 @@ module.exports = Self => {
|
|||
if (!hasWriteRole)
|
||||
throw new UserError(`You don't have enough privileges`);
|
||||
|
||||
if (process.env.NODE_ENV == 'test')
|
||||
if (!isProduction())
|
||||
throw new UserError(`Action not allowed on the test environment`);
|
||||
|
||||
// Upload file to temporary path
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
const {Email} = require('vn-print');
|
||||
const isProduction = require('vn-loopback/server/boot/isProduction');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('send', {
|
||||
|
@ -70,7 +71,7 @@ module.exports = Self => {
|
|||
const newParams = Object.assign({}, queueParams, sendParams);
|
||||
const email = new Email(queueName, newParams);
|
||||
|
||||
if (process.env.NODE_ENV != 'test')
|
||||
if (isProduction())
|
||||
await email.send();
|
||||
|
||||
await queue.updateAttribute('status', statusSent);
|
||||
|
|
|
@ -18,15 +18,10 @@ module.exports = Self => {
|
|||
Self.renewToken = async function(ctx) {
|
||||
const {accessToken: token} = ctx.req;
|
||||
|
||||
// Check if current token is valid
|
||||
|
||||
const {renewPeriod, courtesyTime} = await models.AccessTokenConfig.findOne({
|
||||
fields: ['renewPeriod', 'courtesyTime']
|
||||
const {courtesyTime} = await models.AccessTokenConfig.findOne({
|
||||
fields: ['courtesyTime']
|
||||
});
|
||||
const now = Date.now();
|
||||
const differenceMilliseconds = now - token.created;
|
||||
const differenceSeconds = Math.floor(differenceMilliseconds / 1000);
|
||||
const isNotExceeded = differenceSeconds < renewPeriod - courtesyTime;
|
||||
const isNotExceeded = await Self.validateToken(ctx);
|
||||
if (isNotExceeded)
|
||||
return token;
|
||||
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
const {models} = require('vn-loopback/server/server');
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('validateToken', {
|
||||
description: 'Validates the current logged user token',
|
||||
accepts: [],
|
||||
accessType: 'READ',
|
||||
returns: {
|
||||
type: 'Boolean',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/validateToken`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.validateToken = async function(ctx) {
|
||||
const {accessToken: token} = ctx.req;
|
||||
|
||||
// Check if current token is valid
|
||||
const {renewPeriod, courtesyTime} = await models.AccessTokenConfig.findOne({
|
||||
fields: ['renewPeriod', 'courtesyTime']
|
||||
});
|
||||
const now = Date.now();
|
||||
const differenceMilliseconds = now - token.created;
|
||||
const differenceSeconds = Math.floor(differenceMilliseconds / 1000);
|
||||
const isNotExceeded = differenceSeconds < renewPeriod - courtesyTime;
|
||||
return isNotExceeded;
|
||||
};
|
||||
};
|
|
@ -186,5 +186,8 @@
|
|||
},
|
||||
"AgencyWorkCenter": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"RouteConfig": {
|
||||
"dataSource": "vn"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
{
|
||||
"name": "Collection",
|
||||
"base": "VnModel",
|
||||
"properties": {
|
||||
"id": {
|
||||
"id": true,
|
||||
"type": "number",
|
||||
"required": true
|
||||
},
|
||||
"workerFk": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "collection"
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "RouteConfig",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "routeConfig"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "number",
|
||||
"description": "Identifier"
|
||||
},
|
||||
"kmMax": {
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ module.exports = function(Self) {
|
|||
require('../methods/vn-user/renew-token')(Self);
|
||||
require('../methods/vn-user/share-token')(Self);
|
||||
require('../methods/vn-user/update-user')(Self);
|
||||
require('../methods/vn-user/validate-token')(Self);
|
||||
|
||||
Self.definition.settings.acls = Self.definition.settings.acls.filter(acl => acl.property !== 'create');
|
||||
|
||||
|
|
|
@ -113,6 +113,13 @@
|
|||
"principalId": "$everyone",
|
||||
"permission": "ALLOW"
|
||||
},
|
||||
{
|
||||
"property": "validateToken",
|
||||
"accessType": "EXECUTE",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$authenticated",
|
||||
"permission": "ALLOW"
|
||||
},
|
||||
{
|
||||
"property": "privileges",
|
||||
"accessType": "*",
|
||||
|
|
|
@ -762,7 +762,12 @@ INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeF
|
|||
(30, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL, NULL),
|
||||
(31, 1, 8, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL + 2 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL, NULL),
|
||||
(32, 1, 8, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL + 2 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE(), NULL, NULL),
|
||||
(33, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1102, 'NY roofs', 122, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL, NULL);
|
||||
(33, 1, 7, 1, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1102, 'NY roofs', 122, NULL, 0, 3, 5, 1, util.VN_CURDATE(), NULL, NULL),
|
||||
(34, 1, 1, 1, 3, util.VN_CURDATE(), util.VN_CURDATE(), 1103, 'BEJAR', 123, NULL, 0, 1, 16, 0, util.VN_CURDATE(), NULL, NULL),
|
||||
(35, 1, 1, 1, 3, util.VN_CURDATE(), util.VN_CURDATE(), 1102, 'Somewhere in Philippines', 123, NULL, 0, 1, 16, 0, util.VN_CURDATE(), NULL, NULL),
|
||||
(36, 1, 1, 1, 3, util.VN_CURDATE(), util.VN_CURDATE(), 1102, 'Ant-Man Adventure', 123, NULL, 0, 1, 16, 0, util.VN_CURDATE(), NULL, NULL),
|
||||
(37, 1, 1, 1, 3, util.VN_CURDATE(), util.VN_CURDATE(), 1110, 'Deadpool swords', 123, NULL, 0, 1, 16, 0, util.VN_CURDATE(), NULL, NULL);
|
||||
|
||||
INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `description`)
|
||||
VALUES
|
||||
(1, 11, 1, 'ready'),
|
||||
|
@ -808,7 +813,10 @@ INSERT INTO `vn`.`ticketTracking`(`ticketFk`, `stateFk`, `userFk`, `created`)
|
|||
(21, 1, 19, DATE_ADD(util.VN_NOW(), INTERVAL +1 MONTH)),
|
||||
(22, 1, 19, DATE_ADD(util.VN_NOW(), INTERVAL +1 MONTH)),
|
||||
(23, 16, 21, util.VN_NOW()),
|
||||
(24, 16, 21, util.VN_NOW());
|
||||
(24, 16, 21, util.VN_NOW()),
|
||||
(34, 14, 49, util.VN_NOW()),
|
||||
(35, 14, 18, util.VN_NOW()),
|
||||
(36, 14, 18, util.VN_NOW());
|
||||
|
||||
INSERT INTO `vn`.`deliveryPoint` (`id`, `name`, `ubication`)
|
||||
VALUES
|
||||
|
@ -1068,7 +1076,10 @@ INSERT INTO `vn`.`sale`(`id`, `itemFk`, `ticketFk`, `concept`, `quantity`, `pric
|
|||
(37, 4, 31, 'Melee weapon heavy shield 100cm', 20, 1.72, 0, 0, 0, util.VN_CURDATE()),
|
||||
(36, 4, 30, 'Melee weapon heavy shield 100cm', 20, 1.72, 0, 0, 0, util.VN_CURDATE()),
|
||||
(38, 2, 32, 'Melee weapon combat fist 15cm', 30, 7.07, 0, 0, 0, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH)),
|
||||
(39, 1, 32, 'Ranged weapon longbow 200cm', 2, 103.49, 0, 0, 0, util.VN_CURDATE());
|
||||
(39, 1, 32, 'Ranged weapon longbow 200cm', 2, 103.49, 0, 0, 0, util.VN_CURDATE()),
|
||||
(40, 2, 34, 'Melee weapon combat fist 15cm', 10.00, 3.91, 0, 0, 0, util.VN_CURDATE()),
|
||||
(41, 2, 35, 'Melee weapon combat fist 15cm', 8.00, 3.01, 0, 0, 0, util.VN_CURDATE()),
|
||||
(42, 2, 36, 'Melee weapon combat fist 15cm', 6.00, 2.50, 0, 0, 0, util.VN_CURDATE());
|
||||
|
||||
INSERT INTO `vn`.`saleComponent`(`saleFk`, `componentFk`, `value`)
|
||||
VALUES
|
||||
|
@ -1205,11 +1216,11 @@ INSERT INTO `vn`.`saleComponent`(`saleFk`, `componentFk`, `value`)
|
|||
(32, 36, -92.324),
|
||||
(32, 39, 0.994);
|
||||
|
||||
INSERT INTO `vn`.`itemShelving` (`itemFk`, `shelvingFk`, `visible`, `grouping`, `packing`, `userFk`)
|
||||
INSERT INTO `vn`.`itemShelving` (`itemFk`, `shelvingFk`, `visible`, `grouping`, `packing`,`buyFk`, `userFk`)
|
||||
VALUES
|
||||
(2, 'GVC', 1, 1, 1, 1106),
|
||||
(4, 'HEJ', 1, 1, 1, 1106),
|
||||
(1, 'UXN', 2, 12, 12, 1106);
|
||||
(2, 'GVC', 1, 1, 1, 2,1106),
|
||||
(4, 'HEJ', 1, 1, 1, NULL,1106),
|
||||
(1, 'UXN', 2, 12, 12, NULL,1106);
|
||||
|
||||
INSERT INTO `vn`.`itemShelvingSale` (`itemShelvingFk`, `saleFk`, `quantity`, `created`, `userFk`)
|
||||
VALUES
|
||||
|
@ -1247,14 +1258,20 @@ INSERT INTO `vn`.`operator` (`workerFk`, `numberOfWagons`, `trainFk`, `itemPacki
|
|||
INSERT INTO `vn`.`collection`(`id`, `workerFk`, `stateFk`, `created`, `trainFk`)
|
||||
VALUES
|
||||
(1, 1106, 5, DATE_ADD(util.VN_CURDATE(),INTERVAL +1 DAY), 1),
|
||||
(2, 1106, 14, util.VN_CURDATE(), 1);
|
||||
(2, 1106, 14, util.VN_CURDATE(), 1),
|
||||
(4, 49, 5, util.VN_CURDATE(), 1),
|
||||
(5, 18, 5, util.VN_CURDATE(), 1),
|
||||
(6, 18, 5, util.VN_CURDATE(), 1);
|
||||
|
||||
INSERT INTO `vn`.`ticketCollection`(`ticketFk`, `collectionFk`, `level`)
|
||||
VALUES
|
||||
(1, 1, 1),
|
||||
(2, 1, NULL),
|
||||
(3, 2, NULL),
|
||||
(23, 1, NULL);
|
||||
(23, 1, NULL),
|
||||
(34, 4, 1),
|
||||
(35, 5, 1),
|
||||
(8, 6, 1);
|
||||
|
||||
INSERT INTO `vn`.`genus`(`id`, `name`)
|
||||
VALUES
|
||||
|
@ -3705,7 +3722,8 @@ INSERT IGNORE INTO vn.saleGroup
|
|||
SET id = 4,
|
||||
userFk = 1,
|
||||
parkingFk = 9,
|
||||
sectorFk = 9992;
|
||||
sectorFk = 9992,
|
||||
ticketFk = 36;
|
||||
|
||||
INSERT IGNORE INTO vn.sectorCollectionSaleGroup
|
||||
SET id = 9999,
|
||||
|
@ -3807,3 +3825,27 @@ INSERT INTO `vn`.`ledgerCompany` SET
|
|||
|
||||
INSERT INTO `vn`.`ledgerConfig` SET
|
||||
maxTolerance = 0.01;
|
||||
|
||||
INSERT INTO vn.sectorCollection
|
||||
SET id = 2,
|
||||
userFk = 18,
|
||||
sectorFk = 1;
|
||||
|
||||
INSERT INTO vn.sectorCollectionSaleGroup
|
||||
SET id = 8,
|
||||
sectorCollectionFk = 2,
|
||||
saleGroupFk = 4;
|
||||
|
||||
INSERT INTO vn.saleGroup (userFk, parkingFk, sectorFk, ticketFk)
|
||||
VALUES
|
||||
(1, 1, 1, 37);
|
||||
|
||||
INSERT INTO vn.sectorCollection
|
||||
SET id = 3,
|
||||
userFk = 18,
|
||||
sectorFk = 1;
|
||||
|
||||
INSERT INTO vn.sectorCollectionSaleGroup
|
||||
SET id = 9,
|
||||
sectorCollectionFk = 3,
|
||||
saleGroupFk = 6;
|
|
@ -23,22 +23,19 @@ BEGIN
|
|||
DECLARE vXtraLongAgj INT;
|
||||
DECLARE vDefaultKlo INT;
|
||||
|
||||
SELECT
|
||||
ec.usefulAuctionLeftSegmentLength,
|
||||
ec.standardBarcodeLength,
|
||||
ec.floridayBarcodeLength,
|
||||
ec.floramondoBarcodeLength,
|
||||
ec.defaultKlo
|
||||
INTO
|
||||
vUsefulAuctionLeftSegmentLength,
|
||||
SELECT usefulAuctionLeftSegmentLength,
|
||||
standardBarcodeLength,
|
||||
floridayBarcodeLength,
|
||||
floramondoBarcodeLength,
|
||||
defaultKlo
|
||||
INTO vUsefulAuctionLeftSegmentLength,
|
||||
vStandardBarcodeLength,
|
||||
vFloridayBarcodeLength,
|
||||
vFloramondoBarcodeLength,
|
||||
vDefaultKlo
|
||||
FROM edi.ektConfig ec;
|
||||
FROM ektConfig;
|
||||
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.ekt;
|
||||
CREATE TEMPORARY TABLE tmp.ekt
|
||||
CREATE OR REPLACE TEMPORARY TABLE tmp.ekt
|
||||
ENGINE = MEMORY
|
||||
SELECT id ektFk FROM ekt LIMIT 0;
|
||||
|
||||
|
@ -46,14 +43,14 @@ BEGIN
|
|||
WHEN LENGTH(vBarcode) <= vFloridayBarcodeLength THEN
|
||||
INSERT INTO tmp.ekt
|
||||
SELECT id
|
||||
FROM edi.ektRecent e
|
||||
FROM ektRecent e
|
||||
WHERE e.cps = vBarcode
|
||||
OR e.batchNumber = vBarcode;
|
||||
|
||||
WHEN LENGTH(vBarcode) = vFloramondoBarcodeLength THEN
|
||||
INSERT INTO tmp.ekt
|
||||
SELECT e.id
|
||||
FROM edi.ektRecent e
|
||||
FROM ektRecent e
|
||||
WHERE e.pro = MID(vBarcode,2,6)
|
||||
AND CAST(e.ptd AS SIGNED) = MID(vBarcode, 8, 5);
|
||||
|
||||
|
@ -74,13 +71,15 @@ BEGIN
|
|||
SELECT id
|
||||
FROM ekt
|
||||
WHERE fec >= vFec - INTERVAL 1 DAY
|
||||
AND ((
|
||||
vKlo = vDefaultKlo
|
||||
AND (
|
||||
(vKlo = vDefaultKlo
|
||||
AND (klo = vKlo OR klo IS NULL OR klo = 0)
|
||||
AND agj IN (vShortAgj, vLongAgj, vXtraLongAgj))
|
||||
OR (klo = vKlo
|
||||
AND agj IN (vShortAgj, vLongAgj, vXtraLongAgj)
|
||||
) OR (
|
||||
klo = vKlo
|
||||
AND auction = vAuction
|
||||
AND agj = vShortAgj)
|
||||
AND agj = vShortAgj
|
||||
)
|
||||
)
|
||||
ORDER BY agj DESC, fec DESC
|
||||
LIMIT 1;
|
||||
|
@ -91,9 +90,11 @@ BEGIN
|
|||
IF NOT vIsFound THEN
|
||||
INSERT INTO tmp.ekt
|
||||
SELECT id
|
||||
FROM edi.ektRecent e
|
||||
WHERE e.batchNumber
|
||||
= LEFT(vBarcode,vUsefulAuctionLeftSegmentLength)
|
||||
FROM ektRecent e
|
||||
WHERE e.batchNumber = LEFT(
|
||||
vBarcode,
|
||||
vUsefulAuctionLeftSegmentLength
|
||||
)
|
||||
AND e.batchNumber > 0;
|
||||
|
||||
SELECT COUNT(*) FROM tmp.ekt INTO vIsFound;
|
||||
|
@ -103,7 +104,7 @@ BEGIN
|
|||
IF NOT vIsFound THEN
|
||||
INSERT INTO tmp.ekt
|
||||
SELECT id
|
||||
FROM edi.ektRecent e
|
||||
FROM ektRecent e
|
||||
WHERE e.putOrderFk = vBarcode;
|
||||
|
||||
SELECT COUNT(*) FROM tmp.ekt INTO vIsFound;
|
||||
|
@ -113,13 +114,23 @@ BEGIN
|
|||
IF NOT vIsFound THEN
|
||||
INSERT INTO tmp.ekt
|
||||
SELECT id
|
||||
FROM edi.ektRecent e
|
||||
WHERE e.deliveryNumber
|
||||
= MID(vBarcode, 4, 13)
|
||||
FROM ektRecent e
|
||||
WHERE e.deliveryNumber = MID(vBarcode, 4, 13)
|
||||
AND e.deliveryNumber > 0;
|
||||
|
||||
SELECT COUNT(*) FROM tmp.ekt INTO vIsFound;
|
||||
END IF;
|
||||
|
||||
-- Solo campo agj
|
||||
IF NOT vIsFound THEN
|
||||
INSERT INTO tmp.ekt
|
||||
SELECT id
|
||||
FROM ektRecent
|
||||
WHERE agj = vShortAgj;
|
||||
|
||||
SELECT COUNT(*) FROM tmp.ekt INTO vIsFound;
|
||||
END IF;
|
||||
|
||||
END CASE;
|
||||
|
||||
IF vIsFound THEN
|
||||
|
|
|
@ -40,19 +40,28 @@ proc:BEGIN
|
|||
postalCode,
|
||||
`type`,
|
||||
image,
|
||||
description
|
||||
description,
|
||||
addressFk
|
||||
)
|
||||
SELECT i.name,
|
||||
i.`size`,
|
||||
i.id,
|
||||
SELECT CONCAT(i.name, ' by ',a.nickname),
|
||||
r.price + apc.deliveryCost,
|
||||
r.itemFk,
|
||||
vLanded,
|
||||
vPostalCode,
|
||||
it.name,
|
||||
CONCAT('https://cdn.verdnatura.es/image/catalog/1600x900/', i.image),
|
||||
i.description
|
||||
i.description,
|
||||
apc.addressFk
|
||||
FROM vn.item i
|
||||
JOIN (SELECT itemFk, SUM(quantity * cost) price
|
||||
FROM recipe
|
||||
GROUP BY itemFk) r ON r.itemFk = i.id
|
||||
JOIN vn.itemType it ON it.id = i.typeFk
|
||||
WHERE it.code IN ('FNR','FNP');
|
||||
JOIN addressPostCode apc
|
||||
ON apc.dayOfWeek = dayOfWeek(vLanded)
|
||||
AND NOW() < vLanded - INTERVAL apc.hoursInAdvance HOUR
|
||||
AND apc.postCode = vPostalCode
|
||||
JOIN vn.address a ON a.id = apc.addressFk;
|
||||
|
||||
SELECT *
|
||||
FROM catalogue
|
||||
|
|
|
@ -13,8 +13,17 @@ BEGIN
|
|||
/**
|
||||
* Set actions for contact request
|
||||
*
|
||||
* @param vPostalCode Delivery address postal code
|
||||
* @param vName Name
|
||||
* @param vPhone Phone number
|
||||
* @param vEmail e-mail
|
||||
* @param vMessage text of the message
|
||||
*/
|
||||
|
||||
CALL vn.mail_insert(
|
||||
'floranet@verdnatura.es',
|
||||
vEmail,
|
||||
'Contact request',
|
||||
CONCAT('Phone: ',vPhone, ' Message: ', vMessage)
|
||||
);
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -21,7 +21,7 @@ BEGIN
|
|||
apc.dayOfWeek - vCurrentDayOfWeek,
|
||||
7 - apc.dayOfWeek
|
||||
) DAY nextDay,
|
||||
NOW() + INTERVAL apc.hoursInAdvance - 12 HOUR minDeliveryTime
|
||||
NOW() + INTERVAL apc.hoursInAdvance HOUR minDeliveryTime
|
||||
FROM addressPostCode apc
|
||||
WHERE apc.postCode = vPostalCode
|
||||
HAVING nextDay > minDeliveryTime) sub;
|
||||
|
|
|
@ -1,25 +1,167 @@
|
|||
DROP PROCEDURE IF EXISTS floranet.order_confirm;
|
||||
|
||||
DELIMITER $$
|
||||
$$
|
||||
|
||||
CREATE DEFINER=`root`@`localhost`PROCEDURE floranet.order_confirm(vCatalogueFk INT)
|
||||
CREATE OR REPLACE DEFINER=`root`@`localhost`PROCEDURE floranet.order_confirm(vCatalogueFk INT)
|
||||
READS SQL DATA
|
||||
|
||||
BEGIN
|
||||
/** Update order.isPaid field.
|
||||
proc:BEGIN
|
||||
/** Update order.isPaid field, and makes the ticket
|
||||
*
|
||||
* @param vCatalogueFk floranet.catalogue.id
|
||||
*
|
||||
* @returns floranet.order.isPaid
|
||||
*/
|
||||
DECLARE vNewTicketFk INT;
|
||||
DECLARE vCustomerEmail VARCHAR(255);
|
||||
DECLARE vFloranetEmail VARCHAR(255);
|
||||
DECLARE vSubjectEmail VARCHAR(100);
|
||||
DECLARE vBodyEmail TEXT;
|
||||
DECLARE vZoneFk INT;
|
||||
|
||||
DECLARE exit handler FOR SQLEXCEPTION
|
||||
BEGIN
|
||||
ROLLBACK;
|
||||
|
||||
GET DIAGNOSTICS CONDITION 2 @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT;
|
||||
|
||||
SELECT CONCAT('ERROR ', IFNULL(@errno,0), ': ', ifnull(@text,'texto')) AS `SQLEXCEPTION`;
|
||||
|
||||
CALL vn.mail_insert(
|
||||
'floranet@verdnatura.es,pako@verdnatura.es',
|
||||
'noreply@verdnatura.es',
|
||||
'Floranet.order_confirm failure',
|
||||
CONCAT('CatalogueFk: ', vCatalogueFk, '\n','ERROR ', IFNULL(@errno, 0), ': ', ifnull(@text, 'texto'))
|
||||
);
|
||||
END;
|
||||
|
||||
IF (SELECT isPaid FROM `order` WHERE catalogueFk = vCatalogueFk) THEN
|
||||
SELECT CONCAT('CatalogueFk: ', vCatalogueFk, ' Esta orden ya está confirmada') AS `ERROR`;
|
||||
LEAVE proc;
|
||||
END IF;
|
||||
|
||||
START TRANSACTION;
|
||||
|
||||
UPDATE `order`
|
||||
SET isPaid = TRUE,
|
||||
payed = NOW()
|
||||
WHERE catalogueFk = vCatalogueFk;
|
||||
|
||||
SELECT isPaid
|
||||
SELECT zoneFk
|
||||
INTO vZoneFk
|
||||
FROM (
|
||||
SELECT zoneFk, COUNT(*) totalCount
|
||||
FROM vn.ticket t
|
||||
JOIN catalogue c ON c.id = vCatalogueFk
|
||||
WHERE t.shipped > util.VN_CURDATE() - INTERVAL 1 YEAR
|
||||
AND t.addressFk = c.addressFk
|
||||
GROUP BY zoneFk
|
||||
ORDER BY totalCount DESC
|
||||
LIMIT 10000000000000000000
|
||||
) sub
|
||||
LIMIT 1;
|
||||
|
||||
INSERT INTO vn.ticket (
|
||||
clientFk,
|
||||
shipped,
|
||||
addressFk,
|
||||
agencyModeFk,
|
||||
nickname,
|
||||
warehouseFk,
|
||||
routeFk,
|
||||
companyFk,
|
||||
landed,
|
||||
zoneFk
|
||||
)
|
||||
SELECT a.clientFk,
|
||||
c.dated - INTERVAL 1 DAY,
|
||||
c.addressFk,
|
||||
a.agencyModeFk,
|
||||
a.nickname,
|
||||
ag.warehouseFk,
|
||||
NULL,
|
||||
co.id,
|
||||
c.dated,
|
||||
vZoneFk
|
||||
FROM vn.address a
|
||||
JOIN vn.agencyMode am ON am.id = a.agencyModeFk
|
||||
JOIN vn.agency ag ON ag.id = am.agencyFk
|
||||
JOIN catalogue c ON c.addressFk = a.id
|
||||
JOIN vn.company co ON co.code = 'VNL'
|
||||
WHERE c.id = vCatalogueFk;
|
||||
|
||||
SET vNewTicketFk = LAST_INSERT_ID();
|
||||
|
||||
INSERT INTO vn.sale(
|
||||
ticketFk,
|
||||
itemFk,
|
||||
concept,
|
||||
price,
|
||||
quantity)
|
||||
SELECT
|
||||
vNewTicketFk,
|
||||
c.itemFk,
|
||||
CONCAT('Entrega: ',c.name),
|
||||
- c.price,
|
||||
1
|
||||
FROM catalogue c
|
||||
JOIN addressPostCode apc
|
||||
ON apc.addressFk = c.addressFk
|
||||
AND apc.dayOfWeek = dayOfWeek(c.dated)
|
||||
WHERE c.id = vCatalogueFk;
|
||||
|
||||
INSERT INTO vn.sale(
|
||||
ticketFk,
|
||||
itemFk,
|
||||
concept,
|
||||
price,
|
||||
quantity)
|
||||
SELECT
|
||||
vNewTicketFk,
|
||||
r.elementFk,
|
||||
i.longName,
|
||||
r.cost,
|
||||
r.quantity
|
||||
FROM catalogue c
|
||||
JOIN recipe r ON r.itemFk = c.itemFk
|
||||
JOIN vn.item i ON i.id = r.elementFk
|
||||
WHERE c.id = vCatalogueFk;
|
||||
|
||||
SELECT cl.email,
|
||||
cf.email,
|
||||
CONCAT('Nuevo pedido FLORANET para entrega el ',c.dated),
|
||||
CONCAT_WS('\n',
|
||||
CONCAT('Producto: ', c.name),
|
||||
CONCAT('Fecha de entrega: ',c.dated),
|
||||
CONCAT('Destinatario: ', o.deliveryName),
|
||||
CONCAT('Dirección: ', o.address),
|
||||
CONCAT('CP: ', c.postalCode),
|
||||
CONCAT('Foto: ', c.image),
|
||||
CONCAT('Mensaje: ', IFNULL(o.message,"Ninguno.")),
|
||||
CONCAT('Teléfono: ',IFNULL(o.deliveryPhone,"--")),
|
||||
CONCAT('Observaciones: ', IFNULL(o.observations,"No hay."))
|
||||
)
|
||||
INTO vCustomerEmail,
|
||||
vFloranetEmail,
|
||||
vSubjectEmail,
|
||||
vBodyEmail
|
||||
FROM vn.client cl
|
||||
JOIN vn.address a ON a.clientFk = cl.id
|
||||
JOIN catalogue c ON c.addressFk = a.id
|
||||
JOIN `order` o ON o.catalogueFk = c.id
|
||||
JOIN config cf
|
||||
WHERE c.id = vCatalogueFk;
|
||||
|
||||
CALL vn.mail_insert(
|
||||
vCustomerEmail,
|
||||
vFloranetEmail,
|
||||
vSubjectEmail,
|
||||
vBodyEmail);
|
||||
|
||||
SELECT isPaid, vNewTicketFk
|
||||
FROM `order`
|
||||
WHERE catalogueFk = vCatalogueFk;
|
||||
|
||||
COMMIT;
|
||||
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -7,7 +7,7 @@ BEGIN
|
|||
*
|
||||
* @param vJsonData The order data in json format
|
||||
*/
|
||||
INSERT INTO `order`
|
||||
REPLACE `order`
|
||||
SET catalogueFk = JSON_UNQUOTE(JSON_EXTRACT(vJsonData, '$.customer.customerData.products[0].id')),
|
||||
customerName = JSON_UNQUOTE(JSON_EXTRACT(vJsonData, '$.customer.customerData.customerName')),
|
||||
email = JSON_UNQUOTE(JSON_EXTRACT(vJsonData, '$.customer.customerData.email')),
|
||||
|
@ -15,7 +15,8 @@ BEGIN
|
|||
message= JSON_UNQUOTE(JSON_EXTRACT(vJsonData, '$.customer.customerData.message')),
|
||||
deliveryName = JSON_UNQUOTE(JSON_EXTRACT(vJsonData, '$.customer.customerData.deliveryName')),
|
||||
address = JSON_UNQUOTE(JSON_EXTRACT(vJsonData, '$.customer.customerData.address')),
|
||||
deliveryPhone = JSON_UNQUOTE(JSON_EXTRACT(vJsonData, '$.customer.customerData.deliveryPhone'));
|
||||
deliveryPhone = JSON_UNQUOTE(JSON_EXTRACT(vJsonData, '$.customer.customerData.deliveryPhone')),
|
||||
observations = JSON_UNQUOTE(JSON_EXTRACT(vJsonData, '$.customer.customerData.observations'));
|
||||
|
||||
SELECT LAST_INSERT_ID() orderFk;
|
||||
END$$
|
||||
|
|
|
@ -15,6 +15,5 @@ BEGIN
|
|||
JOIN vn.itemType it ON it.id = i.typeFk
|
||||
WHERE it.code IN ('FNR','FNP')
|
||||
LIMIT 3;
|
||||
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -17,13 +17,15 @@ BEGIN
|
|||
SELECT
|
||||
itemFk,
|
||||
packing,
|
||||
created
|
||||
created,
|
||||
buyFk
|
||||
FROM itemShelving
|
||||
WHERE id = vItemShelvingFk
|
||||
) ish2
|
||||
ON ish2.itemFk = ish.itemFk
|
||||
AND ish2.packing = ish.packing
|
||||
AND date(ish2.created) = date(ish.created)
|
||||
AND ish2.buyFk = ish.buyFk
|
||||
WHERE ish.shelvingFk = vShelvingFk COLLATE utf8_unicode_ci;
|
||||
|
||||
IF vNewItemShelvingFk THEN
|
||||
|
|
|
@ -2,7 +2,6 @@ DELIMITER $$
|
|||
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`itemShelving_add`(IN vShelvingFk VARCHAR(8), IN vBarcode VARCHAR(22), IN vQuantity INT, IN vPackagingFk VARCHAR(10), IN vGrouping INT, IN vPacking INT, IN vWarehouseFk INT)
|
||||
BEGIN
|
||||
|
||||
|
||||
/**
|
||||
* Añade registro o lo actualiza si ya existe.
|
||||
*
|
||||
|
@ -15,11 +14,23 @@ BEGIN
|
|||
* @param vWarehouseFk indica el sector
|
||||
*
|
||||
**/
|
||||
|
||||
DECLARE vItemFk INT;
|
||||
DECLARE vBuyFk INT;
|
||||
|
||||
SELECT id INTO vBuyFk
|
||||
FROM buy WHERE id = vBarcode;
|
||||
|
||||
SELECT barcodeToItem(vBarcode) INTO vItemFk;
|
||||
|
||||
IF vBuyFk IS NULL THEN
|
||||
CALL cache.last_buy_refresh(FALSE);
|
||||
|
||||
SELECT buy_id INTO vBuyFk
|
||||
FROM cache.last_buy
|
||||
WHERE item_id = vItemFk
|
||||
AND warehouse_id = vWarehouseFk;
|
||||
END IF;
|
||||
|
||||
IF vPacking IS NULL
|
||||
THEN
|
||||
SET vPacking = itemPacking(vBarcode, vWarehouseFk);
|
||||
|
@ -29,31 +40,32 @@ BEGIN
|
|||
IF (SELECT COUNT(*) FROM itemShelving
|
||||
WHERE shelvingFk COLLATE utf8_unicode_ci = vShelvingFk
|
||||
AND itemFk = vItemFk
|
||||
AND packing = vPacking) = 1 THEN
|
||||
AND packing = vPacking
|
||||
AND buyFk = vBuyFk) THEN
|
||||
|
||||
UPDATE itemShelving
|
||||
SET visible = visible + vQuantity
|
||||
WHERE shelvingFk COLLATE utf8_unicode_ci = vShelvingFk AND itemFk = vItemFk AND packing = vPacking;
|
||||
|
||||
ELSE
|
||||
CALL cache.last_buy_refresh(FALSE);
|
||||
INSERT INTO itemShelving( itemFk,
|
||||
|
||||
INSERT INTO itemShelving(
|
||||
itemFk,
|
||||
shelvingFk,
|
||||
visible,
|
||||
grouping,
|
||||
packing,
|
||||
packagingFk)
|
||||
|
||||
packagingFk,
|
||||
buyFk)
|
||||
SELECT vItemFk,
|
||||
vShelvingFk,
|
||||
vQuantity,
|
||||
IFNULL(vGrouping, b.grouping),
|
||||
IFNULL(vPacking, b.packing),
|
||||
IFNULL(vPackagingFk, b.packagingFk)
|
||||
FROM item i
|
||||
LEFT JOIN cache.last_buy lb ON i.id = lb.item_id AND lb.warehouse_id = vWarehouseFk
|
||||
LEFT JOIN buy b ON b.id = lb.buy_id
|
||||
WHERE i.id = vItemFk;
|
||||
IFNULL(vPackagingFk, b.packagingFk),
|
||||
id
|
||||
FROM buy b
|
||||
WHERE id = vBuyFk;
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
|
|
@ -23,7 +23,6 @@ proc: BEGIN
|
|||
* @param tmp.comparativeFilterType(filterFk INT ,itemTypeFk INT)
|
||||
* @return tmp.comparative
|
||||
*/
|
||||
|
||||
DECLARE vDayRangeStart DATE;
|
||||
DECLARE vDayRangeEnd DATE;
|
||||
DECLARE w1, w2, w3, w4, w5, w6, w7 INT;
|
||||
|
@ -59,14 +58,14 @@ proc: BEGIN
|
|||
END IF;
|
||||
|
||||
SELECT MIN(dated) INTO vDayRangeStart
|
||||
FROM vn.time
|
||||
FROM `time`
|
||||
WHERE dated <= vDate
|
||||
GROUP BY period
|
||||
ORDER BY dated desc
|
||||
LIMIT 1 OFFSET vWeekRange;
|
||||
|
||||
SELECT MAX(dated) INTO vDayRangeEnd
|
||||
FROM vn.time
|
||||
FROM `time`
|
||||
WHERE dated >= vDate
|
||||
GROUP BY period
|
||||
ORDER BY dated ASC
|
||||
|
@ -83,12 +82,11 @@ proc: BEGIN
|
|||
JOIN itemType t ON t.id = i.typeFk
|
||||
JOIN itemCategory c ON c.id = t.categoryFk
|
||||
LEFT JOIN worker w ON w.id = t.workerFk
|
||||
WHERE (NOT vHasTypeFilter
|
||||
OR t.id IN (SELECT itemTypeFk FROM tmp.comparativeFilterType))
|
||||
AND (vBuyerFk IS NULL
|
||||
OR t.workerFk = vBuyerFk)
|
||||
AND (vIsFloramondo IS NULL
|
||||
OR i.isFloramondo = vIsFloramondo);
|
||||
WHERE (NOT vHasTypeFilter OR t.id IN (
|
||||
SELECT itemTypeFk FROM tmp.comparativeFilterType
|
||||
))
|
||||
AND (vBuyerFk IS NULL OR t.workerFk = vBuyerFk)
|
||||
AND (vIsFloramondo IS NULL OR i.isFloramondo = vIsFloramondo);
|
||||
|
||||
IF vDate < util.VN_CURDATE() THEN
|
||||
ALTER TABLE tmp.itemInventory
|
||||
|
@ -115,10 +113,11 @@ proc: BEGIN
|
|||
SET i = i + 1;
|
||||
|
||||
SELECT t.period INTO vPeriod
|
||||
FROM vn.`time` t
|
||||
FROM `time` t
|
||||
WHERE t.dated = vDayRangeStart + INTERVAL (vWeekCount * (i - 1)) DAY;
|
||||
|
||||
INSERT IGNORE INTO tTable(cy, ly, zy) VALUES(vPeriod, vPeriod - 100, vPeriod - 200);
|
||||
INSERT IGNORE INTO tTable(cy, ly, zy)
|
||||
VALUES(vPeriod, vPeriod - 100, vPeriod - 200);
|
||||
UNTIL i = vWeekCount END REPEAT;
|
||||
|
||||
SELECT cy, ly, zy INTO w1, y1, z1 FROM tTable LIMIT 1;
|
||||
|
@ -130,7 +129,6 @@ proc: BEGIN
|
|||
SELECT cy, ly, zy INTO w7, y7, z7 FROM tTable WHERE cy > w6 LIMIT 1;
|
||||
|
||||
-- Genera una tabla con los datos del año pasado.
|
||||
|
||||
CREATE OR REPLACE TEMPORARY TABLE tLastYear
|
||||
(KEY (lItemFk))
|
||||
ENGINE = MEMORY
|
||||
|
@ -151,15 +149,14 @@ proc: BEGIN
|
|||
SUM(IF(c.timePeriod = y7, c.price, 0)) lprice7
|
||||
FROM tmp.itemInventory ai
|
||||
JOIN comparative c ON c.itemFk = ai.id
|
||||
JOIN warehouse w on w.id = c.warehouseFk
|
||||
JOIN warehouse w ON w.id = c.warehouseFk
|
||||
JOIN tTable wt ON c.timePeriod = wt.ly
|
||||
WHERE IFNULL(vWarehouseFk, c.warehouseFk) = c.warehouseFk
|
||||
WHERE (vWarehouseFk IS NULL OR vWarehouseFk = c.warehouseFk)
|
||||
AND w.isComparative
|
||||
AND (vCountryFk IS NULL OR c.countryFk = vCountryFk)
|
||||
GROUP BY ai.id;
|
||||
|
||||
-- Genera una tabla con los datos de hace DOS años.
|
||||
|
||||
-- Genera una tabla con los datos de hace 2 años
|
||||
CREATE OR REPLACE TEMPORARY TABLE tTwoYearsAgo
|
||||
(KEY (tItemFk))
|
||||
ENGINE = MEMORY
|
||||
|
@ -180,59 +177,58 @@ proc: BEGIN
|
|||
SUM(IF(c.timePeriod = z7, c.price, 0)) vlprice7
|
||||
FROM tmp.itemInventory ai
|
||||
JOIN comparative c ON c.itemFk = ai.id
|
||||
JOIN warehouse w on w.id = c.warehouseFk
|
||||
JOIN warehouse w ON w.id = c.warehouseFk
|
||||
JOIN tTable wt ON c.timePeriod = wt.zy
|
||||
WHERE IFNULL(vWarehouseFk, c.warehouseFk) = c.warehouseFk
|
||||
WHERE (vWarehouseFk IS NULL OR vWarehouseFk = c.warehouseFk)
|
||||
AND w.isComparative
|
||||
AND (vCountryFk IS NULL OR c.countryFk = vCountryFk)
|
||||
GROUP BY ai.id;
|
||||
|
||||
-- Genera una tabla con los datos de este año.ss
|
||||
|
||||
-- Genera una tabla con los datos de este año
|
||||
CREATE OR REPLACE TEMPORARY TABLE tCurrentYear
|
||||
(KEY (cItemFk))
|
||||
ENGINE = MEMORY
|
||||
SELECT t.itemFk cItemFk,
|
||||
SUM(IF(week = w1, total, 0)) cweek1,
|
||||
SUM(IF(week = w2, total, 0)) cweek2,
|
||||
SUM(IF(week = w3, total, 0)) cweek3,
|
||||
SUM(IF(week = w4, total, 0)) cweek4,
|
||||
SUM(IF(week = w5, total, 0)) cweek5,
|
||||
SUM(IF(week = w6, total, 0)) cweek6,
|
||||
SUM(IF(week = w7, total, 0)) cweek7,
|
||||
SUM(IF(week = w1, price, 0)) cprice1,
|
||||
SUM(IF(week = w2, price, 0)) cprice2,
|
||||
SUM(IF(week = w3, price, 0)) cprice3,
|
||||
SUM(IF(week = w4, price, 0)) cprice4,
|
||||
SUM(IF(week = w5, price, 0)) cprice5,
|
||||
SUM(IF(week = w6, price, 0)) cprice6,
|
||||
SUM(IF(week = w7, price, 0)) cprice7
|
||||
SUM(IF(`week` = w1, total, 0)) cweek1,
|
||||
SUM(IF(`week` = w2, total, 0)) cweek2,
|
||||
SUM(IF(`week` = w3, total, 0)) cweek3,
|
||||
SUM(IF(`week` = w4, total, 0)) cweek4,
|
||||
SUM(IF(`week` = w5, total, 0)) cweek5,
|
||||
SUM(IF(`week` = w6, total, 0)) cweek6,
|
||||
SUM(IF(`week` = w7, total, 0)) cweek7,
|
||||
SUM(IF(`week` = w1, price, 0)) cprice1,
|
||||
SUM(IF(`week` = w2, price, 0)) cprice2,
|
||||
SUM(IF(`week` = w3, price, 0)) cprice3,
|
||||
SUM(IF(`week` = w4, price, 0)) cprice4,
|
||||
SUM(IF(`week` = w5, price, 0)) cprice5,
|
||||
SUM(IF(`week` = w6, price, 0)) cprice6,
|
||||
SUM(IF(`week` = w7, price, 0)) cprice7
|
||||
FROM (
|
||||
SELECT s.itemFk,
|
||||
ti.period `week`,
|
||||
SUM(s.quantity) total,
|
||||
TRUNCATE(SUM(s.quantity * s.priceFixed), 0) price
|
||||
FROM ticket t
|
||||
FROM ticket t FORCE INDEX (Fecha)
|
||||
JOIN sale s ON t.id = s.ticketFk
|
||||
JOIN tmp.itemInventory it ON it.id = s.itemFk
|
||||
JOIN time ti ON ti.dated = DATE(t.shipped)
|
||||
JOIN `time` ti ON ti.dated = DATE(t.shipped)
|
||||
JOIN item i ON i.id = s.itemFk
|
||||
JOIN itemType tp ON tp.id = i.typeFk
|
||||
JOIN itemCategory ic ON ic.id = tp.categoryFk
|
||||
JOIN warehouse w ON w.id = t.warehouseFk
|
||||
STRAIGHT_JOIN address ad ON ad.id = t.addressFk
|
||||
JOIN `address` ad ON ad.id = t.addressFk
|
||||
JOIN province p ON p.id = ad.provinceFk
|
||||
JOIN `client` c ON c.id = ad.clientFk
|
||||
WHERE t.shipped BETWEEN vDayRangeStart AND util.dayEnd(vDayRangeEnd)
|
||||
AND c.typeFk IN ('Normal','handMaking')
|
||||
AND w.id = COALESCE(vWarehouseFk, w.id)
|
||||
AND w.isComparative
|
||||
AND c.typeFk IN ('normal', 'handMaking')
|
||||
AND (vWarehouseFk IS NULL OR vWarehouseFk = w.id)
|
||||
AND (vCountryFk IS NULL OR p.countryFk = vCountryFk)
|
||||
GROUP BY i.id, week
|
||||
AND w.isComparative
|
||||
GROUP BY i.id, `week`
|
||||
) t
|
||||
GROUP BY t.itemFk;
|
||||
|
||||
-- Genera la tabla con la comparativa.
|
||||
-- Genera la tabla con la comparativa
|
||||
CREATE OR REPLACE TEMPORARY TABLE tmp.comparative
|
||||
ENGINE = MEMORY
|
||||
SELECT it.subName productor,
|
||||
|
@ -240,13 +236,13 @@ proc: BEGIN
|
|||
b.buyingValue costefijo,
|
||||
b.groupingMode caja,
|
||||
it.image ArticleImage,
|
||||
IFNULL(it.inkFk,"?") color,
|
||||
IFNULL(it.inkFk, '?') color,
|
||||
tp.code tipo,
|
||||
it.typeFk tipo_id,
|
||||
o.code origen,
|
||||
it.category categoria,
|
||||
it.stems tallos,
|
||||
it.size medida,
|
||||
it.`size` medida,
|
||||
it.name article,
|
||||
w.code codigoTrabajador,
|
||||
tp.categoryFk reino_id,
|
||||
|
@ -264,17 +260,20 @@ proc: BEGIN
|
|||
e.id provider_id,
|
||||
it.comment comments,
|
||||
it.description itemDescription,
|
||||
IF(cy.cItemFk IS NULL AND i.visible = 0 AND i.avalaible = 0
|
||||
AND IFNULL(i.sd, 0) = 0, FALSE, TRUE) filtret,
|
||||
IF(cy.cItemFk IS NULL AND i.visible = 0
|
||||
AND i.avalaible = 0 AND (i.sd IS NULL OR i.sd = 0),
|
||||
FALSE,
|
||||
TRUE
|
||||
) filtret,
|
||||
IF(it.hasMinPrice, FORMAT(it.minPrice, 2), "") pvp,
|
||||
s.company_name
|
||||
FROM tmp.itemInventory i
|
||||
JOIN item it ON it.id = i.id
|
||||
LEFT JOIN itemType tp ON tp.id = it.typeFk
|
||||
LEFT JOIN worker w ON w.id = tp.workerFk
|
||||
JOIN itemType tp ON tp.id = it.typeFk
|
||||
JOIN worker w ON w.id = tp.workerFk
|
||||
LEFT JOIN buy b ON b.id = i.buy_id
|
||||
LEFT JOIN entry e ON e.id = b.entryFk
|
||||
LEFT JOIN origin o ON o.id = it.originFk
|
||||
LEFT JOIN `entry` e ON e.id = b.entryFk
|
||||
JOIN origin o ON o.id = it.originFk
|
||||
LEFT JOIN tLastYear ly ON ly.lItemFk = it.id
|
||||
LEFT JOIN tCurrentYear cy ON cy.cItemFk = it.id
|
||||
LEFT JOIN tTwoYearsAgo zy ON zy.tItemFk = it.id
|
||||
|
@ -287,8 +286,8 @@ proc: BEGIN
|
|||
OR ly.lweek1 OR ly.lweek2 OR ly.lweek3 OR ly.lweek4 OR ly.lweek5 OR ly.lweek6 OR ly.lweek7
|
||||
OR zy.vlweek1 OR zy.vlweek2 OR zy.vlweek3 OR zy.vlweek4 OR zy.vlweek5 OR zy.vlweek6 OR zy.vlweek7;
|
||||
|
||||
-- Elimina las tablas temporales creadas...
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.itemInventory,
|
||||
DROP TEMPORARY TABLE IF EXISTS
|
||||
tmp.itemInventory,
|
||||
tTwoYearsAgo,
|
||||
tLastYear,
|
||||
tCurrentYear,
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`item_ValuateInventory`(vDated DATE, vIsDetailed BOOLEAN)
|
||||
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`item_valuateInventory`(
|
||||
vDated DATE
|
||||
)
|
||||
BEGIN
|
||||
DECLARE vInventoried DATE;
|
||||
DECLARE vHasNotInventory BOOLEAN DEFAULT FALSE;
|
||||
|
@ -15,8 +17,7 @@ BEGIN
|
|||
SELECT tr.landed INTO vInventoried
|
||||
FROM travel tr
|
||||
JOIN `entry` e ON e.travelFk = tr.id
|
||||
JOIN entryConfig ec
|
||||
WHERE landed <= vDateDayEnd
|
||||
WHERE tr.landed <= vDateDayEnd
|
||||
AND e.supplierFk = vInventorySupplierFk
|
||||
ORDER BY tr.landed DESC
|
||||
LIMIT 1;
|
||||
|
@ -27,8 +28,7 @@ BEGIN
|
|||
SELECT landed INTO vInventoryClone
|
||||
FROM travel tr
|
||||
JOIN `entry` e ON e.travelFk = tr.id
|
||||
JOIN entryConfig ec
|
||||
WHERE landed >= vDated
|
||||
WHERE tr.landed >= vDated
|
||||
AND e.supplierFk = vInventorySupplierFk
|
||||
ORDER BY landed ASC
|
||||
LIMIT 1;
|
||||
|
@ -41,6 +41,7 @@ BEGIN
|
|||
warehouseFk SMALLINT,
|
||||
itemFk BIGINT,
|
||||
quantity INT,
|
||||
volume DECIMAL(10,2),
|
||||
cost DOUBLE DEFAULT 0,
|
||||
total DOUBLE DEFAULT 0,
|
||||
warehouseInventory VARCHAR(20),
|
||||
|
@ -60,9 +61,8 @@ BEGIN
|
|||
JOIN `entry` e ON e.id = b.entryFk
|
||||
JOIN travel tr ON tr.id = e.travelFk
|
||||
JOIN itemType t ON t.id = i.typeFk
|
||||
JOIN warehouse w ON w.id = warehouseInFk
|
||||
JOIN entryConfig ec
|
||||
WHERE landed = vDateDayEnd
|
||||
JOIN warehouse w ON w.id = tr.warehouseInFk
|
||||
WHERE tr.landed = vDateDayEnd
|
||||
AND e.supplierFk = vInventorySupplierFk
|
||||
AND w.valuatedInventory
|
||||
AND t.isInventory
|
||||
|
@ -78,9 +78,8 @@ BEGIN
|
|||
JOIN `entry` e ON e.id = b.entryFk
|
||||
JOIN travel tr ON tr.id = e.travelFk
|
||||
JOIN itemType t ON t.id = i.typeFk
|
||||
JOIN warehouse w ON w.id = warehouseInFk
|
||||
JOIN entryConfig ec
|
||||
WHERE landed = vInventoried
|
||||
JOIN warehouse w ON w.id = tr.warehouseInFk
|
||||
WHERE tr.landed = vInventoried
|
||||
AND e.supplierFk = vInventorySupplierFk
|
||||
AND w.valuatedInventory
|
||||
AND t.isInventory
|
||||
|
@ -99,7 +98,6 @@ BEGIN
|
|||
JOIN travel tr ON tr.id = e.travelFk
|
||||
JOIN itemType t ON t.id = i.typeFk
|
||||
JOIN warehouse w ON w.id = tr.warehouseInFk
|
||||
JOIN entryConfig ec
|
||||
WHERE tr.landed BETWEEN vInventoried AND vDateDayEnd
|
||||
AND IF(tr.landed = util.VN_CURDATE(), tr.isReceived, TRUE)
|
||||
AND NOT e.isRaid
|
||||
|
@ -183,52 +181,37 @@ BEGIN
|
|||
AND e.isConfirmed
|
||||
ON DUPLICATE KEY UPDATE tInventory.quantity = tInventory.quantity + (b.quantity);
|
||||
|
||||
CALL vn.buyUltimate(NULL, vDateDayEnd);
|
||||
CALL buyUltimate(NULL, vDateDayEnd);
|
||||
|
||||
DELETE FROM tInventory WHERE quantity IS NULL OR NOT quantity;
|
||||
|
||||
UPDATE tInventory i
|
||||
JOIN tmp.buyUltimate bu ON i.warehouseFk = bu.warehouseFk AND i.itemFk = bu.itemFk
|
||||
JOIN buy b ON b.id = bu.buyFk
|
||||
SET total = i.quantity * (IFNULL(b.buyingValue, 0) + IFNULL(b.packageValue, 0) + IFNULL(b.freightValue, 0) + IFNULL(b.comissionValue, 0)),
|
||||
cost = IFNULL(b.buyingValue, 0) + IFNULL(b.packageValue, 0) + IFNULL(b.freightValue, 0) + IFNULL(b.comissionValue, 0)
|
||||
WHERE i.quantity;
|
||||
LEFT JOIN itemCost ic ON ic.itemFk = i.itemFk
|
||||
AND ic.warehouseFk = i.warehouseFk
|
||||
SET i.total = i.quantity * (IFNULL(b.buyingValue, 0) + IFNULL(b.packageValue, 0) + IFNULL(b.freightValue, 0) + IFNULL(b.comissionValue, 0)),
|
||||
i.cost = IFNULL(b.buyingValue, 0) + IFNULL(b.packageValue, 0) + IFNULL(b.freightValue, 0) + IFNULL(b.comissionValue, 0),
|
||||
i.volume = i.quantity * ic.cm3delivery / 1000000;
|
||||
|
||||
DELETE FROM tInventory
|
||||
WHERE quantity IS NULL OR NOT quantity;
|
||||
|
||||
IF vIsDetailed THEN
|
||||
SELECT ti.warehouseFk,
|
||||
i.id itemFk,
|
||||
i.id,
|
||||
i.longName,
|
||||
i.size,
|
||||
ti.quantity,
|
||||
tp.name Tipo,
|
||||
ic.name Reino,
|
||||
ti.volume,
|
||||
tp.name itemTypeName,
|
||||
ic.name itemCategoryName,
|
||||
ti.cost,
|
||||
CAST(ti.total AS DECIMAL(10, 2)) total,
|
||||
ti.warehouseInventory almacen
|
||||
ti.total,
|
||||
ti.warehouseInventory
|
||||
FROM tInventory ti
|
||||
JOIN warehouse w ON w.id = warehouseFk
|
||||
JOIN item i ON i.id = ti.itemFk
|
||||
JOIN itemType tp ON tp.id = i.typeFk
|
||||
JOIN itemCategory ic ON ic.id = tp.categoryFk
|
||||
WHERE w.valuatedInventory
|
||||
AND ti.total > 0
|
||||
ORDER BY ti.total DESC;
|
||||
ELSE
|
||||
SELECT i.warehouseInventory Almacen,
|
||||
ic.name Reino,
|
||||
CAST(i.total AS DECIMAL(10, 2)) Euros,
|
||||
w.code Comprador,
|
||||
it.id
|
||||
FROM tInventory i
|
||||
JOIN warehouse wh ON wh.id = warehouseFk
|
||||
JOIN item it ON it.id = i.itemFk
|
||||
JOIN itemType itp ON itp.id = it.typeFk
|
||||
LEFT JOIN worker w ON w.id = itp.workerFk
|
||||
JOIN itemCategory ic ON ic.id = itp.categoryFk
|
||||
WHERE wh.valuatedInventory
|
||||
AND i.total > 0;
|
||||
END IF;
|
||||
AND ti.total > 0;
|
||||
|
||||
DROP TEMPORARY TABLE
|
||||
tmp.buyUltimate,
|
|
@ -27,7 +27,10 @@ BEGIN
|
|||
SELECT DISTINCT clientFk
|
||||
FROM (
|
||||
SELECT clientFk, SUM(quantity) totalQuantity
|
||||
FROM tmp.packagingToInvoice
|
||||
FROM tmp.packagingToInvoice tpi
|
||||
JOIN client c ON c.id = tpi.clientFk
|
||||
LEFT JOIN supplier s ON s.nif = c.fi
|
||||
WHERE s.id IS NULL
|
||||
GROUP BY itemFk, clientFk
|
||||
HAVING totalQuantity > 0)sub;
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`travel_throwAwb`(vSelf INT)
|
||||
BEGIN
|
||||
/**
|
||||
* Throws an error if travel does not have a logical AWB
|
||||
* or there are several AWBs associated with the same DUA
|
||||
*
|
||||
* @param vSelf The travel id
|
||||
*/
|
||||
IF NOT travel_hasUniqueAwb(vSelf) THEN
|
||||
CALL util.throw('A different AWB is found in the entries');
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -7,8 +7,8 @@ BEGIN
|
|||
CALL supplier_checkIsActive(NEW.supplierFk);
|
||||
SET NEW.currencyFk = entry_getCurrency(NEW.currencyFk, NEW.supplierFk);
|
||||
SET NEW.commission = entry_getCommission(NEW.travelFk, NEW.currencyFk,NEW.supplierFk);
|
||||
IF NEW.travelFk IS NOT NULL AND NOT travel_hasUniqueAwb(NEW.travelFk) THEN
|
||||
CALL util.throw('The travel is incorrect, there is a different AWB in the associated entries');
|
||||
IF NEW.travelFk IS NOT NULL THEN
|
||||
CALL travel_throwAwb(NEW.travelFk);
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
|
|
@ -25,8 +25,8 @@ BEGIN
|
|||
|
||||
IF NOT (NEW.travelFk <=> OLD.travelFk) THEN
|
||||
|
||||
IF NEW.travelFk IS NOT NULL AND NOT travel_hasUniqueAwb(NEW.travelFk) THEN
|
||||
CALL util.throw('The travel is incorrect, there is a different AWB in the associated entries');
|
||||
IF NEW.travelFk IS NOT NULL THEN
|
||||
CALL travel_throwAwb(NEW.travelFk);
|
||||
END IF;
|
||||
|
||||
SELECT COUNT(*) > 0 INTO vIsVirtual
|
||||
|
|
|
@ -9,8 +9,8 @@ BEGIN
|
|||
|
||||
CALL travel_checkWarehouseIsFeedStock(NEW.warehouseInFk);
|
||||
|
||||
IF NEW.awbFk IS NOT NULL AND NOT travel_hasUniqueAwb(NEW.id) THEN
|
||||
CALL util.throw('The AWB is incorrect, there is a different AWB in the associated entries');
|
||||
IF NEW.awbFk IS NOT NULL THEN
|
||||
CALL travel_throwAwb(NEW.id);
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
|
|
@ -33,8 +33,8 @@ BEGIN
|
|||
END IF;
|
||||
END IF;
|
||||
|
||||
IF (NOT(NEW.awbFk <=> OLD.awbFk)) AND NEW.awbFk IS NOT NULL AND NOT travel_hasUniqueAwb(NEW.id) THEN
|
||||
CALL util.throw('The AWB is incorrect, there is a different AWB in the associated entries');
|
||||
IF (NOT(NEW.awbFk <=> OLD.awbFk)) AND NEW.awbFk IS NOT NULL THEN
|
||||
CALL travel_throwAwb(NEW.id);
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
-- Place your SQL code here
|
||||
INSERT INTO salix.defaultViewConfig
|
||||
(tableCode, `columns`)
|
||||
VALUES('routesList', '{"ID":true,"worker":true,"agency":true,"vehicle":true,"date":true,"volume":true,"description":true,"started":true,"finished":true,"actions":true}');
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE vn.item ADD COLUMN photoMotivation VARCHAR(255);
|
|
@ -0,0 +1,4 @@
|
|||
-- Place your SQL code here
|
||||
|
||||
ALTER TABLE floranet.catalogue ADD addressFk int(11) NOT NULL;
|
||||
ALTER TABLE floranet.catalogue ADD CONSTRAINT catalogue_address_FK FOREIGN KEY (addressFk) REFERENCES vn.address(id) ON DELETE CASCADE ON UPDATE CASCADE;
|
|
@ -0,0 +1,6 @@
|
|||
ALTER TABLE floranet.builder DROP FOREIGN KEY builder_FK_1;
|
||||
ALTER TABLE floranet.`element` DROP PRIMARY KEY;
|
||||
ALTER TABLE floranet.`element` ADD id INT NOT NULL;
|
||||
ALTER TABLE floranet.`element` ADD CONSTRAINT element_pk PRIMARY KEY (id);
|
||||
ALTER TABLE floranet.builder ADD CONSTRAINT builder_element_FK FOREIGN KEY (elementFk) REFERENCES floranet.`element`(id) ON DELETE CASCADE ON UPDATE CASCADE;
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
-- Place your SQL code here
|
||||
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
|
||||
VALUES ('RouteConfig','*','READ','ALLOW','ROLE','employee');
|
|
@ -0,0 +1,46 @@
|
|||
use account;
|
||||
|
||||
INSERT INTO role
|
||||
SET name = 'reviewer',
|
||||
description = 'Revisor de producción',
|
||||
hasLogin = TRUE,
|
||||
created = util.VN_CURDATE(),
|
||||
modified = util.VN_CURDATE(),
|
||||
editorFk = NULL;
|
||||
|
||||
INSERT INTO roleInherit(
|
||||
role,
|
||||
inheritsFrom
|
||||
)
|
||||
SELECT r1.id,
|
||||
r2.id
|
||||
FROM role r1
|
||||
JOIN role r2
|
||||
WHERE r1.name = 'reviewer'
|
||||
AND r2.name = 'production'
|
||||
UNION
|
||||
SELECT ri.role,
|
||||
r2.id
|
||||
FROM roleInherit ri
|
||||
JOIN role r1 ON r1.id = ri.role
|
||||
JOIN role r2 ON r2.name = 'reviewer'
|
||||
WHERE r1.name IN ('claimManager', 'productionBoss')
|
||||
GROUP BY ri.role;
|
||||
|
||||
DELETE ri
|
||||
FROM roleInherit ri
|
||||
JOIN role r1 ON ri.role = r1.id
|
||||
JOIN role r2 ON ri.inheritsFrom = r2.id
|
||||
WHERE r1.name = 'replenisher'
|
||||
AND r2.name = 'buyer';
|
||||
|
||||
UPDATE salix.ACL
|
||||
SET principalId = 'reviewer'
|
||||
WHERE property = 'isInPreparing';
|
||||
|
||||
UPDATE user u
|
||||
JOIN vn.workerDepartment wd ON wd.workerFk = u.id
|
||||
JOIN vn.department d ON wd.departmentFk = d.id
|
||||
JOIN role r ON r.name = 'reviewer'
|
||||
SET u.role = r.id
|
||||
WHERE d.name IN ('REVISION', 'PREVIA');
|
|
@ -0,0 +1,24 @@
|
|||
REVOKE UPDATE ON vn. invoiceIn FROM administrative, hrBoss, buyer, logistic;
|
||||
GRANT UPDATE (id,
|
||||
serialNumber,
|
||||
serial,
|
||||
supplierFk,
|
||||
issued,
|
||||
supplierRef,
|
||||
currencyFk,
|
||||
created,
|
||||
companyFk,
|
||||
docFk,
|
||||
booked,
|
||||
operated,
|
||||
siiTypeInvoiceInFk,
|
||||
cplusRectificationTypeFk,
|
||||
cplusSubjectOpFk,
|
||||
cplusTaxBreakFk,
|
||||
siiTrascendencyInvoiceInFk,
|
||||
bookEntried,
|
||||
isVatDeductible,
|
||||
withholdingSageFk,
|
||||
expenseFkDeductible,
|
||||
editorFk
|
||||
) ON vn.invoiceIn TO administrative, hrBoss, buyer, logistic;
|
|
@ -0,0 +1,23 @@
|
|||
UPDATE salix.ACL
|
||||
SET accessType = 'READ'
|
||||
WHERE principalId IN ('administrative','buyer')
|
||||
AND model = 'invoiceIn'
|
||||
AND property = '*';
|
||||
|
||||
INSERT INTO salix.ACL (model, property, accessType, permission, principalType, principalId)
|
||||
VALUES
|
||||
('InvoiceIn', 'updateInvoiceIn', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
|
||||
('InvoiceIn', 'clone', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
|
||||
('InvoiceIn', 'corrective', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
|
||||
('InvoiceIn', 'exchangeRateUpdate', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
|
||||
('InvoiceIn', 'invoiceInEmail', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
|
||||
('InvoiceIn', 'toBook', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
|
||||
('InvoiceIn', 'toUnbook', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
|
||||
('InvoiceIn', 'deleteById', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
|
||||
('InvoiceIn', 'updateInvoiceIn', 'WRITE', 'ALLOW', 'ROLE', 'buyer'),
|
||||
('InvoiceIn', 'clone', 'WRITE', 'ALLOW', 'ROLE', 'buyer'),
|
||||
('InvoiceIn', 'corrective', 'WRITE', 'ALLOW', 'ROLE', 'buyer'),
|
||||
('InvoiceIn', 'exchangeRateUpdate', 'WRITE', 'ALLOW', 'ROLE', 'buyer'),
|
||||
('InvoiceIn', 'invoiceInEmail', 'WRITE', 'ALLOW', 'ROLE', 'buyer'),
|
||||
('InvoiceIn', 'toBook', 'WRITE', 'ALLOW', 'ROLE', 'buyer'),
|
||||
('InvoiceIn', 'deleteById', 'WRITE', 'ALLOW', 'ROLE', 'buyer');
|
|
@ -0,0 +1,9 @@
|
|||
-- Place your SQL code here
|
||||
CREATE OR REPLACE TABLE floranet.config (
|
||||
email varchar(255) DEFAULT 'floranet@verdnatura.es' NOT NULL
|
||||
)
|
||||
ENGINE=InnoDB
|
||||
DEFAULT CHARSET=utf8mb3
|
||||
COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
-- Place your SQL code here
|
||||
DROP TABLE IF EXISTS floranet.builder;
|
||||
|
||||
CREATE OR REPLACE TABLE floranet.`element` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(30) NOT NULL,
|
||||
`itemFk` int(11) DEFAULT NULL,
|
||||
`longNameFilter` varchar(30) DEFAULT NULL,
|
||||
`typeFk` smallint(5) unsigned DEFAULT NULL,
|
||||
`minSize` int(10) unsigned DEFAULT NULL,
|
||||
`maxSize` int(10) unsigned DEFAULT NULL,
|
||||
`inkFk` char(3) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci DEFAULT NULL,
|
||||
`originFk` tinyint(2) unsigned DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `element_FK` (`itemFk`),
|
||||
KEY `element_FK_1` (`typeFk`),
|
||||
KEY `element_FK_2` (`inkFk`),
|
||||
KEY `element_FK_3` (`originFk`),
|
||||
CONSTRAINT `element_FK` FOREIGN KEY (`itemFk`) REFERENCES `vn`.`item` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
CONSTRAINT `element_FK_1` FOREIGN KEY (`typeFk`) REFERENCES `vn`.`itemType` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
CONSTRAINT `element_FK_2` FOREIGN KEY (`inkFk`) REFERENCES `vn`.`ink` (`id`) ON UPDATE CASCADE,
|
||||
CONSTRAINT `element_FK_3` FOREIGN KEY (`originFk`) REFERENCES `vn`.`origin` (`id`) ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='Filtro para localizar posibles items que coincidan con la descripción';
|
||||
|
||||
CREATE OR REPLACE TABLE floranet.`recipe` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`itemFk` int(11) NOT NULL,
|
||||
`elementFk` int(11) NOT NULL,
|
||||
`quantity` int(10) unsigned NOT NULL DEFAULT 1,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `recipe_FK` (`itemFk`),
|
||||
KEY `recipe_FK_1` (`elementFk`),
|
||||
CONSTRAINT `recipe_FK` FOREIGN KEY (`itemFk`) REFERENCES `vn`.`item` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
CONSTRAINT `recipe_element_FK` FOREIGN KEY (`elementFk`) REFERENCES `element` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='Links handmade products with their elements';
|
|
@ -0,0 +1,20 @@
|
|||
-- Place your SQL code here
|
||||
|
||||
|
||||
-- floranet.recipe definition
|
||||
|
||||
CREATE OR REPLACE TABLE floranet.`recipe`
|
||||
(
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`itemFk` int(11) NOT NULL COMMENT 'Bouquet or plant name',
|
||||
`elementFk` int(11) NOT NULL COMMENT 'Item detail for bouquet''s composition',
|
||||
`quantity` int(10) unsigned NOT NULL DEFAULT 1,
|
||||
`cost` decimal(10,2) NOT NULL DEFAULT 1.00,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `recipe_FK` (`itemFk`),
|
||||
KEY `recipe_FK_1` (`elementFk`),
|
||||
CONSTRAINT `recipe_FK` FOREIGN KEY (`itemFk`) REFERENCES `vn`.`item` (`id`) ON UPDATE CASCADE,
|
||||
CONSTRAINT `recipe_item_FK` FOREIGN KEY (`elementFk`) REFERENCES `vn`.`item` (`id`) ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='Links handmade products with their elements';
|
||||
|
||||
DROP TABLE IF EXISTS floranet.`element`;
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE vn.productionConfig ADD scannablePreviusCodeType enum('qr','barcode')
|
||||
CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci DEFAULT 'barcode' NOT NULL;
|
|
@ -51,7 +51,7 @@ describe('Client Add address path', () => {
|
|||
await page.waitToClick(selectors.clientAddresses.saveButton);
|
||||
const message = await page.waitForSnackbar();
|
||||
|
||||
expect(message.text).toContain('Incoterms is required for a non UEE member');
|
||||
expect(message.text).toContain('Incoterms and Customs agent are required for a non UEE member');
|
||||
});
|
||||
|
||||
it(`should receive an error after clicking save button as customsAgent is empty`, async() => {
|
||||
|
@ -59,7 +59,7 @@ describe('Client Add address path', () => {
|
|||
await page.waitToClick(selectors.clientAddresses.saveButton);
|
||||
const message = await page.waitForSnackbar();
|
||||
|
||||
expect(message.text).toContain('Customs agent is required for a non UEE member');
|
||||
expect(message.text).toContain('Incoterms and Customs agent are required for a non UEE member');
|
||||
});
|
||||
|
||||
it(`should create a new custom agent and then save the address`, async() => {
|
||||
|
|
|
@ -225,7 +225,7 @@ describe('Ticket Edit sale path', () => {
|
|||
});
|
||||
|
||||
it('should show error trying to delete a ticket with a refund', async() => {
|
||||
await page.loginAndModule('production', 'ticket');
|
||||
await page.loginAndModule('salesPerson', 'ticket');
|
||||
await page.accessToSearchResult('8');
|
||||
await page.waitToClick(selectors.ticketDescriptor.moreMenu);
|
||||
await page.waitToClick(selectors.ticketDescriptor.moreMenuDeleteTicket);
|
||||
|
|
|
@ -69,3 +69,4 @@ Send cau: Enviar cau
|
|||
By sending this ticket, all the data related to the error, the section, the user, etc., are already sent.: Al enviar este cau ya se envían todos los datos relacionados con el error, la sección, el usuario, etc
|
||||
ExplainReason: Explique el motivo por el que no deberia aparecer este fallo
|
||||
You already have the mailAlias: Ya tienes este alias de correo
|
||||
Error loading ACLs: Error al cargar los ACLs
|
||||
|
|
|
@ -7,16 +7,17 @@ import UserError from 'core/lib/user-error';
|
|||
* @property {Boolean} loggedIn Whether the user is currently logged
|
||||
*/
|
||||
export default class Auth {
|
||||
constructor($http, $q, $state, $transitions, $window, vnToken, vnModules, aclService) {
|
||||
constructor($http, $q, vnApp, $translate, $state, $transitions, $window, vnToken, vnModules) {
|
||||
Object.assign(this, {
|
||||
$http,
|
||||
$q,
|
||||
vnApp,
|
||||
$translate,
|
||||
$state,
|
||||
$transitions,
|
||||
$window,
|
||||
vnToken,
|
||||
vnModules,
|
||||
aclService,
|
||||
loggedIn: false
|
||||
});
|
||||
}
|
||||
|
@ -39,9 +40,26 @@ export default class Auth {
|
|||
};
|
||||
|
||||
if (this.vnToken.token) {
|
||||
return this.loadAcls()
|
||||
const loadWithRetry = () => {
|
||||
return this.validateToken()
|
||||
.then(() => true)
|
||||
.catch(redirectToLogin);
|
||||
.catch(err => {
|
||||
switch (err.status) {
|
||||
case 400:
|
||||
case 401:
|
||||
return redirectToLogin();
|
||||
default:
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
this.vnApp.showMessage(this.$translate.instant('Loading...'));
|
||||
|
||||
resolve(loadWithRetry());
|
||||
}, 2000);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
return loadWithRetry();
|
||||
} else
|
||||
return redirectToLogin();
|
||||
});
|
||||
|
@ -87,13 +105,11 @@ export default class Auth {
|
|||
headers: {Authorization: json.data.token}
|
||||
}).then(({data}) => {
|
||||
this.vnToken.set(json.data.token, data.multimediaToken.id, now, json.data.ttl, remember);
|
||||
this.loadAcls().then(() => {
|
||||
let continueHash = this.$state.params.continue;
|
||||
if (continueHash)
|
||||
this.$window.location = continueHash;
|
||||
else
|
||||
this.$state.go('home');
|
||||
});
|
||||
}).catch(() => {});
|
||||
}
|
||||
|
||||
|
@ -107,24 +123,25 @@ export default class Auth {
|
|||
this.vnToken.unset();
|
||||
this.loggedIn = false;
|
||||
this.vnModules.reset();
|
||||
this.aclService.reset();
|
||||
this.vnModules.aclService.reset();
|
||||
this.$state.go('login');
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
loadAcls() {
|
||||
return this.aclService.load()
|
||||
validateToken() {
|
||||
return this.$http.get('VnUsers/validateToken')
|
||||
.then(() => {
|
||||
this.loggedIn = true;
|
||||
this.vnModules.reset();
|
||||
})
|
||||
.catch(err => {
|
||||
this.vnToken.unset();
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
}
|
||||
Auth.$inject = ['$http', '$q', '$state', '$transitions', '$window', 'vnToken', 'vnModules', 'aclService'];
|
||||
Auth.$inject = [
|
||||
'$http', '$q', 'vnApp', '$translate', '$state',
|
||||
'$transitions', '$window', 'vnToken', 'vnModules'];
|
||||
|
||||
ngModule.service('vnAuth', Auth);
|
||||
|
|
|
@ -164,6 +164,7 @@ export default class UploadPhoto extends Component {
|
|||
|
||||
const options = {
|
||||
type: 'blob',
|
||||
size: 'original'
|
||||
};
|
||||
return this.editor.result(options)
|
||||
.then(blob => this.newPhoto.blob = blob)
|
||||
|
|
|
@ -12,7 +12,8 @@ function config($stateProvider, $urlRouterProvider) {
|
|||
template: '<vn-layout></vn-layout>',
|
||||
resolve: {
|
||||
config: ['vnConfig', vnConfig => vnConfig.initialize()],
|
||||
token: ['vnToken', vnToken => vnToken.fetchConfig()]
|
||||
token: ['vnToken', vnToken => vnToken.fetchConfig()],
|
||||
acl: ['aclService', aclService => aclService.load()]
|
||||
}
|
||||
})
|
||||
.state('outLayout', {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
module.exports = function(Self) {
|
||||
require('../methods/application/status')(Self);
|
||||
require('../methods/application/post')(Self);
|
||||
|
|
|
@ -61,7 +61,8 @@
|
|||
"Changed sale discount": "I have changed the following lines discounts from the ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}",
|
||||
"Created claim": "I have created the claim [{{claimId}}]({{{claimUrl}}}) for the following lines from the ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}",
|
||||
"Changed sale price": "I have changed the price of [{{itemId}} {{concept}}]({{{itemUrl}}}) ({{quantity}}) from {{oldPrice}}€ ➔ *{{newPrice}}€* of the ticket [{{ticketId}}]({{{ticketUrl}}})",
|
||||
"Changed sale quantity": "I have changed the quantity of [{{itemId}} {{concept}}]({{{itemUrl}}}) from {{oldQuantity}} ➔ *{{newQuantity}}* of the ticket [{{ticketId}}]({{{ticketUrl}}})",
|
||||
"Changed sale quantity": "I have changed {{changes}} of the ticket [{{ticketId}}]({{{ticketUrl}}})",
|
||||
"Changes in sales": "the quantity of [{{itemId}} {{concept}}]({{{itemUrl}}}) from {{oldQuantity}} ➔ *{{newQuantity}}*",
|
||||
"Changed sale reserved state": "I have changed the following lines reserved state from the ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}",
|
||||
"Bought units from buy request": "Bought {{quantity}} units of [{{itemId}} {{concept}}]({{{urlItem}}}) for the ticket id [{{ticketId}}]({{{url}}})",
|
||||
"MESSAGE_INSURANCE_CHANGE": "I have changed the insurence credit of client [{{clientName}} ({{clientId}})]({{{url}}}) to *{{credit}} €*",
|
||||
|
@ -227,5 +228,6 @@
|
|||
"They're not your subordinate": "They're not your subordinate",
|
||||
"InvoiceIn is already booked": "InvoiceIn is already booked",
|
||||
"This workCenter is already assigned to this agency": "This workCenter is already assigned to this agency",
|
||||
"You can only have one PDA": "You can only have one PDA"
|
||||
"You can only have one PDA": "You can only have one PDA",
|
||||
"Incoterms and Customs agent are required for a non UEE member": "Incoterms and Customs agent are required for a non UEE member"
|
||||
}
|
|
@ -124,7 +124,8 @@
|
|||
"Changed sale discount": "He cambiado el descuento de las siguientes lineas al ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}",
|
||||
"Created claim": "He creado la reclamación [{{claimId}}]({{{claimUrl}}}) de las siguientes lineas del ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}",
|
||||
"Changed sale price": "He cambiado el precio de [{{itemId}} {{concept}}]({{{itemUrl}}}) ({{quantity}}) de {{oldPrice}}€ ➔ *{{newPrice}}€* del ticket [{{ticketId}}]({{{ticketUrl}}})",
|
||||
"Changed sale quantity": "He cambiado la cantidad de [{{itemId}} {{concept}}]({{{itemUrl}}}) de {{oldQuantity}} ➔ *{{newQuantity}}* del ticket [{{ticketId}}]({{{ticketUrl}}})",
|
||||
"Changed sale quantity": "He cambiado {{changes}} del ticket [{{ticketId}}]({{{ticketUrl}}})",
|
||||
"Changes in sales": "la cantidad de [{{itemId}} {{concept}}]({{{itemUrl}}}) de {{oldQuantity}} ➔ *{{newQuantity}}*",
|
||||
"State": "Estado",
|
||||
"regular": "normal",
|
||||
"reserved": "reservado",
|
||||
|
@ -358,6 +359,8 @@
|
|||
"Select ticket or client": "Elija un ticket o un client",
|
||||
"It was not able to create the invoice": "No se pudo crear la factura",
|
||||
"ticketCommercial": "El ticket {{ ticket }} para el vendedor {{ salesMan }} está en preparación. (mensaje generado automáticamente)",
|
||||
"This PDA is already assigned to another user": "Este PDA ya está asignado a otro usuario",
|
||||
"You can only have one PDA": "Solo puedes tener un PDA"
|
||||
"This PDA is already assigned to another user": "Esta PDA ya está asignado a otro usuario",
|
||||
"You can only have one PDA": "Solo puedes tener una PDA",
|
||||
"Incoterms and Customs agent are required for a non UEE member": "Se requieren Incoterms y agente de aduanas para un no miembro de la UEE",
|
||||
"You can not use the same password": "No puedes usar la misma contraseña"
|
||||
}
|
|
@ -123,8 +123,9 @@
|
|||
"Added sale to ticket": "J'ai ajouté la ligne suivante au ticket [{{ticketId}}]({{{ticketUrl}}}): {{{addition}}}",
|
||||
"Changed sale discount": "J'ai changé le rabais des lignes suivantes du ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}",
|
||||
"Created claim": "J'ai créé la réclamation [{{claimId}}]({{{claimUrl}}}) des lignes suivantes du ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}",
|
||||
"Changed sale price": "J'ai changé le prix de [{{itemId}} {{concept}}]({{{itemUrl}}}) ({{quantity}}) de {{oldPrice}}€ ➔ *{{newPrice}}€* du ticket [{{ticketId}}]({{{ticketUrl}}})",
|
||||
"Changed sale quantity": "J'ai changé la quantité de {{itemId}} {{concept}} de {{oldQuantity}} ➔ {{newQuantity}} du ticket [{{ticketId}}]({{{ticketUrl}}})",
|
||||
"Changed sale price": " le prix de [{{itemId}} {{concept}}]({{{itemUrl}}}) ({{quantity}}) de {{oldPrice}}€ ➔ *{{newPrice}}€* du ticket [{{ticketId}}]({{{ticketUrl}}})",,
|
||||
"Changed sale quantity": "J'ai changé {{changes}} du ticket [{{ticketId}}]({{{ticketUrl}}})",
|
||||
"Changes in sales": "la quantité de {{itemId}} {{concept}} de {{oldQuantity}} ➔ {{newQuantity}}",
|
||||
"State": "État",
|
||||
"regular": "normal",
|
||||
"reserved": "réservé",
|
||||
|
|
|
@ -124,7 +124,8 @@
|
|||
"Changed sale discount": "Desconto da venda alterado no ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}",
|
||||
"Created claim": "Reclamação criada [{{claimId}}]({{{claimUrl}}}) no ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}",
|
||||
"Changed sale price": "Preço da venda alterado para [{{itemId}} {{concept}}]({{{itemUrl}}}) ({{quantity}}) de {{oldPrice}}€ ➔ *{{newPrice}}€* no ticket [{{ticketId}}]({{{ticketUrl}}})",
|
||||
"Changed sale quantity": "Quantidade da venda alterada para [{{itemId}} {{concept}}]({{{itemUrl}}}) de {{oldQuantity}} ➔ *{{newQuantity}}* no ticket [{{ticketId}}]({{{ticketUrl}}})",
|
||||
"Changed sale quantity": "Quantidade da venda alterada para {{changes}} no ticket [{{ticketId}}]({{{ticketUrl}}})",
|
||||
"Changes in sales": " [{{itemId}} {{concept}}]({{{itemUrl}}}) de {{oldQuantity}} ➔ *{{newQuantity}}* ",
|
||||
"State": "Estado",
|
||||
"regular": "normal",
|
||||
"reserved": "reservado",
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
module.exports = (localAsProduction = true) => {
|
||||
return (!process.env.NODE_ENV && localAsProduction) || process.env.NODE_ENV == 'production';
|
||||
};
|
|
@ -3,9 +3,10 @@ const app = require('vn-loopback/server/server');
|
|||
const ldap = require('../util/ldapjs-extra');
|
||||
const crypto = require('crypto');
|
||||
const nthash = require('smbhash').nthash;
|
||||
const isProduction = require('vn-loopback/server/boot/isProduction');
|
||||
|
||||
module.exports = Self => {
|
||||
const shouldSync = process.env.NODE_ENV !== 'test';
|
||||
const shouldSync = isProduction();
|
||||
|
||||
Self.getLinker = async function() {
|
||||
return await Self.findOne({
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
const ldap = require('../util/ldapjs-extra');
|
||||
const execFile = require('child_process').execFile;
|
||||
const isProduction = require('vn-loopback/server/boot/isProduction');
|
||||
|
||||
/**
|
||||
* Summary of userAccountControl flags:
|
||||
|
@ -12,7 +13,7 @@ const UserAccountControlFlags = {
|
|||
};
|
||||
|
||||
module.exports = Self => {
|
||||
const shouldSync = process.env.NODE_ENV !== 'test';
|
||||
const shouldSync = isProduction();
|
||||
|
||||
Self.getLinker = async function() {
|
||||
return await Self.findOne({
|
||||
|
|
|
@ -6,6 +6,7 @@ describe('claimBeginning', () => {
|
|||
const claimManagerId = 72;
|
||||
const activeCtx = {
|
||||
accessToken: {userId: claimManagerId},
|
||||
__: value => value
|
||||
};
|
||||
const ctx = {req: activeCtx};
|
||||
|
||||
|
|
|
@ -92,11 +92,8 @@ module.exports = function(Self) {
|
|||
}, myOptions);
|
||||
|
||||
const isUeeMember = province.country().isUeeMember;
|
||||
if (!isUeeMember && !args.incotermsFk)
|
||||
throw new UserError(`Incoterms is required for a non UEE member`);
|
||||
|
||||
if (!isUeeMember && !args.customsAgentFk)
|
||||
throw new UserError(`Customs agent is required for a non UEE member`);
|
||||
if (!isUeeMember && (!args.incotermsFk || !args.customsAgentFk))
|
||||
throw new UserError(`Incoterms and Customs agent are required for a non UEE member`);
|
||||
|
||||
delete args.ctx; // Remove unwanted properties
|
||||
const newAddress = await models.Address.create(args, myOptions);
|
||||
|
|
|
@ -50,7 +50,7 @@ describe('Address createAddress', () => {
|
|||
}
|
||||
|
||||
expect(error).toBeDefined();
|
||||
expect(error.message).toEqual('Incoterms is required for a non UEE member');
|
||||
expect(error.message).toEqual('Incoterms and Customs agent are required for a non UEE member');
|
||||
});
|
||||
|
||||
it('should throw a non uee member error if no customsAgent is defined', async() => {
|
||||
|
@ -81,7 +81,7 @@ describe('Address createAddress', () => {
|
|||
}
|
||||
|
||||
expect(error).toBeDefined();
|
||||
expect(error.message).toEqual('Customs agent is required for a non UEE member');
|
||||
expect(error.message).toEqual('Incoterms and Customs agent are required for a non UEE member');
|
||||
});
|
||||
|
||||
it('should create a new address and set as a client default address', async() => {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const got = require('got');
|
||||
const UserError = require('vn-loopback/util/user-error');
|
||||
const isProduction = require('vn-loopback/server/boot/isProduction');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('send', {
|
||||
|
@ -47,7 +48,7 @@ module.exports = Self => {
|
|||
|
||||
let response;
|
||||
try {
|
||||
if (process.env.NODE_ENV !== 'production')
|
||||
if (!isProduction(false))
|
||||
response = {result: [{status: 'ok'}]};
|
||||
else {
|
||||
const jsonTest = {
|
||||
|
|
|
@ -76,6 +76,15 @@
|
|||
},
|
||||
"enlazadoSage": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"enlazado": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"key": {
|
||||
"type": "number",
|
||||
"mysql": {
|
||||
"columnName": "CLAVE"
|
||||
}
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
|
|
|
@ -22,5 +22,8 @@
|
|||
},
|
||||
"EntryObservation": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"EntryType": {
|
||||
"dataSource": "vn"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"name": "EntryType",
|
||||
"base": "VnModel",
|
||||
"mixins": {
|
||||
"Loggable": true
|
||||
},
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "entryType"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"code": {
|
||||
"type": "string",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"isInformal": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -101,6 +101,11 @@
|
|||
"type": "belongsTo",
|
||||
"model": "Account",
|
||||
"foreignKey": "observationEditorFk"
|
||||
},
|
||||
"entryType": {
|
||||
"type": "belongsTo",
|
||||
"model": "EntryType",
|
||||
"foreignKey": "typeFk"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -54,6 +54,20 @@ module.exports = Self => {
|
|||
value: rate
|
||||
});
|
||||
}
|
||||
const monday = 1;
|
||||
if (xmlDateWithoutTime.getDay() === monday) {
|
||||
const saturday = new Date(xmlDateWithoutTime);
|
||||
saturday.setDate(xmlDateWithoutTime.getDate() - 2);
|
||||
const sunday = new Date(xmlDateWithoutTime);
|
||||
sunday.setDate(xmlDateWithoutTime.getDate() - 1);
|
||||
|
||||
for (const date of [saturday, sunday]) {
|
||||
await models.ReferenceRate.upsertWithWhere(
|
||||
{currencyFk: currency.id, dated: date},
|
||||
{currencyFk: currency.id, dated: date, value: rate}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
describe('invoiceIn toUnbook()', () => {
|
||||
it('should check that invoiceIn is unbooked', async() => {
|
||||
const userId = 1;
|
||||
const ctx = {
|
||||
req: {
|
||||
|
||||
accessToken: {userId: userId},
|
||||
headers: {origin: 'http://localhost:5000'},
|
||||
}
|
||||
};
|
||||
const invoiceInId = 1;
|
||||
const tx = await models.InvoiceIn.beginTransaction({});
|
||||
const options = {transaction: tx};
|
||||
|
||||
try {
|
||||
await models.InvoiceIn.toBook(ctx, invoiceInId, options);
|
||||
const bookEntry = await models.InvoiceIn.toUnbook(ctx, invoiceInId, options);
|
||||
const invoiceIn = await models.InvoiceIn.findById(invoiceInId, null, options);
|
||||
|
||||
expect(bookEntry.accountingEntries).toEqual(4);
|
||||
expect(bookEntry.isLinked).toBeFalsy();
|
||||
expect(invoiceIn.isBooked).toEqual(false);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
|
@ -0,0 +1,80 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('toUnbook', {
|
||||
description: 'To unbook the invoiceIn',
|
||||
accessType: 'WRITE',
|
||||
accepts: {
|
||||
arg: 'id',
|
||||
type: 'number',
|
||||
required: true,
|
||||
description: 'The invoiceIn id',
|
||||
http: {source: 'path'}
|
||||
},
|
||||
returns: {
|
||||
type: 'object',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: '/:id/toUnbook',
|
||||
verb: 'POST'
|
||||
}
|
||||
});
|
||||
|
||||
Self.toUnbook = async(ctx, invoiceInId, options) => {
|
||||
let tx;
|
||||
const models = Self.app.models;
|
||||
const myOptions = {userId: ctx.req.accessToken.userId};
|
||||
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
if (!myOptions.transaction) {
|
||||
tx = await Self.beginTransaction({});
|
||||
myOptions.transaction = tx;
|
||||
}
|
||||
|
||||
try {
|
||||
let isLinked;
|
||||
let accountingEntries;
|
||||
|
||||
let bookEntry = await models.Xdiario.findOne({
|
||||
fields: ['ASIEN'],
|
||||
where: {
|
||||
and: [
|
||||
{key: invoiceInId},
|
||||
{enlazado: false},
|
||||
{enlazadoSage: false}
|
||||
]
|
||||
}
|
||||
}, myOptions);
|
||||
|
||||
let asien = bookEntry?.ASIEN;
|
||||
if (asien) {
|
||||
accountingEntries = await models.Xdiario.count({ASIEN: asien}, myOptions);
|
||||
|
||||
await models.Xdiario.destroyAll({ASIEN: asien}, myOptions);
|
||||
await Self.updateAll({id: invoiceInId}, {isBooked: false}, myOptions);
|
||||
} else {
|
||||
const linkedBookEntry = await models.Xdiario.findOne({
|
||||
fields: ['ASIEN'],
|
||||
where: {
|
||||
key: invoiceInId,
|
||||
and: [{or: [{enlazado: true, enlazadoSage: true}]}]
|
||||
}
|
||||
}, myOptions);
|
||||
|
||||
asien = linkedBookEntry?.ASIEN;
|
||||
isLinked = true;
|
||||
}
|
||||
if (tx) await tx.commit();
|
||||
|
||||
return {
|
||||
isLinked,
|
||||
bookEntry: asien,
|
||||
accountingEntries
|
||||
};
|
||||
} catch (e) {
|
||||
if (tx) await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
};
|
|
@ -0,0 +1,104 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('updateInvoiceIn', {
|
||||
description: 'To update the invoiceIn attributes',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'id',
|
||||
type: 'number',
|
||||
required: true,
|
||||
description: 'The invoiceIn id',
|
||||
http: {source: 'path'}
|
||||
}, {
|
||||
arg: 'supplierFk',
|
||||
type: 'number',
|
||||
required: true
|
||||
}, {
|
||||
arg: 'supplierRef',
|
||||
type: 'any',
|
||||
}, {
|
||||
arg: 'issued',
|
||||
type: 'any',
|
||||
}, {
|
||||
arg: 'operated',
|
||||
type: 'any',
|
||||
}, {
|
||||
arg: 'deductibleExpenseFk',
|
||||
type: 'any',
|
||||
}, {
|
||||
arg: 'dmsFk',
|
||||
type: 'any',
|
||||
}, {
|
||||
arg: 'bookEntried',
|
||||
type: 'any',
|
||||
}, {
|
||||
arg: 'booked',
|
||||
type: 'any',
|
||||
}, {
|
||||
arg: 'currencyFk',
|
||||
type: 'number',
|
||||
required: true
|
||||
}, {
|
||||
arg: 'companyFk',
|
||||
type: 'any',
|
||||
}, {
|
||||
arg: 'withholdingSageFk',
|
||||
type: 'any',
|
||||
},
|
||||
],
|
||||
returns: {
|
||||
type: 'object',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: '/:id/updateInvoiceIn',
|
||||
verb: 'PATCH'
|
||||
}
|
||||
});
|
||||
|
||||
Self.updateInvoiceIn = async(ctx,
|
||||
id,
|
||||
supplierFk,
|
||||
supplierRef,
|
||||
issued,
|
||||
operated,
|
||||
deductibleExpenseFk,
|
||||
dmsFk,
|
||||
bookEntried,
|
||||
booked,
|
||||
currencyFk,
|
||||
companyFk,
|
||||
withholdingSageFk,
|
||||
options
|
||||
) => {
|
||||
let tx;
|
||||
const myOptions = {userId: ctx.req.accessToken.userId};
|
||||
|
||||
if (typeof options == 'object') Object.assign(myOptions, options);
|
||||
|
||||
if (!myOptions.transaction) {
|
||||
tx = await Self.beginTransaction({});
|
||||
myOptions.transaction = tx;
|
||||
}
|
||||
|
||||
try {
|
||||
const invoiceIn = await Self.findById(id, null, myOptions);
|
||||
invoiceIn.updateAttributes({supplierFk,
|
||||
supplierRef,
|
||||
issued,
|
||||
operated,
|
||||
deductibleExpenseFk,
|
||||
dmsFk,
|
||||
bookEntried,
|
||||
booked,
|
||||
currencyFk,
|
||||
companyFk,
|
||||
withholdingSageFk
|
||||
}, myOptions);
|
||||
if (tx) await tx.commit();
|
||||
return invoiceIn;
|
||||
} catch (e) {
|
||||
if (tx) await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
};
|
|
@ -11,6 +11,8 @@ module.exports = Self => {
|
|||
require('../methods/invoice-in/getSerial')(Self);
|
||||
require('../methods/invoice-in/corrective')(Self);
|
||||
require('../methods/invoice-in/exchangeRateUpdate')(Self);
|
||||
require('../methods/invoice-in/toUnbook')(Self);
|
||||
require('../methods/invoice-in/updateInvoiceIn')(Self);
|
||||
|
||||
Self.rewriteDbError(function(err) {
|
||||
if (err.code === 'ER_ROW_IS_REFERENCED_2' && err.sqlMessage.includes('vehicleInvoiceIn'))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<mg-ajax path="InvoiceIns/{{patch.params.id}}" options="vnPatch"></mg-ajax>
|
||||
<mg-ajax path="InvoiceIns/{{patch.params.id}}/updateInvoiceIn" options="vnPatch"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.invoiceIn"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const isProduction = require('vn-loopback/server/boot/isProduction');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('download', {
|
||||
|
@ -66,7 +67,7 @@ module.exports = Self => {
|
|||
console.error(err);
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV == 'test') {
|
||||
if (!isProduction()) {
|
||||
try {
|
||||
await fs.access(file.path);
|
||||
} catch (error) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
const print = require('vn-print');
|
||||
const path = require('path');
|
||||
const UserError = require('vn-loopback/util/user-error');
|
||||
const isProduction = require('vn-loopback/server/boot/isProduction');
|
||||
|
||||
module.exports = Self => {
|
||||
require('../methods/invoiceOut/filter')(Self);
|
||||
|
@ -59,7 +60,7 @@ module.exports = Self => {
|
|||
hasPdf: true
|
||||
}, options);
|
||||
|
||||
if (process.env.NODE_ENV !== 'test') {
|
||||
if (isProduction()) {
|
||||
await print.storage.write(buffer, {
|
||||
type: 'invoice',
|
||||
path: pdfFile.path,
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
<vn-autocomplete
|
||||
url="Tickets"
|
||||
label="Ticket"
|
||||
search-function="{or: [{id: $search}, {nickname: {like: '%'+$search+'%'}}]}"
|
||||
search-function="{refFk: null, or: [{id: $search}, {nickname: {like: '%'+$search+'%'}}]}"
|
||||
show-field="id"
|
||||
value-field="id"
|
||||
fields="['nickname']"
|
||||
|
|
|
@ -4,7 +4,7 @@ module.exports = Self => {
|
|||
accessType: 'READ',
|
||||
accepts: [{
|
||||
arg: 'barcode',
|
||||
type: 'number',
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: 'barcode'
|
||||
}],
|
||||
|
|
|
@ -64,7 +64,7 @@ describe('item getBalance()', () => {
|
|||
const secondItemBalance = await models.Item.getBalance(ctx, secondFilter, options);
|
||||
|
||||
expect(firstItemBalance[9].claimFk).toEqual(null);
|
||||
expect(secondItemBalance[4].claimFk).toEqual(2);
|
||||
expect(secondItemBalance[7].claimFk).toEqual(2);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"properties": {
|
||||
"id": {
|
||||
"id": true,
|
||||
"type": "number",
|
||||
"type": "string",
|
||||
"description": "Identifier"
|
||||
},
|
||||
"name": {
|
||||
|
|
|
@ -155,6 +155,9 @@
|
|||
"minQuantity": {
|
||||
"type": "number",
|
||||
"description": "Min quantity"
|
||||
},
|
||||
"photoMotivation": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const UserError = require('vn-loopback/util/user-error');
|
||||
const isProduction = require('vn-loopback/server/boot/isProduction');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('upload', {
|
||||
|
@ -111,7 +112,7 @@ module.exports = Self => {
|
|||
const destinationFile = path.join(
|
||||
accessContainer.client.root, accessContainer.name, appName, `${toVersion}.7z`);
|
||||
|
||||
if (process.env.NODE_ENV == 'test')
|
||||
if (!isProduction())
|
||||
await fs.unlink(srcFile);
|
||||
else {
|
||||
await fs.move(srcFile, destinationFile, {
|
||||
|
|
|
@ -151,7 +151,7 @@ describe('SalesMonitor salesFilter()', () => {
|
|||
const result = await models.SalesMonitor.salesFilter(ctx, filter, options);
|
||||
const firstRow = result[0];
|
||||
|
||||
expect(result.length).toEqual(12);
|
||||
expect(result.length).toEqual(15);
|
||||
expect(firstRow.alertLevel).not.toEqual(0);
|
||||
|
||||
await tx.rollback();
|
||||
|
|
|
@ -11,6 +11,12 @@
|
|||
"Sector": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"SectorCollection": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"SectorCollectionSaleGroup": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"Train": {
|
||||
"dataSource": "vn"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "SectorCollection",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "sectorCollection"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "number",
|
||||
"id": true
|
||||
},
|
||||
"created": {
|
||||
"type": "date"
|
||||
},
|
||||
"userFk": {
|
||||
"type": "number"
|
||||
},
|
||||
"sectorFk": {
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"name": "SectorCollectionSaleGroup",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "sectorCollectionSaleGroup"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "number",
|
||||
"id": true
|
||||
},
|
||||
"created": {
|
||||
"type": "date"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
"sectorCollection": {
|
||||
"type": "belongsTo",
|
||||
"model": "SectorCollection",
|
||||
"foreignKey": "sectorCollectionFk"
|
||||
},
|
||||
"saleGroup": {
|
||||
"type": "belongsTo",
|
||||
"model": "SaleGroup",
|
||||
"foreignKey": "saleGroupFk"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,7 +33,7 @@ module.exports = Self => {
|
|||
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, et.printedStickers
|
||||
) SELECT i.id, i.name, et.quantity, SUM(b.quantity) quantityTotal, et.printedStickers, ic.url
|
||||
FROM vn.buy b
|
||||
JOIN vn.item i ON i.id = b.itemFk
|
||||
JOIN vn.entry e ON e.id = b.entryFk
|
||||
|
@ -41,6 +41,7 @@ module.exports = Self => {
|
|||
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
|
||||
JOIN hedera.imageConfig ic
|
||||
WHERE e.supplierFk = ?
|
||||
AND i.family IN ('EMB', 'CONT')
|
||||
AND b.created > (util.VN_CURDATE() - INTERVAL bc.monthsAgo MONTH)
|
||||
|
|
|
@ -2,10 +2,12 @@ const models = require('vn-loopback/server/server').models;
|
|||
const LoopBackContext = require('loopback-context');
|
||||
|
||||
describe('ticket setDelivered()', () => {
|
||||
const userId = 50;
|
||||
const userId = 49;
|
||||
const activeCtx = {
|
||||
accessToken: {userId: userId},
|
||||
__: value => value
|
||||
};
|
||||
const ctx = {req: activeCtx};
|
||||
|
||||
beforeAll(async() => {
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||
|
@ -19,8 +21,6 @@ describe('ticket setDelivered()', () => {
|
|||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const ctx = {req: {accessToken: {userId: 49}}};
|
||||
|
||||
const originalTicketOne = await models.Ticket.findById(8, null, options);
|
||||
const originalTicketTwo = await models.Ticket.findById(10, null, options);
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ module.exports = Self => {
|
|||
http: {source: 'path'}
|
||||
},
|
||||
{
|
||||
arg: 'itemId',
|
||||
type: 'number',
|
||||
arg: 'barcode',
|
||||
type: 'any',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
|
@ -29,7 +29,7 @@ module.exports = Self => {
|
|||
}
|
||||
});
|
||||
|
||||
Self.addSale = async(ctx, id, itemId, quantity, options) => {
|
||||
Self.addSale = async(ctx, id, barcode, quantity, options) => {
|
||||
const $t = ctx.req.__; // $translate
|
||||
const models = Self.app.models;
|
||||
const myOptions = {userId: ctx.req.accessToken.userId};
|
||||
|
@ -46,7 +46,9 @@ module.exports = Self => {
|
|||
try {
|
||||
await models.Ticket.isEditableOrThrow(ctx, id, myOptions);
|
||||
|
||||
const itemId = await models.ItemBarcode.toItem(barcode, myOptions);
|
||||
const item = await models.Item.findById(itemId, null, myOptions);
|
||||
|
||||
const ticket = await models.Ticket.findById(id, {
|
||||
include: {
|
||||
relation: 'client',
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('addSaleByCode', {
|
||||
description: 'Add a collection',
|
||||
accessType: 'WRITE',
|
||||
accepts: [
|
||||
{
|
||||
arg: 'barcode',
|
||||
type: 'string',
|
||||
required: true
|
||||
}, {
|
||||
arg: 'quantity',
|
||||
type: 'number',
|
||||
required: true
|
||||
}, {
|
||||
arg: 'ticketFk',
|
||||
type: 'number',
|
||||
required: true
|
||||
}, {
|
||||
arg: 'warehouseFk',
|
||||
type: 'number',
|
||||
required: true
|
||||
},
|
||||
|
||||
],
|
||||
http: {
|
||||
path: `/addSaleByCode`,
|
||||
verb: 'POST'
|
||||
},
|
||||
});
|
||||
|
||||
Self.addSaleByCode = async(ctx, barcode, quantity, ticketFk, warehouseFk, options) => {
|
||||
const myOptions = {userId: ctx.req.accessToken.userId};
|
||||
let tx;
|
||||
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
if (!myOptions.transaction) {
|
||||
tx = await Self.beginTransaction({});
|
||||
myOptions.transaction = tx;
|
||||
}
|
||||
|
||||
try {
|
||||
const [[item]] = await Self.rawSql('CALL vn.item_getInfo(?,?)', [barcode, warehouseFk], myOptions);
|
||||
if (!item?.available) throw new UserError('We do not have availability for the selected item');
|
||||
|
||||
await Self.rawSql('CALL vn.collection_addItem(?, ?, ?)', [item.id, quantity, ticketFk], myOptions);
|
||||
|
||||
if (tx) await tx.commit();
|
||||
} catch (e) {
|
||||
if (tx) await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
};
|
|
@ -8,18 +8,13 @@ module.exports = Self => {
|
|||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
const state = await models.TicketState.findOne({
|
||||
where: {ticketFk: id}
|
||||
}, myOptions);
|
||||
|
||||
const state = await models.TicketState.findOne({where: {ticketFk: id}}, myOptions);
|
||||
const isRoleAdvanced = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'isRoleAdvanced', '*');
|
||||
const isProductionReviewer = await models.ACL.checkAccessAcl(ctx, 'Sale', 'isInPreparing', '*');
|
||||
const canEditWeeklyTicket = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'canEditWeekly', 'WRITE');
|
||||
const alertLevel = state ? state.alertLevel : null;
|
||||
const ticket = await models.Ticket.findById(id, {
|
||||
fields: ['clientFk'],
|
||||
include: {
|
||||
relation: 'client'
|
||||
}
|
||||
fields: ['clientFk'], include: {relation: 'client'}
|
||||
}, myOptions);
|
||||
|
||||
const isLocked = await models.Ticket.isLocked(id, myOptions);
|
||||
|
@ -29,10 +24,24 @@ module.exports = Self => {
|
|||
const isNormalClient = ticket && ticket.client().typeFk == 'normal';
|
||||
const isEditable = !(alertLevelGreaterThanZero && isNormalClient);
|
||||
|
||||
const ticketCollection = await models.TicketCollection.findOne({
|
||||
include: {relation: 'collection'}, where: {ticketFk: id}
|
||||
}, myOptions);
|
||||
let isOwner = ticketCollection?.collection()?.workerFk === ctx.req.accessToken.userId;
|
||||
|
||||
if (!isOwner) {
|
||||
const saleGroup = await models.SaleGroup.findOne({fields: ['id'], where: {ticketFk: id}}, myOptions);
|
||||
const sectorCollectionSaleGroup = saleGroup && await models.SectorCollectionSaleGroup.findOne({
|
||||
include: {relation: 'sectorCollection'}, where: {saleGroupFk: saleGroup.id}
|
||||
}, myOptions);
|
||||
|
||||
isOwner = sectorCollectionSaleGroup?.sectorCollection()?.userFk === ctx.req.accessToken.userId;
|
||||
}
|
||||
|
||||
if (!ticket)
|
||||
throw new ForbiddenError(`The ticket doesn't exist.`);
|
||||
|
||||
if (!isEditable && !isRoleAdvanced)
|
||||
if (!isEditable && !isRoleAdvanced && !isProductionReviewer && !isOwner)
|
||||
throw new ForbiddenError(`This ticket is not editable.`);
|
||||
|
||||
if (isLocked && !isWeekly)
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
const {models} = require('vn-loopback/server/server');
|
||||
const LoopBackContext = require('loopback-context');
|
||||
|
||||
describe('Ticket addSaleByCode()', () => {
|
||||
const quantity = 3;
|
||||
const ticketFk = 13;
|
||||
const warehouseFk = 1;
|
||||
beforeAll(async() => {
|
||||
activeCtx = {
|
||||
req: {
|
||||
accessToken: {userId: 9},
|
||||
headers: {origin: 'http://localhost'},
|
||||
__: value => value
|
||||
}
|
||||
};
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||
active: activeCtx
|
||||
});
|
||||
});
|
||||
|
||||
it('should add a new sale', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
const code = '1111111111';
|
||||
|
||||
const salesBefore = await models.Sale.find(null, options);
|
||||
await models.Ticket.addSaleByCode(activeCtx, code, quantity, ticketFk, warehouseFk, options);
|
||||
const salesAfter = await models.Sale.find(null, options);
|
||||
|
||||
expect(salesAfter.length).toEqual(salesBefore.length + 1);
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
|
@ -68,7 +68,7 @@ describe('ticket filter()', () => {
|
|||
const filter = {};
|
||||
const result = await models.Ticket.filter(ctx, filter, options);
|
||||
|
||||
expect(result.length).toEqual(7);
|
||||
expect(result.length).toEqual(10);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
|
|
|
@ -42,7 +42,7 @@ describe('sale priceDifference()', () => {
|
|||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const ctx = {req: {accessToken: {userId: 1106}}};
|
||||
const ctx = {req: {accessToken: {userId: 1105}}};
|
||||
ctx.args = {
|
||||
id: 1,
|
||||
landed: Date.vnNew(),
|
||||
|
@ -84,7 +84,7 @@ describe('sale priceDifference()', () => {
|
|||
|
||||
const {items} = await models.Ticket.priceDifference(ctx, options);
|
||||
|
||||
expect(items[0].movable).toEqual(410);
|
||||
expect(items[0].movable).toEqual(386);
|
||||
expect(items[1].movable).toEqual(1810);
|
||||
|
||||
await tx.rollback();
|
||||
|
|
|
@ -7,6 +7,7 @@ describe('ticket state()', () => {
|
|||
const productionId = 49;
|
||||
const activeCtx = {
|
||||
accessToken: {userId: 9},
|
||||
__: value => value
|
||||
};
|
||||
const ctx = {req: activeCtx};
|
||||
const now = Date.vnNew();
|
||||
|
@ -88,7 +89,8 @@ describe('ticket state()', () => {
|
|||
const ticket = await models.Ticket.create(sampleTicket, options);
|
||||
|
||||
activeCtx.accessToken.userId = productionId;
|
||||
const params = {ticketFk: ticket.id, stateFk: 3};
|
||||
const stateOk = await models.State.findOne({where: {code: 'OK'}}, options);
|
||||
const params = {ticketFk: ticket.id, stateFk: stateOk.id};
|
||||
|
||||
const ticketTracking = await models.Ticket.state(ctx, params, options);
|
||||
|
||||
|
@ -112,16 +114,68 @@ describe('ticket state()', () => {
|
|||
const options = {transaction: tx};
|
||||
|
||||
const ticket = await models.Ticket.create(sampleTicket, options);
|
||||
const ctx = {req: {accessToken: {userId: 18}}};
|
||||
activeCtx.accessToken.userId = salesPersonId;
|
||||
const assignedState = await models.State.findOne({where: {code: 'PICKER_DESIGNED'}}, options);
|
||||
const params = {ticketFk: ticket.id, stateFk: assignedState.id, userFk: 1};
|
||||
const res = await models.Ticket.state(ctx, params, options);
|
||||
const paramsAssigned = {ticketFk: ticket.id, stateFk: assignedState.id, userFk: 1};
|
||||
const resAssigned = await models.Ticket.state(ctx, paramsAssigned, options);
|
||||
|
||||
expect(res.ticketFk).toBe(params.ticketFk);
|
||||
expect(res.stateFk).toBe(params.stateFk);
|
||||
expect(res.userFk).toBe(params.userFk);
|
||||
expect(res.userFk).toBe(1);
|
||||
expect(res.id).toBeDefined();
|
||||
expect(resAssigned.ticketFk).toBe(paramsAssigned.ticketFk);
|
||||
expect(resAssigned.stateFk).toBe(paramsAssigned.stateFk);
|
||||
expect(resAssigned.userFk).toBe(paramsAssigned.userFk);
|
||||
expect(resAssigned.userFk).toBe(1);
|
||||
expect(resAssigned.id).toBeDefined();
|
||||
|
||||
activeCtx.accessToken.userId = productionId;
|
||||
const packedState = await models.State.findOne({where: {code: 'PACKED'}}, options);
|
||||
const paramsPacked = {ticketFk: ticket.id, stateFk: packedState.id, userFk: salesPersonId};
|
||||
const resPacked = await models.Ticket.state(ctx, paramsPacked, options);
|
||||
|
||||
expect(resPacked.stateFk).toBe(paramsPacked.stateFk);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('Should equalize the quantities of quantity and originalQuantity' +
|
||||
' if they are different', async() => {
|
||||
const tx = await models.TicketTracking.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const ticket = await models.Ticket.create(sampleTicket, options);
|
||||
activeCtx.accessToken.userId = salesPersonId;
|
||||
|
||||
const sampleSale = {
|
||||
ticketFk: ticket.id,
|
||||
itemFk: 1,
|
||||
concept: 'Test',
|
||||
quantity: 10,
|
||||
originalQuantity: 6
|
||||
};
|
||||
await models.Sale.create(sampleSale, options);
|
||||
const assignedState = await models.State.findOne({where: {code: 'PICKER_DESIGNED'}}, options);
|
||||
const paramsAssigned = {ticketFk: ticket.id, stateFk: assignedState.id, userFk: 1};
|
||||
const resAssigned = await models.Ticket.state(ctx, paramsAssigned, options);
|
||||
|
||||
expect(resAssigned.ticketFk).toBe(paramsAssigned.ticketFk);
|
||||
expect(resAssigned.stateFk).toBe(paramsAssigned.stateFk);
|
||||
expect(resAssigned.userFk).toBe(paramsAssigned.userFk);
|
||||
expect(resAssigned.userFk).toBe(1);
|
||||
expect(resAssigned.id).toBeDefined();
|
||||
|
||||
activeCtx.accessToken.userId = productionId;
|
||||
const packedState = await models.State.findOne({where: {code: 'PACKED'}}, options);
|
||||
const paramsPacked = {ticketFk: ticket.id, stateFk: packedState.id, userFk: salesPersonId};
|
||||
const resPacked = await models.Ticket.state(ctx, paramsPacked, options);
|
||||
|
||||
const sale = await models.Sale.findOne({where: {ticketFk: ticket.id}}, options);
|
||||
|
||||
expect(resPacked.stateFk).toBe(paramsPacked.stateFk);
|
||||
expect(sale.quantity).toBe(sale.originalQuantity);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
|
|
|
@ -64,7 +64,63 @@ module.exports = Self => {
|
|||
if ((ticketState && !oldStateAllowed) || !newStateAllowed)
|
||||
throw new UserError(`You don't have enough privileges`, 'ACCESS_DENIED');
|
||||
|
||||
await Self.rawSql(`CALL vn.ticket_setState(?, ?)`, [params.ticketFk, params.code], myOptions);
|
||||
const ticket = await models.Ticket.findById(params.ticketFk, {
|
||||
include: [{
|
||||
relation: 'client',
|
||||
scope: {
|
||||
fields: ['salesPersonFk']
|
||||
}
|
||||
}],
|
||||
fields: ['id', 'clientFk']
|
||||
}, myOptions);
|
||||
|
||||
const salesPersonFk = ticket.client().salesPersonFk;
|
||||
if (salesPersonFk) {
|
||||
const sales = await Self.rawSql(`
|
||||
SELECT DISTINCT s.id,
|
||||
s.itemFk,
|
||||
s.concept,
|
||||
s.originalQuantity AS oldQuantity,
|
||||
s.quantity AS newQuantity
|
||||
FROM vn.sale s
|
||||
JOIN vn.saleTracking st ON st.saleFk = s.id
|
||||
JOIN vn.ticket t ON t.id = s.ticketFk
|
||||
JOIN vn.client c ON c.id = t.clientFk
|
||||
JOIN vn.ticketState ts ON ts.ticketFk = t.id
|
||||
JOIN vn.state s2 ON s2.id = ts.stateFk
|
||||
WHERE s.ticketFk = ?
|
||||
AND st.isChecked
|
||||
AND s.originalQuantity IS NOT NULL
|
||||
AND s.originalQuantity <> s.quantity
|
||||
AND s2.\`order\` < (SELECT \`order\` FROM vn.state WHERE code = 'CHECKED')
|
||||
ORDER BY st.created DESC
|
||||
`, [params.ticketFk], myOptions);
|
||||
|
||||
let changes = '';
|
||||
const url = await models.Url.getUrl();
|
||||
const $t = ctx.req.__;
|
||||
for (let sale of sales) {
|
||||
changes += `\r\n-` + $t('Changes in sales', {
|
||||
itemId: sale.itemFk,
|
||||
concept: sale.concept,
|
||||
oldQuantity: sale.oldQuantity,
|
||||
newQuantity: sale.newQuantity,
|
||||
itemUrl: `${url}item/${sale.itemFk}/summary`
|
||||
});
|
||||
const currentSale = await models.Sale.findById(sale.id, null, myOptions);
|
||||
await currentSale.updateAttributes({
|
||||
originalQuantity: currentSale.quantity
|
||||
}, myOptions);
|
||||
}
|
||||
|
||||
const message = $t('Changed sale quantity', {
|
||||
ticketId: ticket.id,
|
||||
changes: changes,
|
||||
ticketUrl: `${url}ticket/${ticket.id}/sale`
|
||||
});
|
||||
await models.Chat.sendCheckingPresence(ctx, salesPersonFk, message, myOptions);
|
||||
}
|
||||
await Self.rawSql(`CALL vn.ticket_setState(?, ?)`, [ticket.id, params.code], myOptions);
|
||||
|
||||
const ticketTracking = await models.TicketTracking.findOne({
|
||||
where: {ticketFk: params.ticketFk},
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
},
|
||||
"parkingFk": {
|
||||
"type": "number"
|
||||
},
|
||||
"ticketFk": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
|
|
|
@ -1,361 +1,318 @@
|
|||
/* eslint max-len: ["error", { "code": 150 }]*/
|
||||
|
||||
const models = require('vn-loopback/server/server').models;
|
||||
const {models} = require('vn-loopback/server/server');
|
||||
const LoopBackContext = require('loopback-context');
|
||||
|
||||
describe('sale model ', () => {
|
||||
const ctx = {
|
||||
req: {
|
||||
accessToken: {userId: 9},
|
||||
headers: {origin: 'localhost:5000'},
|
||||
__: () => {}
|
||||
}
|
||||
};
|
||||
function getActiveCtx(userId) {
|
||||
return {
|
||||
active: {
|
||||
accessToken: {userId},
|
||||
http: {
|
||||
req: {
|
||||
headers: {origin: 'http://localhost'}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
const developerId = 9;
|
||||
const buyerId = 35;
|
||||
const employeeId = 1;
|
||||
const productionId = 49;
|
||||
const salesPersonId = 18;
|
||||
const reviewerId = 130;
|
||||
|
||||
const barcode = '4444444444';
|
||||
const ticketCollectionProd = 34;
|
||||
const ticketCollectionSalesPerson = 35;
|
||||
const previaTicketSalesPerson = 36;
|
||||
const previaTicketProd = 37;
|
||||
const notEditableError = 'This ticket is not editable.';
|
||||
|
||||
const ctx = getCtx(developerId);
|
||||
let tx;
|
||||
let opts;
|
||||
|
||||
function getCtx(userId, active = false) {
|
||||
const accessToken = {userId};
|
||||
const headers = {origin: 'localhost:5000'};
|
||||
if (!active) return {req: {accessToken, headers, __: () => {}}};
|
||||
return {active: {accessToken, http: {req: {headers}}}};
|
||||
}
|
||||
|
||||
beforeEach(async() => {
|
||||
tx = await models.Sale.beginTransaction({});
|
||||
opts = {transaction: tx};
|
||||
});
|
||||
|
||||
afterEach(async() => await tx.rollback());
|
||||
|
||||
describe('quantity field ', () => {
|
||||
it('should add quantity if the quantity is greater than it should be and is role advanced', async() => {
|
||||
const saleId = 17;
|
||||
const buyerId = 35;
|
||||
const ctx = {
|
||||
req: {
|
||||
accessToken: {userId: buyerId},
|
||||
headers: {origin: 'localhost:5000'},
|
||||
__: () => {}
|
||||
}
|
||||
};
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getActiveCtx(buyerId));
|
||||
spyOn(models.Sale, 'rawSql').and.callFake((sqlStatement, params, options) => {
|
||||
const ctx = getCtx(buyerId);
|
||||
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(buyerId, true));
|
||||
spyOn(models.Sale, 'rawSql').and.callFake((sqlStatement, params, opts) => {
|
||||
if (sqlStatement.includes('catalog_calcFromItem')) {
|
||||
sqlStatement = `CREATE OR REPLACE TEMPORARY TABLE tmp.ticketCalculateItem ENGINE = MEMORY
|
||||
SELECT 100 as available;`;
|
||||
params = null;
|
||||
}
|
||||
return models.Ticket.rawSql(sqlStatement, params, options);
|
||||
return models.Ticket.rawSql(sqlStatement, params, opts);
|
||||
});
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const isRoleAdvanced = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'isRoleAdvanced', '*');
|
||||
|
||||
expect(isRoleAdvanced).toEqual(true);
|
||||
|
||||
const originalLine = await models.Sale.findOne({where: {id: saleId}, fields: ['quantity']}, options);
|
||||
const originalLine = await models.Sale.findOne({where: {id: saleId}, fields: ['quantity']}, opts);
|
||||
|
||||
expect(originalLine.quantity).toEqual(30);
|
||||
|
||||
const newQuantity = originalLine.quantity + 1;
|
||||
await models.Sale.updateQuantity(ctx, saleId, newQuantity, options);
|
||||
await models.Sale.updateQuantity(ctx, saleId, newQuantity, opts);
|
||||
|
||||
const modifiedLine = await models.Sale.findOne({where: {id: saleId}, fields: ['quantity']}, options);
|
||||
const modifiedLine = await models.Sale.findOne({where: {id: saleId}, fields: ['quantity']}, opts);
|
||||
|
||||
expect(modifiedLine.quantity).toEqual(newQuantity);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should update the quantity of a given sale current line', async() => {
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getActiveCtx(9));
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(developerId, true));
|
||||
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
const saleId = 25;
|
||||
const newQuantity = 4;
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const originalLine = await models.Sale.findOne({where: {id: saleId}, fields: ['quantity']}, options);
|
||||
const originalLine = await models.Sale.findOne({where: {id: saleId}, fields: ['quantity']}, opts);
|
||||
|
||||
expect(originalLine.quantity).toEqual(20);
|
||||
|
||||
await models.Sale.updateQuantity(ctx, saleId, newQuantity, options);
|
||||
await models.Sale.updateQuantity(ctx, saleId, newQuantity, opts);
|
||||
|
||||
const modifiedLine = await models.Sale.findOne({where: {id: saleId}, fields: ['quantity']}, options);
|
||||
const modifiedLine = await models.Sale.findOne({where: {id: saleId}, fields: ['quantity']}, opts);
|
||||
|
||||
expect(modifiedLine.quantity).toEqual(newQuantity);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should throw an error if the quantity is negative and it is not a refund ticket', async() => {
|
||||
const ctx = {
|
||||
req: {
|
||||
accessToken: {userId: 1},
|
||||
headers: {origin: 'localhost:5000'},
|
||||
__: () => {}
|
||||
}
|
||||
};
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getActiveCtx(1));
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(employeeId, true));
|
||||
|
||||
const saleId = 17;
|
||||
const newQuantity = -10;
|
||||
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
|
||||
let error;
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
await models.Sale.updateQuantity(ctx, saleId, newQuantity, options);
|
||||
|
||||
await tx.rollback();
|
||||
await models.Sale.updateQuantity(ctx, saleId, newQuantity, opts);
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
error = e;
|
||||
expect(e).toEqual(new Error('You can only add negative amounts in refund tickets'));
|
||||
}
|
||||
|
||||
expect(error).toEqual(new Error('You can only add negative amounts in refund tickets'));
|
||||
});
|
||||
|
||||
it('should update a negative quantity when is a ticket refund', async() => {
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getActiveCtx(9));
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(developerId, true));
|
||||
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
const saleId = 32;
|
||||
const newQuantity = -10;
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
await models.Sale.updateQuantity(ctx, saleId, newQuantity, opts);
|
||||
|
||||
await models.Sale.updateQuantity(ctx, saleId, newQuantity, options);
|
||||
|
||||
const modifiedLine = await models.Sale.findOne({where: {id: saleId}, fields: ['quantity']}, options);
|
||||
const modifiedLine = await models.Sale.findOne({where: {id: saleId}, fields: ['quantity']}, opts);
|
||||
|
||||
expect(modifiedLine.quantity).toEqual(newQuantity);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should throw an error if the quantity is less than the minimum quantity of the item', async() => {
|
||||
const ctx = {
|
||||
req: {
|
||||
accessToken: {userId: 1},
|
||||
headers: {origin: 'localhost:5000'},
|
||||
__: () => {}
|
||||
}
|
||||
};
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getActiveCtx(1));
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(employeeId, true));
|
||||
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
const itemId = 2;
|
||||
const saleId = 17;
|
||||
const minQuantity = 30;
|
||||
const newQuantity = minQuantity - 1;
|
||||
|
||||
let error;
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const item = await models.Item.findById(itemId, null, options);
|
||||
await item.updateAttribute('minQuantity', minQuantity, options);
|
||||
spyOn(models.Sale, 'rawSql').and.callFake((sqlStatement, params, options) => {
|
||||
const item = await models.Item.findById(itemId, null, opts);
|
||||
await item.updateAttribute('minQuantity', minQuantity, opts);
|
||||
spyOn(models.Sale, 'rawSql').and.callFake((sqlStatement, params, opts) => {
|
||||
if (sqlStatement.includes('catalog_calcFromItem')) {
|
||||
sqlStatement = `CREATE OR REPLACE TEMPORARY TABLE tmp.ticketCalculateItem ENGINE = MEMORY
|
||||
SELECT 100 as available;`;
|
||||
params = null;
|
||||
}
|
||||
return models.Ticket.rawSql(sqlStatement, params, options);
|
||||
return models.Ticket.rawSql(sqlStatement, params, opts);
|
||||
});
|
||||
|
||||
await models.Sale.updateQuantity(ctx, saleId, newQuantity, options);
|
||||
|
||||
await tx.rollback();
|
||||
await models.Sale.updateQuantity(ctx, saleId, newQuantity, opts);
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
error = e;
|
||||
expect(e).toEqual(new Error('The amount cannot be less than the minimum'));
|
||||
}
|
||||
|
||||
expect(error).toEqual(new Error('The amount cannot be less than the minimum'));
|
||||
});
|
||||
|
||||
it('should change quantity if has minimum quantity and new quantity is equal than item available', async() => {
|
||||
const ctx = {
|
||||
req: {
|
||||
accessToken: {userId: 1},
|
||||
headers: {origin: 'localhost:5000'},
|
||||
__: () => {}
|
||||
}
|
||||
};
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getActiveCtx(1));
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(employeeId, true));
|
||||
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
const itemId = 2;
|
||||
const saleId = 17;
|
||||
const minQuantity = 30;
|
||||
const newQuantity = minQuantity - 1;
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
const item = await models.Item.findById(itemId, null, opts);
|
||||
await item.updateAttribute('minQuantity', minQuantity, opts);
|
||||
|
||||
const item = await models.Item.findById(itemId, null, options);
|
||||
await item.updateAttribute('minQuantity', minQuantity, options);
|
||||
|
||||
spyOn(models.Sale, 'rawSql').and.callFake((sqlStatement, params, options) => {
|
||||
spyOn(models.Sale, 'rawSql').and.callFake((sqlStatement, params, opts) => {
|
||||
if (sqlStatement.includes('catalog_calcFromItem')) {
|
||||
sqlStatement = `CREATE OR REPLACE TEMPORARY TABLE tmp.ticketCalculateItem ENGINE = MEMORY
|
||||
SELECT ${newQuantity} as available;`;
|
||||
params = null;
|
||||
}
|
||||
return models.Ticket.rawSql(sqlStatement, params, options);
|
||||
return models.Ticket.rawSql(sqlStatement, params, opts);
|
||||
});
|
||||
|
||||
await models.Sale.updateQuantity(ctx, saleId, newQuantity, options);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
await models.Sale.updateQuantity(ctx, saleId, newQuantity, opts);
|
||||
});
|
||||
|
||||
describe('newPrice', () => {
|
||||
it('should increase quantity if you have enough available and the new price is the same as the previous one', async() => {
|
||||
const ctx = {
|
||||
req: {
|
||||
accessToken: {userId: 1},
|
||||
headers: {origin: 'localhost:5000'},
|
||||
__: () => {}
|
||||
}
|
||||
};
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getActiveCtx(1));
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(employeeId, true));
|
||||
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
const itemId = 2;
|
||||
const saleId = 17;
|
||||
const minQuantity = 30;
|
||||
const newQuantity = 31;
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const item = await models.Item.findById(itemId, null, options);
|
||||
await item.updateAttribute('minQuantity', minQuantity, options);
|
||||
spyOn(models.Sale, 'rawSql').and.callFake((sqlStatement, params, options) => {
|
||||
const item = await models.Item.findById(itemId, null, opts);
|
||||
await item.updateAttribute('minQuantity', minQuantity, opts);
|
||||
spyOn(models.Sale, 'rawSql').and.callFake((sqlStatement, params, opts) => {
|
||||
if (sqlStatement.includes('catalog_calcFromItem')) {
|
||||
sqlStatement = `
|
||||
CREATE OR REPLACE TEMPORARY TABLE tmp.ticketCalculateItem ENGINE = MEMORY SELECT ${newQuantity} as available;
|
||||
CREATE OR REPLACE TEMPORARY TABLE tmp.ticketComponentPrice ENGINE = MEMORY SELECT 1 as grouping, 7.07 as price;`;
|
||||
params = null;
|
||||
}
|
||||
return models.Ticket.rawSql(sqlStatement, params, options);
|
||||
return models.Ticket.rawSql(sqlStatement, params, opts);
|
||||
});
|
||||
|
||||
await models.Sale.updateQuantity(ctx, saleId, newQuantity, options);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
await models.Sale.updateQuantity(ctx, saleId, newQuantity, opts);
|
||||
});
|
||||
|
||||
it('should increase quantity when the new price is lower than the previous one', async() => {
|
||||
const ctx = {
|
||||
req: {
|
||||
accessToken: {userId: 1},
|
||||
headers: {origin: 'localhost:5000'},
|
||||
__: () => {}
|
||||
}
|
||||
};
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getActiveCtx(1));
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(employeeId, true));
|
||||
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
const itemId = 2;
|
||||
const saleId = 17;
|
||||
const minQuantity = 30;
|
||||
const newQuantity = 31;
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const item = await models.Item.findById(itemId, null, options);
|
||||
await item.updateAttribute('minQuantity', minQuantity, options);
|
||||
spyOn(models.Sale, 'rawSql').and.callFake((sqlStatement, params, options) => {
|
||||
const item = await models.Item.findById(itemId, null, opts);
|
||||
await item.updateAttribute('minQuantity', minQuantity, opts);
|
||||
spyOn(models.Sale, 'rawSql').and.callFake((sqlStatement, params, opts) => {
|
||||
if (sqlStatement.includes('catalog_calcFromItem')) {
|
||||
sqlStatement = `
|
||||
CREATE OR REPLACE TEMPORARY TABLE tmp.ticketCalculateItem ENGINE = MEMORY SELECT ${newQuantity} as available;
|
||||
CREATE OR REPLACE TEMPORARY TABLE tmp.ticketComponentPrice ENGINE = MEMORY SELECT 1 as grouping, 1 as price;`;
|
||||
params = null;
|
||||
}
|
||||
return models.Ticket.rawSql(sqlStatement, params, options);
|
||||
return models.Ticket.rawSql(sqlStatement, params, opts);
|
||||
});
|
||||
|
||||
await models.Sale.updateQuantity(ctx, saleId, newQuantity, options);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
await models.Sale.updateQuantity(ctx, saleId, newQuantity, opts);
|
||||
});
|
||||
|
||||
it('should throw error when increase quantity and the new price is higher than the previous one', async() => {
|
||||
const ctx = {
|
||||
req: {
|
||||
accessToken: {userId: 1},
|
||||
headers: {origin: 'localhost:5000'},
|
||||
__: () => {}
|
||||
}
|
||||
};
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getActiveCtx(1));
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(employeeId, true));
|
||||
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
const itemId = 2;
|
||||
const saleId = 17;
|
||||
const minQuantity = 30;
|
||||
const newQuantity = 31;
|
||||
|
||||
let error;
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const item = await models.Item.findById(itemId, null, options);
|
||||
await item.updateAttribute('minQuantity', minQuantity, options);
|
||||
spyOn(models.Sale, 'rawSql').and.callFake((sqlStatement, params, options) => {
|
||||
const item = await models.Item.findById(itemId, null, opts);
|
||||
await item.updateAttribute('minQuantity', minQuantity, opts);
|
||||
spyOn(models.Sale, 'rawSql').and.callFake((sqlStatement, params, opts) => {
|
||||
if (sqlStatement.includes('catalog_calcFromItem')) {
|
||||
sqlStatement = `
|
||||
CREATE OR REPLACE TEMPORARY TABLE tmp.ticketCalculateItem ENGINE = MEMORY SELECT ${newQuantity} as available;
|
||||
CREATE OR REPLACE TEMPORARY TABLE tmp.ticketComponentPrice ENGINE = MEMORY SELECT 1 as grouping, 100000 as price;`;
|
||||
params = null;
|
||||
}
|
||||
return models.Ticket.rawSql(sqlStatement, params, options);
|
||||
return models.Ticket.rawSql(sqlStatement, params, opts);
|
||||
});
|
||||
|
||||
await models.Sale.updateQuantity(ctx, saleId, newQuantity, options);
|
||||
|
||||
await tx.rollback();
|
||||
await models.Sale.updateQuantity(ctx, saleId, newQuantity, opts);
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
error = e;
|
||||
expect(e).toEqual(new Error('The price of the item changed'));
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('add a sale from a collection or previa ticket', () => {
|
||||
it('if is allocated to them and alert level higher than 0 as Production role', async() => {
|
||||
const ctx = getCtx(productionId);
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(productionId, true));
|
||||
|
||||
const beforeSalesCollection = await models.Sale.count({ticketFk: ticketCollectionProd}, opts);
|
||||
await models.Ticket.addSale(ctx, ticketCollectionProd, barcode, 20, opts);
|
||||
const afterSalesCollection = await models.Sale.count({ticketFk: ticketCollectionProd}, opts);
|
||||
|
||||
expect(afterSalesCollection).toEqual(beforeSalesCollection + 1);
|
||||
|
||||
const beforeSalesPrevia = await models.Sale.count({ticketFk: previaTicketProd}, opts);
|
||||
await models.Ticket.addSale(ctx, previaTicketProd, barcode, 20, opts);
|
||||
const afterSalesPrevia = await models.Sale.count({ticketFk: previaTicketProd}, opts);
|
||||
|
||||
expect(afterSalesPrevia).toEqual(beforeSalesPrevia + 1);
|
||||
});
|
||||
|
||||
it('should throw an error if is not allocated to them and alert level higher than 0 as Production role', async() => {
|
||||
const ctx = getCtx(productionId);
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(productionId, true));
|
||||
|
||||
try {
|
||||
await models.Ticket.addSale(ctx, ticketCollectionSalesPerson, barcode, 20, opts);
|
||||
} catch ({message}) {
|
||||
expect(message).toEqual(notEditableError);
|
||||
}
|
||||
|
||||
expect(error).toEqual(new Error('The price of the item changed'));
|
||||
});
|
||||
try {
|
||||
await models.Ticket.addSale(ctx, previaTicketSalesPerson, barcode, 20, opts);
|
||||
} catch ({message}) {
|
||||
expect(message).toEqual(notEditableError);
|
||||
}
|
||||
});
|
||||
|
||||
it('if is allocated to them and alert level higher than 0 as salesPerson role', async() => {
|
||||
const ctx = getCtx(salesPersonId);
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(salesPersonId, true));
|
||||
|
||||
const beforeSalesCollection = await models.Sale.count({ticketFk: ticketCollectionSalesPerson}, opts);
|
||||
await models.Ticket.addSale(ctx, ticketCollectionSalesPerson, barcode, 20, opts);
|
||||
const afterSalesCollection = await models.Sale.count({ticketFk: ticketCollectionSalesPerson}, opts);
|
||||
|
||||
expect(afterSalesCollection).toEqual(beforeSalesCollection + 1);
|
||||
|
||||
const beforeSalesPrevia = await models.Sale.count({ticketFk: previaTicketSalesPerson}, opts);
|
||||
await models.Ticket.addSale(ctx, previaTicketSalesPerson, barcode, 20, opts);
|
||||
const afterSalesPrevia = await models.Sale.count({ticketFk: previaTicketSalesPerson}, opts);
|
||||
|
||||
expect(afterSalesPrevia).toEqual(beforeSalesPrevia + 1);
|
||||
});
|
||||
|
||||
it('should throw an error if is not allocated to them and alert level higher than 0 as salesPerson role', async() => {
|
||||
const ctx = getCtx(salesPersonId);
|
||||
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(salesPersonId, true));
|
||||
|
||||
try {
|
||||
await models.Ticket.addSale(ctx, ticketCollectionProd, barcode, 20, opts);
|
||||
} catch ({message}) {
|
||||
expect(message).toEqual(notEditableError);
|
||||
}
|
||||
});
|
||||
|
||||
it('if is a reviewer', async() => {
|
||||
const ctx = getCtx(reviewerId);
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(reviewerId, true));
|
||||
|
||||
const beforeSalesCollection = await models.Sale.count({ticketFk: ticketCollectionSalesPerson}, opts);
|
||||
await models.Ticket.addSale(ctx, ticketCollectionSalesPerson, barcode, 20, opts);
|
||||
const afterSalesCollection = await models.Sale.count({ticketFk: ticketCollectionSalesPerson}, opts);
|
||||
|
||||
expect(afterSalesCollection).toEqual(beforeSalesCollection + 1);
|
||||
|
||||
const beforeSalesPrevia = await models.Sale.count({ticketFk: previaTicketSalesPerson}, opts);
|
||||
await models.Ticket.addSale(ctx, previaTicketSalesPerson, barcode, 20, opts);
|
||||
const afterSalesPrevia = await models.Sale.count({ticketFk: previaTicketSalesPerson}, opts);
|
||||
|
||||
expect(afterSalesPrevia).toEqual(beforeSalesPrevia + 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -46,6 +46,5 @@ module.exports = function(Self) {
|
|||
require('../methods/ticket/invoiceTicketsAndPdf')(Self);
|
||||
require('../methods/ticket/docuwareDownload')(Self);
|
||||
require('../methods/ticket/myLastModified')(Self);
|
||||
require('../methods/ticket/addSaleByCode')(Self);
|
||||
require('../methods/ticket/clone')(Self);
|
||||
};
|
||||
|
|
|
@ -476,7 +476,7 @@ class Controller extends Section {
|
|||
*/
|
||||
addSale(sale) {
|
||||
const data = {
|
||||
itemId: sale.itemFk,
|
||||
barcode: sale.itemFk,
|
||||
quantity: sale.quantity
|
||||
};
|
||||
const query = `tickets/${this.ticket.id}/addSale`;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue