Compare commits
71 Commits
4a73bd0133
...
b480df069d
Author | SHA1 | Date |
---|---|---|
Juanjo Breso | b480df069d | |
Javi Gallego | ebf80a4eb9 | |
Javi Gallego | 147721642b | |
Javi Gallego | 0b12576d2f | |
Javi Gallego | 980f2e61b1 | |
Juan Ferrer | 33c96df0b1 | |
Javi Gallego | 5c9589ba7b | |
Juan Ferrer | cfcfa489b4 | |
Juan Ferrer | 0ae1d6c546 | |
Juan Ferrer | 43c245b45b | |
Jorge Penadés | b5ad85dbb5 | |
Jorge Penadés | 99fbb95669 | |
Jorge Penadés | 13021180e1 | |
Jorge Penadés | 9ee01e2bc2 | |
Jorge Penadés | 86d839ad45 | |
Jorge Penadés | ef5401aa46 | |
Carlos Satorres | 810df2ab95 | |
Jorge Penadés | 0c356938fc | |
Alex Moreno | fdd4947401 | |
Carlos Satorres | c16be228e3 | |
Jorge Penadés | ebd51c4d23 | |
Jorge Penadés | 4164fd8250 | |
Juan Ferrer | fd7e16522f | |
Juan Ferrer | f2071d39ec | |
Juan Ferrer | 766008ce1a | |
Juan Ferrer | 9cda07bc5a | |
Juan Ferrer | d78c8aef40 | |
Juan Ferrer | 0669a3db28 | |
Juan Ferrer | 1c538d58c2 | |
Juan Ferrer | 2994a303b9 | |
Juan Ferrer | 9b3112df2a | |
Carlos Satorres | 855b590918 | |
Juan Ferrer | af536412bf | |
Juan Ferrer | 4eb53614bc | |
Jorge Penadés | ab9ceaf100 | |
Jorge Penadés | fb0b0450c6 | |
Alex Moreno | 9ac0ffb85a | |
Jorge Penadés | 7d01449518 | |
Jorge Penadés | a20effc42c | |
Javi Gallego | fd98348a4d | |
Carlos Satorres | 91c3c8f04d | |
Jorge Penadés | bb91035b77 | |
Jorge Penadés | cfe7fa0790 | |
Jorge Penadés | a2e076e94f | |
Jorge Penadés | f6f6fc575d | |
Jorge Penadés | 3e9dd8b3a0 | |
Jorge Penadés | 51e33887a0 | |
Jorge Penadés | 4490dc7bee | |
Jorge Penadés | 2c9c2df362 | |
Jorge Penadés | af4af43d9f | |
Alex Moreno | 467879bdd6 | |
Carlos Satorres | 3a9c5c90d4 | |
Jorge Penadés | 7b14763f45 | |
Jorge Penadés | e88abe7b7c | |
Carlos Satorres | bbf50995c7 | |
Jorge Penadés | be3e7bb8df | |
Jorge Penadés | 6f306ad18c | |
Jorge Penadés | e6eac54709 | |
Jorge Penadés | c136395d1e | |
Jorge Penadés | d43976192a | |
Javi Gallego | a5e5a0d45d | |
Jorge Penadés | 9e12bdf4e8 | |
Alex Moreno | 141c3d6f6e | |
Carlos Satorres | a6ea4ed048 | |
Carlos Satorres | 5d2f3d1a4b | |
Carlos Satorres | 509d5cea14 | |
Carlos Satorres | 9b8c58ba7d | |
Jorge Penadés | 4fc780967f | |
Jorge Penadés | e5d466b697 | |
Jorge Penadés | ed77347fe1 | |
Javi Gallego | 540c76005e |
10
Dockerfile
10
Dockerfile
|
@ -13,7 +13,7 @@ RUN apt-get update \
|
|||
graphicsmagick \
|
||||
&& curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
|
||||
&& apt-get install -y --no-install-recommends nodejs \
|
||||
&& npm install -g npm@9.6.6
|
||||
&& corepack enable pnpm
|
||||
|
||||
# Puppeteer
|
||||
|
||||
|
@ -39,12 +39,12 @@ RUN apt-get update \
|
|||
|
||||
WORKDIR /salix
|
||||
|
||||
COPY print/package.json print/package-lock.json print/
|
||||
RUN npm ci --no-audit --prefer-offline --omit=dev --prefix=print
|
||||
COPY print/package.json print/pnpm-lock.yaml print/
|
||||
RUN pnpm install --prod --prefix=print
|
||||
|
||||
COPY package.json package-lock.json ./
|
||||
COPY package.json pnpm-lock.yaml ./
|
||||
COPY loopback/package.json loopback/
|
||||
RUN npm ci --no-audit --prefer-offline --omit=dev
|
||||
RUN pnpm install --prod
|
||||
|
||||
COPY loopback loopback
|
||||
COPY back back
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
def PROTECTED_BRANCH
|
||||
def FROM_GIT
|
||||
def RUN_TESTS
|
||||
def RUN_BUILD
|
||||
|
||||
pre: {
|
||||
switch (env.BRANCH_NAME) {
|
||||
|
@ -27,6 +28,7 @@ pre: {
|
|||
|
||||
FROM_GIT = env.JOB_NAME.startsWith('gitea/')
|
||||
RUN_TESTS = !PROTECTED_BRANCH && FROM_GIT
|
||||
RUN_BUILD = PROTECTED_BRANCH && FROM_GIT
|
||||
|
||||
// Uncomment to enable debugging
|
||||
// https://loopback.io/doc/en/lb3/Setting-debug-strings.html#debug-strings-reference
|
||||
|
@ -44,33 +46,22 @@ pipeline {
|
|||
PROJECT_NAME = 'salix'
|
||||
STACK_NAME = "${env.PROJECT_NAME}-${env.BRANCH_NAME}"
|
||||
}
|
||||
stages {
|
||||
stage('Stack') {
|
||||
environment {
|
||||
NODE_ENV = ""
|
||||
TZ = 'Europe/Madrid'
|
||||
}
|
||||
parallel {
|
||||
stage('Back') {
|
||||
stages {
|
||||
stage('Install') {
|
||||
environment {
|
||||
NODE_ENV = ""
|
||||
}
|
||||
parallel {
|
||||
stage('Backend') {
|
||||
steps {
|
||||
sh 'npm install --no-audit --prefer-offline'
|
||||
}
|
||||
}
|
||||
stage('Frontend') {
|
||||
when {
|
||||
expression { FROM_GIT }
|
||||
}
|
||||
steps {
|
||||
sh 'npm install --no-audit --prefer-offline --prefix=front'
|
||||
}
|
||||
}
|
||||
stage('Print') {
|
||||
when {
|
||||
expression { FROM_GIT }
|
||||
}
|
||||
steps {
|
||||
sh 'npm install --no-audit --prefer-offline --prefix=print'
|
||||
}
|
||||
}
|
||||
sh 'pnpm install --prefer-offline'
|
||||
sh 'pnpm install --prefer-offline --prefix=print'
|
||||
}
|
||||
}
|
||||
stage('Test') {
|
||||
|
@ -79,24 +70,81 @@ pipeline {
|
|||
}
|
||||
environment {
|
||||
NODE_ENV = ""
|
||||
TZ = 'Europe/Madrid'
|
||||
}
|
||||
parallel {
|
||||
stage('Backend') {
|
||||
steps {
|
||||
sh 'npm run test:back:ci'
|
||||
}
|
||||
post {
|
||||
always {
|
||||
script {
|
||||
try {
|
||||
junit 'junitresults.xml'
|
||||
junit 'junit.xml'
|
||||
} catch (e) {
|
||||
echo e.toString()
|
||||
}
|
||||
stage('Frontend') {
|
||||
steps {
|
||||
sh 'jest --ci --reporters=default --reporters=jest-junit --maxWorkers=6'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Build') {
|
||||
when {
|
||||
expression { PROTECTED_BRANCH && FROM_GIT }
|
||||
expression { RUN_BUILD }
|
||||
}
|
||||
steps {
|
||||
script {
|
||||
def packageJson = readJSON file: 'package.json'
|
||||
env.VERSION = packageJson.version
|
||||
}
|
||||
sh 'docker-compose build back'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Front') {
|
||||
when {
|
||||
expression { FROM_GIT }
|
||||
}
|
||||
stages {
|
||||
stage('Install') {
|
||||
environment {
|
||||
NODE_ENV = ""
|
||||
}
|
||||
steps {
|
||||
sh 'pnpm install --prefer-offline --prefix=front'
|
||||
}
|
||||
}
|
||||
stage('Test') {
|
||||
when {
|
||||
expression { RUN_TESTS }
|
||||
}
|
||||
environment {
|
||||
NODE_ENV = ""
|
||||
}
|
||||
steps {
|
||||
sh 'jest --ci --reporters=default --reporters=jest-junit --maxWorkers=10'
|
||||
}
|
||||
}
|
||||
stage('Build') {
|
||||
when {
|
||||
expression { RUN_BUILD }
|
||||
}
|
||||
steps {
|
||||
script {
|
||||
def packageJson = readJSON file: 'package.json'
|
||||
env.VERSION = packageJson.version
|
||||
}
|
||||
sh 'gulp build'
|
||||
sh 'docker-compose build front'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Push') {
|
||||
when {
|
||||
expression { RUN_BUILD }
|
||||
}
|
||||
environment {
|
||||
CREDENTIALS = credentials('docker-registry')
|
||||
|
@ -106,8 +154,8 @@ pipeline {
|
|||
def packageJson = readJSON file: 'package.json'
|
||||
env.VERSION = packageJson.version
|
||||
}
|
||||
sh 'gulp build'
|
||||
dockerBuild()
|
||||
sh 'docker login --username $CREDENTIALS_USR --password $CREDENTIALS_PSW $REGISTRY'
|
||||
sh 'docker-compose push'
|
||||
}
|
||||
}
|
||||
stage('Deploy') {
|
||||
|
@ -147,18 +195,6 @@ pipeline {
|
|||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
script {
|
||||
if (RUN_TESTS) {
|
||||
try {
|
||||
junit 'junitresults.xml'
|
||||
junit 'junit.xml'
|
||||
} catch (e) {
|
||||
echo e.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
success {
|
||||
script {
|
||||
if (env.BRANCH_NAME == 'master' && FROM_GIT) {
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/* eslint-disable no-console */
|
||||
const app = require('vn-loopback/server/server');
|
||||
let dataSources = require('../loopback/server/datasources.json');
|
||||
|
||||
async function init() {
|
||||
console.log('Initializing backend.');
|
||||
|
||||
dataSources = JSON.parse(JSON.stringify(dataSources));
|
||||
Object.assign(dataSources.vn, {
|
||||
host: process.env.DB_HOST,
|
||||
port: process.env.DB_PORT
|
||||
});
|
||||
|
||||
const bootOptions = {dataSources};
|
||||
await new Promise((resolve, reject) => {
|
||||
app.boot(bootOptions,
|
||||
err => err ? reject(err) : resolve());
|
||||
});
|
||||
// FIXME: Workaround to wait for loopback to be ready
|
||||
await app.models.Application.status();
|
||||
}
|
||||
|
||||
async function deinit() {
|
||||
console.log('Stopping backend.');
|
||||
await app.disconnect();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init,
|
||||
deinit
|
||||
};
|
||||
|
||||
if (require.main === module)
|
||||
init();
|
116
back/tests.js
116
back/tests.js
|
@ -2,30 +2,21 @@
|
|||
const path = require('path');
|
||||
const Myt = require('@verdnatura/myt/myt');
|
||||
const Run = require('@verdnatura/myt/myt-run');
|
||||
let dataSources = require('../loopback/server/datasources.json');
|
||||
const helper = require('./tests-helper');
|
||||
|
||||
let server;
|
||||
const isCI = process.argv[2] === 'ci';
|
||||
const PARALLEL = false;
|
||||
const TIMEOUT = 900000;
|
||||
|
||||
process.on('warning', warning => {
|
||||
console.log(warning.name);
|
||||
console.log(warning.message);
|
||||
console.log(warning.stack);
|
||||
});
|
||||
process.on('SIGINT', teardown);
|
||||
process.on('exit', teardown);
|
||||
process.on('uncaughtException', onError);
|
||||
process.on('unhandledRejection', onError);
|
||||
|
||||
process.on('SIGUSR2', rmServer);
|
||||
process.on('exit', rmServer);
|
||||
|
||||
async function rmServer() {
|
||||
if (!server) return;
|
||||
await server.rm();
|
||||
server = null;
|
||||
}
|
||||
|
||||
async function test() {
|
||||
async function setup() {
|
||||
console.log('Building and running DB container.');
|
||||
|
||||
const isCI = process.argv[2] === 'ci';
|
||||
|
||||
const myt = new Myt();
|
||||
await myt.init({
|
||||
workspace: path.join(__dirname, '..'),
|
||||
|
@ -36,32 +27,57 @@ async function test() {
|
|||
});
|
||||
server = await myt.run(Run);
|
||||
await myt.deinit();
|
||||
|
||||
const {dbConfig} = server;
|
||||
process.env.DB_HOST = dbConfig.host;
|
||||
process.env.DB_PORT = dbConfig.port;
|
||||
|
||||
console.log('Initializing backend.');
|
||||
if (!PARALLEL)
|
||||
await helper.init();
|
||||
}
|
||||
|
||||
dataSources = JSON.parse(JSON.stringify(dataSources));
|
||||
Object.assign(dataSources.vn, {
|
||||
host: dbConfig.host,
|
||||
port: dbConfig.port
|
||||
});
|
||||
async function teardown() {
|
||||
if (!server) return;
|
||||
|
||||
const bootOptions = {dataSources};
|
||||
const app = require('vn-loopback/server/server');
|
||||
await new Promise((resolve, reject) => {
|
||||
app.boot(bootOptions,
|
||||
err => err ? reject(err) : resolve());
|
||||
});
|
||||
// FIXME: Workaround to wait for loopback to be ready
|
||||
await app.models.Application.status();
|
||||
if (!PARALLEL)
|
||||
await helper.deinit();
|
||||
|
||||
console.log('Running tests.');
|
||||
console.log('Stopping and removing DB container.');
|
||||
await server.rm();
|
||||
server = null;
|
||||
}
|
||||
|
||||
async function onError(err) {
|
||||
await teardown();
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
async function test() {
|
||||
let runner;
|
||||
const config = {
|
||||
globalSetup: setup,
|
||||
globalSetupTimeout: TIMEOUT,
|
||||
globalTeardown: teardown,
|
||||
globalTeardownTimeout: TIMEOUT,
|
||||
spec_dir: '.',
|
||||
spec_files: [
|
||||
'back/**/*[sS]pec.js',
|
||||
'loopback/**/*[sS]pec.js',
|
||||
'modules/*/back/**/*.[sS]pec.js'
|
||||
],
|
||||
helpers: []
|
||||
};
|
||||
|
||||
if (PARALLEL) {
|
||||
const ParallelRunner = require('jasmine/parallel');
|
||||
runner = new ParallelRunner({numWorkers: 1});
|
||||
config.helpers.push(`back/tests-helper.js`);
|
||||
} else {
|
||||
const Jasmine = require('jasmine');
|
||||
const jasmine = new Jasmine();
|
||||
runner = new Jasmine();
|
||||
|
||||
const SpecReporter = require('jasmine-spec-reporter').SpecReporter;
|
||||
jasmine.addReporter(new SpecReporter({
|
||||
runner.addReporter(new SpecReporter({
|
||||
spec: {
|
||||
displaySuccessful: isCI,
|
||||
displayPending: isCI
|
||||
|
@ -70,35 +86,17 @@ async function test() {
|
|||
displayPending: false,
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
if (isCI) {
|
||||
const JunitReporter = require('jasmine-reporters');
|
||||
jasmine.addReporter(new JunitReporter.JUnitXmlReporter());
|
||||
|
||||
jasmine.exitOnCompletion = true;
|
||||
jasmine.jasmine.DEFAULT_TIMEOUT_INTERVAL = 900000;
|
||||
runner.addReporter(new JunitReporter.JUnitXmlReporter());
|
||||
runner.jasmine.DEFAULT_TIMEOUT_INTERVAL = TIMEOUT;
|
||||
}
|
||||
|
||||
const backSpecs = [
|
||||
'./back/**/*[sS]pec.js',
|
||||
'./loopback/**/*[sS]pec.js',
|
||||
'./modules/*/back/**/*.[sS]pec.js'
|
||||
];
|
||||
|
||||
jasmine.loadConfig({
|
||||
spec_dir: '.',
|
||||
spec_files: backSpecs,
|
||||
helpers: [],
|
||||
});
|
||||
|
||||
await jasmine.execute();
|
||||
|
||||
console.log('Stopping.');
|
||||
|
||||
if (app) await app.disconnect();
|
||||
await rmServer();
|
||||
|
||||
console.log('Tests ended.\n');
|
||||
// runner.loadConfigFile('back/jasmine.json');
|
||||
runner.loadConfig(config);
|
||||
await runner.execute();
|
||||
}
|
||||
|
||||
test();
|
||||
|
|
|
@ -5,7 +5,8 @@ proc: BEGIN
|
|||
DECLARE vReserveDate DATETIME;
|
||||
DECLARE vParams CHAR(100);
|
||||
DECLARE vInventoryDate DATE;
|
||||
DECLARE vIsLogifloraDay BOOLEAN;
|
||||
DECLARE vLifeScope DATE;
|
||||
DECLARE vWarehouseFkInventory INT;
|
||||
|
||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||
BEGIN
|
||||
|
@ -26,43 +27,42 @@ proc: BEGIN
|
|||
LEAVE proc;
|
||||
END IF;
|
||||
|
||||
-- Invoca al procedimiento que genera el stock virtual de Logiflora, si coincide con la peticion de refresco del disponible
|
||||
IF vn.isLogifloraDay(vDated, vWarehouse) THEN
|
||||
-- CALL edi.floramondo_offerRefresh;
|
||||
SET vIsLogifloraDay = TRUE;
|
||||
ELSE
|
||||
SET vIsLogifloraDay = FALSE;
|
||||
END IF;
|
||||
|
||||
-- Calcula algunos parámetros necesarios
|
||||
SET vStartDate = TIMESTAMP(vDated, '00:00:00');
|
||||
SELECT inventoried INTO vInventoryDate FROM vn.config;
|
||||
SELECT DATE_SUB(vStartDate, INTERVAL MAX(life) DAY) INTO vLifeScope FROM vn.itemType;
|
||||
SELECT SUBTIME(util.VN_NOW(), reserveTime) INTO vReserveDate
|
||||
FROM hedera.orderConfig;
|
||||
|
||||
SELECT w.id INTO vWarehouseFkInventory
|
||||
FROM vn.warehouse w
|
||||
WHERE w.code = 'inv';
|
||||
|
||||
-- Calcula el ultimo dia de vida para cada producto
|
||||
DROP TEMPORARY TABLE IF EXISTS itemRange;
|
||||
CREATE TEMPORARY TABLE itemRange
|
||||
(PRIMARY KEY (itemFk))
|
||||
ENGINE = MEMORY
|
||||
SELECT c.itemFk,
|
||||
IF(it.life IS NULL,
|
||||
NULL,
|
||||
TIMESTAMP(TIMESTAMPADD(DAY, it.life, c.landing), '23:59:59')) ended
|
||||
FROM (
|
||||
SELECT b.itemFk, MAX(t.landed) landing
|
||||
SELECT i.id itemFk,
|
||||
util.dayEnd(DATE_ADD(c.maxLanded, INTERVAL it.life DAY)) ended, it.life
|
||||
FROM vn.item i
|
||||
LEFT JOIN (
|
||||
SELECT b.itemFk, MAX(t.landed) maxLanded
|
||||
FROM vn.buy b
|
||||
JOIN vn.entry e ON b.entryFk = e.id
|
||||
JOIN vn.travel t ON t.id = e.travelFk
|
||||
JOIN vn.warehouse w ON w.id = t.warehouseInFk
|
||||
WHERE t.landed BETWEEN vInventoryDate AND vStartDate
|
||||
JOIN vn.item i ON i.id = b.itemFk
|
||||
JOIN vn.itemType it ON it.id = i.typeFk
|
||||
WHERE t.landed BETWEEN vLifeScope AND vStartDate
|
||||
AND t.warehouseInFk = vWarehouse
|
||||
AND t.warehouseOutFk <> vWarehouseFkInventory
|
||||
AND it.life
|
||||
AND NOT e.isExcludedFromAvailable
|
||||
GROUP BY b.itemFk
|
||||
) c
|
||||
JOIN vn.item i ON i.id = c.itemFk
|
||||
) c ON i.id = c.itemFk
|
||||
JOIN vn.itemType it ON it.id = i.typeFk
|
||||
HAVING ended >= vStartDate OR ended IS NULL;
|
||||
HAVING ended >= vStartDate OR life IS NULL;
|
||||
|
||||
-- Calcula el ATP
|
||||
DELETE FROM available WHERE calc_id = vCalc;
|
||||
|
@ -86,7 +86,7 @@ proc: BEGIN
|
|||
WHERE i.landed >= vStartDate
|
||||
AND (ir.ended IS NULL OR i.landed <= ir.ended)
|
||||
AND i.warehouseInFk = vWarehouse
|
||||
AND (ISNULL(wf.entryFk) OR vIsLogifloraDay)
|
||||
AND ISNULL(wf.entryFk)
|
||||
UNION ALL
|
||||
SELECT i.itemFk, i.shipped, i.quantity
|
||||
FROM vn.itemEntryOut i
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
UPDATE salix.ACL
|
||||
SET property='clone'
|
||||
WHERE model = 'Sale'
|
||||
AND property = 'refund'
|
|
@ -1,258 +0,0 @@
|
|||
{
|
||||
"name": "salix-front",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "salix-front",
|
||||
"version": "1.0.0",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"@uirouter/angularjs": "^1.0.20",
|
||||
"angular": "^1.7.5",
|
||||
"angular-animate": "^1.7.8",
|
||||
"angular-moment": "^1.3.0",
|
||||
"angular-translate": "^2.18.1",
|
||||
"angular-translate-loader-partial": "^2.18.1",
|
||||
"croppie": "^2.6.5",
|
||||
"js-yaml": "^3.13.1",
|
||||
"mg-crud": "^1.1.2",
|
||||
"oclazyload": "^0.6.3",
|
||||
"require-yaml": "0.0.1",
|
||||
"validator": "^6.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uirouter/angularjs": {
|
||||
"version": "1.0.30",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@uirouter/core": "6.0.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"angular": ">=1.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@uirouter/core": {
|
||||
"version": "6.0.8",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/angular": {
|
||||
"version": "1.8.3",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/angular-animate": {
|
||||
"version": "1.8.2",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/angular-moment": {
|
||||
"version": "1.3.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"moment": ">=2.8.0 <3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/angular-translate": {
|
||||
"version": "2.19.1",
|
||||
"resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.19.1.tgz",
|
||||
"integrity": "sha512-SrU40ndnL422vXiVoqVveCmSnCzMcIXxQgnl7Cv9krOKUg6B8KZK3ddYzidHR/rxVuySezYHNDgRvzQNKwAdNQ==",
|
||||
"deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
|
||||
"dependencies": {
|
||||
"angular": "^1.8.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/angular-translate-loader-partial": {
|
||||
"version": "2.19.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"angular-translate": "~2.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/argparse": {
|
||||
"version": "1.0.10",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"sprintf-js": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/croppie": {
|
||||
"version": "2.6.5",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/esprima": {
|
||||
"version": "4.0.1",
|
||||
"license": "BSD-2-Clause",
|
||||
"bin": {
|
||||
"esparse": "bin/esparse.js",
|
||||
"esvalidate": "bin/esvalidate.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/js-yaml": {
|
||||
"version": "3.14.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"argparse": "^1.0.7",
|
||||
"esprima": "^4.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/mg-crud": {
|
||||
"version": "1.1.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"angular": "^1.6.1"
|
||||
}
|
||||
},
|
||||
"node_modules/moment": {
|
||||
"version": "2.29.4",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/oclazyload": {
|
||||
"version": "0.6.3",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/require-yaml": {
|
||||
"version": "0.0.1",
|
||||
"license": "BSD",
|
||||
"dependencies": {
|
||||
"js-yaml": ""
|
||||
}
|
||||
},
|
||||
"node_modules/require-yaml/node_modules/argparse": {
|
||||
"version": "2.0.1",
|
||||
"license": "Python-2.0"
|
||||
},
|
||||
"node_modules/require-yaml/node_modules/js-yaml": {
|
||||
"version": "4.1.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/sprintf-js": {
|
||||
"version": "1.0.3",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/validator": {
|
||||
"version": "6.3.0",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@uirouter/angularjs": {
|
||||
"version": "1.0.30",
|
||||
"requires": {
|
||||
"@uirouter/core": "6.0.8"
|
||||
}
|
||||
},
|
||||
"@uirouter/core": {
|
||||
"version": "6.0.8"
|
||||
},
|
||||
"angular": {
|
||||
"version": "1.8.3"
|
||||
},
|
||||
"angular-animate": {
|
||||
"version": "1.8.2"
|
||||
},
|
||||
"angular-moment": {
|
||||
"version": "1.3.0",
|
||||
"requires": {
|
||||
"moment": ">=2.8.0 <3.0.0"
|
||||
}
|
||||
},
|
||||
"angular-translate": {
|
||||
"version": "2.19.1",
|
||||
"resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.19.1.tgz",
|
||||
"integrity": "sha512-SrU40ndnL422vXiVoqVveCmSnCzMcIXxQgnl7Cv9krOKUg6B8KZK3ddYzidHR/rxVuySezYHNDgRvzQNKwAdNQ==",
|
||||
"requires": {
|
||||
"angular": "^1.8.0"
|
||||
}
|
||||
},
|
||||
"angular-translate-loader-partial": {
|
||||
"version": "2.19.0",
|
||||
"requires": {
|
||||
"angular-translate": "~2.19.0"
|
||||
}
|
||||
},
|
||||
"argparse": {
|
||||
"version": "1.0.10",
|
||||
"requires": {
|
||||
"sprintf-js": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"croppie": {
|
||||
"version": "2.6.5"
|
||||
},
|
||||
"esprima": {
|
||||
"version": "4.0.1"
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "3.14.1",
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
"esprima": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"mg-crud": {
|
||||
"version": "1.1.2",
|
||||
"requires": {
|
||||
"angular": "^1.6.1"
|
||||
}
|
||||
},
|
||||
"moment": {
|
||||
"version": "2.29.4"
|
||||
},
|
||||
"oclazyload": {
|
||||
"version": "0.6.3"
|
||||
},
|
||||
"require-yaml": {
|
||||
"version": "0.0.1",
|
||||
"requires": {
|
||||
"js-yaml": ""
|
||||
},
|
||||
"dependencies": {
|
||||
"argparse": {
|
||||
"version": "2.0.1"
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "4.1.0",
|
||||
"requires": {
|
||||
"argparse": "^2.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sprintf-js": {
|
||||
"version": "1.0.3"
|
||||
},
|
||||
"validator": {
|
||||
"version": "6.3.0"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@
|
|||
"type": "git",
|
||||
"url": "https://gitea.verdnatura.es/verdnatura/salix"
|
||||
},
|
||||
"packageManager": "pnpm@8.15.1",
|
||||
"dependencies": {
|
||||
"@uirouter/angularjs": "^1.0.20",
|
||||
"angular": "^1.7.5",
|
||||
|
|
|
@ -0,0 +1,156 @@
|
|||
lockfileVersion: '6.0'
|
||||
|
||||
settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
dependencies:
|
||||
'@uirouter/angularjs':
|
||||
specifier: ^1.0.20
|
||||
version: 1.1.0(@uirouter/core@6.1.0)(angular@1.8.3)
|
||||
angular:
|
||||
specifier: ^1.7.5
|
||||
version: 1.8.3
|
||||
angular-animate:
|
||||
specifier: ^1.7.8
|
||||
version: 1.8.3
|
||||
angular-moment:
|
||||
specifier: ^1.3.0
|
||||
version: 1.3.0
|
||||
angular-translate:
|
||||
specifier: ^2.18.1
|
||||
version: 2.19.1
|
||||
angular-translate-loader-partial:
|
||||
specifier: ^2.18.1
|
||||
version: 2.19.1
|
||||
croppie:
|
||||
specifier: ^2.6.5
|
||||
version: 2.6.5
|
||||
js-yaml:
|
||||
specifier: ^3.13.1
|
||||
version: 3.14.1
|
||||
mg-crud:
|
||||
specifier: ^1.1.2
|
||||
version: 1.1.2
|
||||
oclazyload:
|
||||
specifier: ^0.6.3
|
||||
version: 0.6.3
|
||||
require-yaml:
|
||||
specifier: 0.0.1
|
||||
version: 0.0.1
|
||||
validator:
|
||||
specifier: ^6.3.0
|
||||
version: 6.3.0
|
||||
|
||||
packages:
|
||||
|
||||
/@uirouter/angularjs@1.1.0(@uirouter/core@6.1.0)(angular@1.8.3):
|
||||
resolution: {integrity: sha512-AhgxXhMfN6FU2HxDQqwDPbzmd6kTgvYCgV/kgoCAXfxAH6cFQrifViToC90Wdg6djBynHwA3L/KYP+iOYHkw6A==}
|
||||
engines: {node: '>=4.0.0'}
|
||||
peerDependencies:
|
||||
'@uirouter/core': ^6.0.8
|
||||
angular: '>=1.2.0'
|
||||
dependencies:
|
||||
'@uirouter/core': 6.1.0
|
||||
angular: 1.8.3
|
||||
dev: false
|
||||
|
||||
/@uirouter/core@6.1.0:
|
||||
resolution: {integrity: sha512-WFYh5NPAqRX4L2qlI4k62tgR6pxoqOBSW1CM1uBWCau4mAmgasYd5etJ9RoSJrSnCpCQ2km2Jltf0n5ql684MQ==}
|
||||
engines: {node: '>=4.0.0'}
|
||||
dev: false
|
||||
|
||||
/angular-animate@1.8.3:
|
||||
resolution: {integrity: sha512-/LtTKvy5sD6MZbV0v+nHgOIpnFF0mrUp+j5WIxVprVhcrJriYpuCZf4S7Owj1o76De/J0eRzANUozNJ6hVepnQ==}
|
||||
deprecated: For the actively supported Angular, see https://www.npmjs.com/package/@angular/core. AngularJS support has officially ended. For extended AngularJS support options, see https://goo.gle/angularjs-path-forward.
|
||||
dev: false
|
||||
|
||||
/angular-moment@1.3.0:
|
||||
resolution: {integrity: sha512-KG8rvO9MoaBLwtGnxTeUveSyNtrL+RNgGl1zqWN36+HDCCVGk2DGWOzqKWB6o+eTTbO3Opn4hupWKIElc8XETA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dependencies:
|
||||
moment: 2.30.1
|
||||
dev: false
|
||||
|
||||
/angular-translate-loader-partial@2.19.1:
|
||||
resolution: {integrity: sha512-1rDe314zG09gwl/2qsLPwrxp5yehSsRi2vNJn/UwIJq20n0E0Fia/1K0nW9QAv67UFyvFuBOhl34n59I1qEHog==}
|
||||
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
|
||||
dependencies:
|
||||
angular-translate: 2.19.1
|
||||
dev: false
|
||||
|
||||
/angular-translate@2.19.1:
|
||||
resolution: {integrity: sha512-SrU40ndnL422vXiVoqVveCmSnCzMcIXxQgnl7Cv9krOKUg6B8KZK3ddYzidHR/rxVuySezYHNDgRvzQNKwAdNQ==}
|
||||
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
|
||||
dependencies:
|
||||
angular: 1.8.3
|
||||
dev: false
|
||||
|
||||
/angular@1.8.3:
|
||||
resolution: {integrity: sha512-5qjkWIQQVsHj4Sb5TcEs4WZWpFeVFHXwxEBHUhrny41D8UrBAd6T/6nPPAsLngJCReIOqi95W3mxdveveutpZw==}
|
||||
deprecated: For the actively supported Angular, see https://www.npmjs.com/package/@angular/core. AngularJS support has officially ended. For extended AngularJS support options, see https://goo.gle/angularjs-path-forward.
|
||||
dev: false
|
||||
|
||||
/argparse@1.0.10:
|
||||
resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==}
|
||||
dependencies:
|
||||
sprintf-js: 1.0.3
|
||||
dev: false
|
||||
|
||||
/argparse@2.0.1:
|
||||
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
|
||||
dev: false
|
||||
|
||||
/croppie@2.6.5:
|
||||
resolution: {integrity: sha512-IlChnVUGG5T3w2gRZIaQgBtlvyuYnlUWs2YZIXXR3H9KrlO1PtBT3j+ykxvy9eZIWhk+V5SpBmhCQz5UXKrEKQ==}
|
||||
dev: false
|
||||
|
||||
/esprima@4.0.1:
|
||||
resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
|
||||
engines: {node: '>=4'}
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/js-yaml@3.14.1:
|
||||
resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
argparse: 1.0.10
|
||||
esprima: 4.0.1
|
||||
dev: false
|
||||
|
||||
/js-yaml@4.1.0:
|
||||
resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
argparse: 2.0.1
|
||||
dev: false
|
||||
|
||||
/mg-crud@1.1.2:
|
||||
resolution: {integrity: sha512-mAR6t0aQHKnT0QHKHpLOi0kNPZfO36iMpIoiLjFHxuio6mIJyuveBJ4VNlNXJRxLh32/FLADEb41/sYo7QUKFw==}
|
||||
dependencies:
|
||||
angular: 1.8.3
|
||||
dev: false
|
||||
|
||||
/moment@2.30.1:
|
||||
resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
|
||||
dev: false
|
||||
|
||||
/oclazyload@0.6.3:
|
||||
resolution: {integrity: sha512-HpOSYUgjtt6sTB/C6+FWsExR+9HCnXKsUA96RWkDXfv11C8Cc9X2DlR0WIZwFIiG6FQU0pwB5dhoYyut8bFAOQ==}
|
||||
dev: false
|
||||
|
||||
/require-yaml@0.0.1:
|
||||
resolution: {integrity: sha512-M6eVEgLPRbeOhgSCnOTtdrOOEQzbXRchg24Xa13c39dMuraFKdI9emUo97Rih0YEFzSICmSKg8w4RQp+rd9pOQ==}
|
||||
dependencies:
|
||||
js-yaml: 4.1.0
|
||||
dev: false
|
||||
|
||||
/sprintf-js@1.0.3:
|
||||
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
|
||||
dev: false
|
||||
|
||||
/validator@6.3.0:
|
||||
resolution: {integrity: sha512-BylxTwhqwjQI5MDJF7amCy/L0ejJO+74DvCsLV52Lq3+3bhVcVMKqNqOiNcQJm2G48u9EAcw4xFERAmFbwXM9Q==}
|
||||
engines: {node: '>= 0.10'}
|
||||
dev: false
|
|
@ -22,7 +22,7 @@ module.exports = Self => {
|
|||
});
|
||||
|
||||
const modelsLocale = new Map();
|
||||
const modulesDir = path.resolve(`${__dirname}/../../../../modules`);
|
||||
const modulesDir = path.resolve(`${process.cwd()}/modules`);
|
||||
const modules = fs.readdirSync(modulesDir);
|
||||
|
||||
for (const mod of modules) {
|
||||
|
|
|
@ -203,5 +203,7 @@
|
|||
"Cannot past travels with entries": "Cannot past travels with entries",
|
||||
"It was not able to remove the next expeditions:": "It was not able to remove the next expeditions: {{expeditions}}",
|
||||
"Incorrect pin": "Incorrect pin.",
|
||||
"The notification subscription of this worker cant be modified": "The notification subscription of this worker cant be modified"
|
||||
"The notification subscription of this worker cant be modified": "The notification subscription of this worker cant be modified",
|
||||
"Fecha fuera de rango": "Fecha fuera de rango",
|
||||
"There is no zone for these parameters 34": "There is no zone for these parameters 34"
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
const packageJson = require('../../../package.json');
|
||||
const packageJson = require(`${process.cwd()}/package.json`);
|
||||
|
||||
module.exports = function(options) {
|
||||
return function(req, res, next) {
|
||||
|
|
|
@ -28,7 +28,7 @@ module.exports = app;
|
|||
|
||||
let rootDir = __dirname;
|
||||
let lbDir = path.resolve(`${rootDir}/..`);
|
||||
let appDir = path.resolve(`${__dirname}/../..`);
|
||||
let appDir = process.cwd();
|
||||
let localeDir = `${lbDir}/locale`;
|
||||
let modulesDir = `${appDir}/modules`;
|
||||
|
||||
|
@ -80,13 +80,13 @@ app.boot = function(bootOptions, callback) {
|
|||
`${__dirname}/model-config.json`
|
||||
];
|
||||
let modelSources = [
|
||||
`loopback/common/models`,
|
||||
`loopback/server/models`,
|
||||
`${lbDir}/common/models`,
|
||||
`${lbDir}/server/models`,
|
||||
`${__dirname}/../common/models`
|
||||
];
|
||||
let mixinDirs = [
|
||||
`loopback/common/mixins`,
|
||||
`loopback/server/mixins`,
|
||||
`${lbDir}/common/mixins`,
|
||||
`${lbDir}/server/mixins`,
|
||||
`${__dirname}/../common/mixins`
|
||||
];
|
||||
let bootDirs = [
|
||||
|
|
|
@ -1,4 +1,32 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('clone', {
|
||||
description: 'Clone sales and services provided',
|
||||
accessType: 'WRITE',
|
||||
accepts: [
|
||||
{
|
||||
arg: 'salesIds',
|
||||
type: ['number'],
|
||||
}, {
|
||||
arg: 'servicesIds',
|
||||
type: ['number']
|
||||
}, {
|
||||
arg: 'withWarehouse',
|
||||
type: 'boolean',
|
||||
required: true
|
||||
}, {
|
||||
arg: 'negative',
|
||||
type: 'boolean'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: ['object'],
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/clone`,
|
||||
verb: 'POST'
|
||||
}
|
||||
});
|
||||
Self.clone = async(ctx, salesIds, servicesIds, withWarehouse, negative, options) => {
|
||||
const models = Self.app.models;
|
||||
const myOptions = {};
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('refund', {
|
||||
description: 'Create refund tickets with sales and services if provided',
|
||||
accessType: 'WRITE',
|
||||
accepts: [
|
||||
{
|
||||
arg: 'salesIds',
|
||||
type: ['number'],
|
||||
},
|
||||
{
|
||||
arg: 'servicesIds',
|
||||
type: ['number']
|
||||
},
|
||||
{
|
||||
arg: 'withWarehouse',
|
||||
type: 'boolean',
|
||||
required: true
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: ['object'],
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/refund`,
|
||||
verb: 'post'
|
||||
}
|
||||
});
|
||||
|
||||
Self.refund = async(ctx, salesIds, servicesIds, withWarehouse, options) => {
|
||||
const models = Self.app.models;
|
||||
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 refundsTicket = await models.Sale.clone(
|
||||
ctx,
|
||||
salesIds,
|
||||
servicesIds,
|
||||
withWarehouse,
|
||||
true,
|
||||
myOptions
|
||||
);
|
||||
|
||||
if (tx) await tx.commit();
|
||||
|
||||
return refundsTicket;
|
||||
} catch (e) {
|
||||
if (tx) await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
};
|
|
@ -67,4 +67,34 @@ describe('Ticket cloning - clone function', () => {
|
|||
expect(services.length).toBeGreaterThan(0);
|
||||
}
|
||||
});
|
||||
|
||||
it('should create a ticket without sales', async() => {
|
||||
const servicesIds = [4];
|
||||
|
||||
const tickets = await models.Sale.clone(ctx, null, servicesIds, false, false, options);
|
||||
const refundedTicket = await getTicketRefund(tickets[0].id, options);
|
||||
|
||||
expect(refundedTicket).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
async function getTicketRefund(id, options) {
|
||||
return models.Ticket.findOne({
|
||||
where: {
|
||||
id
|
||||
},
|
||||
include: [
|
||||
{
|
||||
relation: 'ticketSales',
|
||||
scope: {
|
||||
include: {
|
||||
relation: 'components'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
relation: 'ticketServices',
|
||||
}
|
||||
]
|
||||
}, options);
|
||||
}
|
||||
|
|
|
@ -1,101 +0,0 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
const LoopBackContext = require('loopback-context');
|
||||
|
||||
describe('Sale refund()', () => {
|
||||
const userId = 5;
|
||||
const ctx = {req: {accessToken: userId}, args: {}};
|
||||
const activeCtx = {
|
||||
accessToken: {userId},
|
||||
};
|
||||
const servicesIds = [3];
|
||||
const withWarehouse = true;
|
||||
|
||||
beforeEach(() => {
|
||||
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||
active: activeCtx
|
||||
});
|
||||
});
|
||||
|
||||
it('should create ticket with the selected lines', async() => {
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
const salesIds = [7, 8];
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const refundedTickets = await models.Sale.refund(ctx, salesIds, servicesIds, withWarehouse, options);
|
||||
|
||||
expect(refundedTickets).toBeDefined();
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should create one ticket for each unique ticketFk in the sales', async() => {
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
const salesIds = [6, 7];
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
const ticketsBefore = await models.Ticket.find({}, options);
|
||||
|
||||
const tickets = await models.Sale.refund(ctx, salesIds, servicesIds, withWarehouse, options);
|
||||
|
||||
const refundedTicket = await getTicketRefund(tickets[0].id, options);
|
||||
const ticketsAfter = await models.Ticket.find({}, options);
|
||||
const salesLength = refundedTicket.ticketSales().length;
|
||||
const componentsLength = refundedTicket.ticketSales()[0].components().length;
|
||||
|
||||
expect(refundedTicket).toBeDefined();
|
||||
expect(salesLength).toEqual(1);
|
||||
expect(ticketsBefore.length).toEqual(ticketsAfter.length - 2);
|
||||
expect(componentsLength).toEqual(4);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should create a ticket without sales', async() => {
|
||||
const servicesIds = [4];
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
const options = {transaction: tx};
|
||||
try {
|
||||
const tickets = await models.Sale.refund(ctx, null, servicesIds, withWarehouse, options);
|
||||
const refundedTicket = await getTicketRefund(tickets[0].id, options);
|
||||
|
||||
expect(refundedTicket).toBeDefined();
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
async function getTicketRefund(id, options) {
|
||||
return models.Ticket.findOne({
|
||||
where: {
|
||||
id
|
||||
},
|
||||
include: [
|
||||
{
|
||||
relation: 'ticketSales',
|
||||
scope: {
|
||||
include: {
|
||||
relation: 'components'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
relation: 'ticketServices',
|
||||
}
|
||||
]
|
||||
}, options);
|
||||
}
|
|
@ -108,6 +108,23 @@ module.exports = function(Self) {
|
|||
|
||||
await Self.rawSql('CALL invoiceOutBooking(?)', [resultInvoice.id], myOptions);
|
||||
|
||||
const client = await models.Client.findById(clientId,
|
||||
{fields: ['hasElectronicInvoice', 'name', 'email']}, myOptions);
|
||||
if (client.hasElectronicInvoice) {
|
||||
const url = await models.Url.getUrl();
|
||||
await models.NotificationQueue.create({
|
||||
notificationFk: 'invoice-electronic',
|
||||
authorFk: client.id,
|
||||
params: JSON.stringify(
|
||||
{
|
||||
'name': client.name,
|
||||
'email': client.email,
|
||||
'ticketId': ticketsIds.join(','),
|
||||
'url': url + 'ticket/index?q=' + encodeURIComponent(JSON.stringify({clientFk: clientId}))
|
||||
})
|
||||
}, myOptions);
|
||||
}
|
||||
|
||||
if (tx) await tx.commit();
|
||||
|
||||
return resultInvoice.id;
|
||||
|
|
|
@ -20,7 +20,7 @@ module.exports = Self => {
|
|||
},
|
||||
http: {
|
||||
path: `/refund`,
|
||||
verb: 'post'
|
||||
verb: 'POST'
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -45,7 +45,7 @@ module.exports = Self => {
|
|||
const services = await models.TicketService.find(filter, myOptions);
|
||||
const servicesIds = services.map(service => service.id);
|
||||
|
||||
const refundedTickets = await models.Sale.refund(ctx, salesIds, servicesIds, withWarehouse, myOptions);
|
||||
const refundedTickets = await models.Sale.clone(ctx, salesIds, servicesIds, withWarehouse, true, myOptions);
|
||||
|
||||
if (tx) await tx.commit();
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ module.exports = Self => {
|
|||
require('../methods/sale/updateQuantity')(Self);
|
||||
require('../methods/sale/updateConcept')(Self);
|
||||
require('../methods/sale/recalculatePrice')(Self);
|
||||
require('../methods/sale/refund')(Self);
|
||||
require('../methods/sale/canEdit')(Self);
|
||||
require('../methods/sale/usesMana')(Self);
|
||||
require('../methods/sale/clone')(Self);
|
||||
|
|
|
@ -248,23 +248,6 @@ class Controller extends Section {
|
|||
if (this.ticket.address.incotermsFk && !this.ticket.weight && !force)
|
||||
return this.$.withoutWeightConfirmation.show();
|
||||
|
||||
const client = this.ticket.client;
|
||||
if (client.hasElectronicInvoice) {
|
||||
this.$http.post(`NotificationQueues`, {
|
||||
notificationFk: 'invoice-electronic',
|
||||
authorFk: client.id,
|
||||
params: JSON.stringify(
|
||||
{
|
||||
'name': client.name,
|
||||
'email': client.email,
|
||||
'ticketId': this.id,
|
||||
'url': window.location.href
|
||||
})
|
||||
}).then(() => {
|
||||
this.vnApp.showSuccess(this.$t('Invoice sent'));
|
||||
});
|
||||
}
|
||||
|
||||
return this.$http.post(`Tickets/invoiceTicketsAndPdf`, {ticketsIds: [this.id]})
|
||||
.then(() => this.reload())
|
||||
.then(() => this.vnApp.showSuccess(this.$t('Ticket invoiced')));
|
||||
|
|
|
@ -523,8 +523,8 @@ class Controller extends Section {
|
|||
if (!sales) return;
|
||||
|
||||
const salesIds = sales.map(sale => sale.id);
|
||||
const params = {salesIds: salesIds, withWarehouse: withWarehouse};
|
||||
const query = 'Sales/refund';
|
||||
const params = {salesIds: salesIds, withWarehouse: withWarehouse, negative: true};
|
||||
const query = 'Sales/clone';
|
||||
this.$http.post(query, params).then(res => {
|
||||
const [refundTicket] = res.data;
|
||||
this.vnApp.showSuccess(this.$t('The following refund ticket have been created', {
|
||||
|
|
|
@ -727,9 +727,10 @@ describe('Ticket', () => {
|
|||
jest.spyOn(controller.$state, 'go');
|
||||
const params = {
|
||||
salesIds: [1, 4],
|
||||
negative: true
|
||||
};
|
||||
const refundTicket = {id: 99};
|
||||
$httpBackend.expect('POST', 'Sales/refund', params).respond(200, [refundTicket]);
|
||||
$httpBackend.expect('POST', 'Sales/clone', params).respond(200, [refundTicket]);
|
||||
controller.createRefund();
|
||||
$httpBackend.flush();
|
||||
|
||||
|
|
|
@ -55,10 +55,10 @@ class Controller extends Section {
|
|||
createRefund() {
|
||||
if (!this.checkeds.length) return;
|
||||
|
||||
const params = {servicesIds: this.checkeds, withWarehouse: false};
|
||||
const query = 'Sales/refund';
|
||||
const params = {servicesIds: this.checkeds, withWarehouse: false, negative: true};
|
||||
const query = 'Sales/clone';
|
||||
this.$http.post(query, params).then(res => {
|
||||
const refundTicket = res.data;
|
||||
const [refundTicket] = res.data;
|
||||
this.vnApp.showSuccess(this.$t('The following refund ticket have been created', {
|
||||
ticketId: refundTicket.id
|
||||
}));
|
||||
|
|
|
@ -30,13 +30,12 @@ module.exports = Self => {
|
|||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
stmts.push(new ParameterizedSQL('CALL vn.subordinateGetList(?)', [userId]));
|
||||
const queryIndex = stmts.push('SELECT * FROM tmp.subordinate') - 1;
|
||||
stmts.push('DROP TEMPORARY TABLE tmp.subordinate');
|
||||
stmts.push(new ParameterizedSQL('CALL vn.worker_getHierarchy(?)', [userId]));
|
||||
const queryIndex = stmts.push('SELECT * FROM tmp.workerHierarchyList') - 1;
|
||||
stmts.push('DROP TEMPORARY TABLE tmp.workerHierarchyList');
|
||||
|
||||
const sql = ParameterizedSQL.join(stmts, ';');
|
||||
const result = await conn.executeStmt(sql, myOptions);
|
||||
|
||||
return result[queryIndex];
|
||||
};
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
16
package.json
16
package.json
|
@ -11,10 +11,13 @@
|
|||
"engines": {
|
||||
"node": ">=20"
|
||||
},
|
||||
"packageManager": "pnpm@8.15.1",
|
||||
"dependencies": {
|
||||
"axios": "^1.2.2",
|
||||
"base64url": "^3.0.1",
|
||||
"body-parser": "^1.19.2",
|
||||
"compression": "^1.7.3",
|
||||
"ejs": "2.3.1",
|
||||
"form-data": "^4.0.0",
|
||||
"fs-extra": "^5.0.0",
|
||||
"ftps": "^1.2.0",
|
||||
|
@ -30,18 +33,22 @@
|
|||
"loopback-boot": "3.3.1",
|
||||
"loopback-component-explorer": "^6.5.0",
|
||||
"loopback-component-storage": "3.6.1",
|
||||
"loopback-connector-mysql": "^6.2.0",
|
||||
"loopback-connector": "4.11.1",
|
||||
"loopback-connector-mysql": "6.2.0",
|
||||
"loopback-connector-remote": "^3.4.1",
|
||||
"loopback-context": "^3.5.2",
|
||||
"loopback-datasource-juggler": "3.36.1",
|
||||
"md5": "^2.2.1",
|
||||
"mysql": "2.18.1",
|
||||
"node-ssh": "^11.0.0",
|
||||
"object.pick": "^1.3.0",
|
||||
"puppeteer": "^21.10.0",
|
||||
"require-yaml": "0.0.1",
|
||||
"smbhash": "0.0.1",
|
||||
"strong-error-handler": "^2.3.2",
|
||||
"vn-loopback": "file:./loopback",
|
||||
"vn-print": "file:./print"
|
||||
"vn-loopback": "link:./loopback",
|
||||
"vn-print": "link:./print",
|
||||
"xmldom": "^0.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.7.7",
|
||||
|
@ -74,11 +81,12 @@
|
|||
"html-loader-jest": "^0.2.1",
|
||||
"html-webpack-plugin": "^5.5.1",
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
"jasmine": "^5.0.0",
|
||||
"jasmine": "^5.0.2",
|
||||
"jasmine-reporters": "^2.4.0",
|
||||
"jasmine-spec-reporter": "^7.0.0",
|
||||
"jest": "^26.0.1",
|
||||
"jest-junit": "^8.0.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"json-loader": "^0.5.7",
|
||||
"merge-stream": "^1.0.1",
|
||||
"minimist": "^1.2.5",
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -11,7 +11,9 @@
|
|||
"url": "https://git.verdnatura.es/salix"
|
||||
},
|
||||
"license": "GPL-3.0",
|
||||
"packageManager": "pnpm@8.15.1",
|
||||
"dependencies": {
|
||||
"express": "4.14.0",
|
||||
"fs-extra": "^7.0.1",
|
||||
"intl": "^1.2.5",
|
||||
"js-yaml": "^3.13.1",
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -10,7 +10,7 @@ module.exports = {
|
|||
required: true
|
||||
},
|
||||
ticketId: {
|
||||
type: [Number],
|
||||
type: [String],
|
||||
required: true
|
||||
},
|
||||
url: {
|
||||
|
|
|
@ -15,7 +15,7 @@ SELECT pack.packages,
|
|||
LEFT JOIN vn.province p ON p.id = c.provinceFk
|
||||
JOIN vn.ticket t ON t.refFk = io.ref
|
||||
JOIN vn.address a ON a.id = t.addressFk
|
||||
LEFT JOIN vn.incoterms ic ON ic.code = a.incotermsFk
|
||||
JOIN vn.incoterms ic ON ic.code = a.incotermsFk
|
||||
LEFT JOIN vn.customsAgent ca ON ca.id = a.customsAgentFk
|
||||
JOIN vn.sale s ON s.ticketFk = t.id
|
||||
JOIN (
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
SELECT IF(incotermsFk IS NULL, FALSE, TRUE) AS hasIncoterms
|
||||
FROM ticket t
|
||||
JOIN invoiceOut io ON io.ref = t.refFk
|
||||
JOIN client c ON c.id = t.clientFk
|
||||
JOIN address a ON a.id = t.addressFk
|
||||
WHERE t.refFk = ?
|
||||
AND IF(c.hasToinvoiceByAddress = FALSE, c.defaultAddressFk, TRUE)
|
||||
LIMIT 1
|
||||
SELECT COUNT(*) AS hasIncoterms
|
||||
FROM invoiceOut io
|
||||
JOIN vn.invoiceOutSerial ios ON ios.code = io.serial
|
||||
AND ios.taxAreaFk = 'WORLD'
|
||||
WHERE io.ref = ?
|
||||
|
|
Loading…
Reference in New Issue