Merge pull request '8355-testToMaster' (!3336) from 8355-testToMaster into master
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
Reviewed-on: #3336 Reviewed-by: Guillermo Bonet <guillermo@verdnatura.es>
This commit is contained in:
commit
72bf27f08d
103
CHANGELOG.md
103
CHANGELOG.md
|
@ -1,3 +1,106 @@
|
|||
# Version 24.52 - 2024-01-07
|
||||
|
||||
### Added 🆕
|
||||
|
||||
- chore: pullinfo by:alexm
|
||||
- chore: refs #8002 drop comments by:jorgep
|
||||
- chore: refs #8002 drop useless code by:jorgep
|
||||
- feat: added translations and show error in item-type by:Jon
|
||||
- feat: modified data to be equal as the updated back by:Jon
|
||||
- feat: refs #4460 invoiceIn refund by:Carlos Andrés
|
||||
- feat: refs #4466 invoiceIn refund by:Carlos Andrés
|
||||
- feat: refs #6583 add new opt in where builder by:jorgep
|
||||
- feat: refs #6583 add tests by:jorgep
|
||||
- feat: refs #6583 retrieve cloned sale by:jorgep
|
||||
- feat: refs #6583 rollback by:jorgep
|
||||
- feat: refs #7301 add inventory-config and acl by:pablone
|
||||
- feat: refs #7301 update SQL fixtures and enhance lastEntriesFilter logic by:pablone
|
||||
- feat: refs #7882 Added locationiq service by:guillermo
|
||||
- feat: refs #7882 Added osrm service by:guillermo
|
||||
- feat: refs #7882 Added tests by:guillermo
|
||||
- feat: refs #7882 Fixed problems osrm service by:guillermo
|
||||
- feat: refs #7882 Osrm service by:guillermo
|
||||
- feat: refs #7882 Reequested changes by:guillermo
|
||||
- feat: refs #7882 Requested changes by:guillermo
|
||||
- feat: refs #7936 add back test for updateInvoiceIn by:jorgep
|
||||
- feat: refs #7936 add company filter by:jorgep
|
||||
- feat: refs #7936 add currency check to updateInvoiceIn by:jorgep
|
||||
- feat: refs #7936 add currency handling in invoiceIn trigger by:jorgep
|
||||
- feat: refs #7936 add locale by:jorgep
|
||||
- feat: refs #7936 add minimum due date by:jorgep
|
||||
- feat: refs #7936 add reference rates for currency in fixtures by:jorgep
|
||||
- feat: refs #7936 add save validation by:jorgep
|
||||
- feat: refs #7936 add SiiTypeInvoiceIn model and update invoice correction logic by:jorgep
|
||||
- feat: refs #7936 add tests for invoiceIn by:jorgep
|
||||
- feat: refs #7936 add tests for invoiceIn filter by:jorgep
|
||||
- feat: refs #7936 add validation to InvoiceIn & InvoiceInTax by:jorgep
|
||||
- feat: refs #7936 return country code & is vies fields by:jorgep
|
||||
- feat: refs #8002 adjust to lilium by:jorgep
|
||||
- feat: refs #8002 drop support btn by:jorgep
|
||||
- feat: refs #8174 Changed datatype incompatibility access by:guillermo
|
||||
- feat: refs #8174 Created table sim by:guillermo
|
||||
- feat: refs #8174 create table simsupplier by:Jbreso
|
||||
- feat: refs #8174 fix by:Jbreso
|
||||
- feat: refs#8174 simSupplier by:Jbreso
|
||||
- feat: refs #8190 entry_getCommission by:robert
|
||||
- feat: refs #8190 entry_getCommission change request by:robert
|
||||
- feat: refs #8218 Added time and code in mistakeType by:guillermo
|
||||
- feat: refs #8293 include zone data by:Jtubau
|
||||
- refactor: refs #6583 entry report table style by:jorgep
|
||||
|
||||
### Changed 📦
|
||||
|
||||
- refactor: refs #6583 entry report table style by:jorgep
|
||||
- refactor: refs #6583 use warehouseId var by:jorgep
|
||||
- refactor: refs #7301 update entry and item filter tests to validate results against specific criteria by:pablone
|
||||
- refactor: refs #7882 Added ACL's by:guillermo
|
||||
- refactor: refs #7882 Deleted quadminds files by:guillermo
|
||||
- refactor: refs #7936 add transaction & tests by:jorgep
|
||||
- refactor: refs #7936 remove old trigger and add isRaid column to travel table by:jorgep
|
||||
- refactor: refs #7936 remove schema by:jorgep
|
||||
- refactor: refs #8002 use loop wip by:jorgep
|
||||
- refactor: refs #8004 simplify SQL query by removing redundant aliases by:pablone
|
||||
- refactor: refs #8262 Deprecated inventoryFailure by:guillermo
|
||||
- refactor: refs #8266 changed expedition item name by:Jtubau
|
||||
- refactor: refs #8272 delete bi.rotacion by:ivanm
|
||||
|
||||
### Fixed 🛠️
|
||||
|
||||
- feat: refs #7301 update SQL fixtures and enhance lastEntriesFilter logic by:pablone
|
||||
- feat: refs #7936 add reference rates for currency in fixtures by:jorgep
|
||||
- feat: refs #8174 fix by:Jbreso
|
||||
- fix: 8174 pasar PIN a CHAR by:Jbreso
|
||||
- fix: monitorPayMethodFilter by:carlossa
|
||||
- fix: refs #6389 back by:carlossa
|
||||
- fix: refs #6389 filter by:carlossa
|
||||
- fix: refs #6389 packing by:carlossa
|
||||
- fix: refs #6389 saleMonitor filter by:carlossa
|
||||
- fix: refs #6389 salesFilter by:carlossa
|
||||
- fix: refs #6583 drop focus by:jorgep
|
||||
- fix: refs #6583 update onlyWithDestination logic to handle null values correctly by:jorgep
|
||||
- fix: refs #7028 fix confirm deny by:carlossa
|
||||
- fix: refs #7028 fix pr by:carlossa
|
||||
- fix: refs #7028 fix tback findById by:carlossa
|
||||
- fix: refs #7028 fix userError by:carlossa
|
||||
- fix: refs #7028 remove ifs by:carlossa
|
||||
- fix: refs #7028 requesterId fix by:carlossa
|
||||
- fix: refs #7028 requesterId fix salesPerson by:carlossa
|
||||
- fix: refs #7031 fix vnPrice by:carlossa
|
||||
- fix: refs #7031 remove check by:carlossa
|
||||
- fix: refs #7301 update ACL insertion to use INSERT IGNORE and refine property value by:pablone
|
||||
- fix: refs #7936 add IF NOT EXISTS to isRaid column in travel table by:jorgep
|
||||
- fix: refs #7936 change type by:jorgep
|
||||
- fix: refs #7936 check if insert in hook & change test description by:jorgep
|
||||
- fix: refs #7936 conflicts by:jorgep
|
||||
- fix: refs #7936 locale by:jorgep
|
||||
- fix: refs #7936 update Spanish locale for SII terms by:jorgep
|
||||
- fix: refs #8174 fix by:Jbreso
|
||||
- fix: refs#8174 fix by:Jbreso
|
||||
- fix: refs8174 pasar a char el PIN by:Jbreso
|
||||
- fix: refs #8174 Version by:guillermo
|
||||
- fix: refs #8251 add eng template by:carlossa
|
||||
- fix: refs #8315 fixture claimDevelopment by:alexm
|
||||
|
||||
# Version 24.48 - 2024-11-25
|
||||
|
||||
### Added 🆕
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
const axios = require('axios');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('optimize', {
|
||||
description: 'Return optimized coords',
|
||||
accessType: 'READ',
|
||||
accepts: [{
|
||||
arg: 'addressIds',
|
||||
type: 'array',
|
||||
required: true
|
||||
}, {
|
||||
arg: 'firstAddressId',
|
||||
type: 'number',
|
||||
required: false
|
||||
}, {
|
||||
arg: 'lastAddressId',
|
||||
type: 'number',
|
||||
required: false
|
||||
}],
|
||||
returns: {
|
||||
type: 'object',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/optimize`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.optimize = async(addressIds, firstAddressId, lastAddressId) => {
|
||||
const models = Self.app.models;
|
||||
try {
|
||||
const osrmConfig = await models.OsrmConfig.findOne();
|
||||
if (!osrmConfig) throw new UserError(`OSRM service is not configured`);
|
||||
|
||||
let coords = [];
|
||||
if (firstAddressId) {
|
||||
const address = await models.Address.findById(firstAddressId);
|
||||
if (address.latitude && address.longitude) {
|
||||
coords.push({
|
||||
addressId: address.id,
|
||||
latitude: address.latitude.toFixed(6),
|
||||
longitude: address.longitude.toFixed(6)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (const addressId of addressIds) {
|
||||
const address = await models.Address.findById(addressId);
|
||||
if (address.latitude && address.longitude) {
|
||||
coords.push({
|
||||
addressId,
|
||||
latitude: address.latitude.toFixed(6),
|
||||
longitude: address.longitude.toFixed(6)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (lastAddressId) {
|
||||
const firstAddress = await models.Address.findById(lastAddressId);
|
||||
if (firstAddress.latitude && firstAddress.longitude) {
|
||||
coords.push({
|
||||
addressId: firstAddress.id,
|
||||
latitude: firstAddress.latitude.toFixed(6),
|
||||
longitude: firstAddress.longitude.toFixed(6)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!coords.length) throw new UserError('No address has coordinates');
|
||||
|
||||
const concatCoords = coords
|
||||
.map(coord => `${coord.longitude},${coord.latitude}`)
|
||||
.join(';');
|
||||
const response = await axios.post(`
|
||||
${osrmConfig.url}/trip/v1/driving/${concatCoords}?source=first&destination=last&roundtrip=true
|
||||
`);
|
||||
const tolerance = osrmConfig.tolerance;
|
||||
for (const waypoint of response.data.waypoints) {
|
||||
const longitude = waypoint.location[0];
|
||||
const latitude = waypoint.location[1];
|
||||
|
||||
const matchedAddress = coords.find(coord =>
|
||||
coord.position === undefined &&
|
||||
Math.abs(coord.latitude - latitude) <= tolerance &&
|
||||
Math.abs(coord.longitude - longitude) <= tolerance
|
||||
);
|
||||
if (matchedAddress)
|
||||
matchedAddress.position = waypoint.waypoint_index;
|
||||
}
|
||||
coords.sort((a, b) => {
|
||||
const posA = a.position !== undefined ? a.position : Infinity;
|
||||
const posB = b.position !== undefined ? b.position : Infinity;
|
||||
return posA - posB;
|
||||
});
|
||||
|
||||
return coords;
|
||||
} catch (err) {
|
||||
switch (err.response?.data?.code) {
|
||||
case 'NoTrips':
|
||||
throw new UserError('No trips found because input coordinates are not connected');
|
||||
case 'NotImplemented':
|
||||
throw new UserError('This request is not supported');
|
||||
case 'InvalidOptions':
|
||||
throw new UserError('Invalid options or too many coordinates');
|
||||
default:
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
|
@ -0,0 +1,33 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
describe('osrmConfig optimize()', function() {
|
||||
it('should send coords, receive OSRM response, and return a correctly ordered result', async function() {
|
||||
const result = await models.OsrmConfig.optimize([4, 3], 1, 2);
|
||||
|
||||
// Verifications
|
||||
expect(Array.isArray(result)).toBe(true);
|
||||
expect(result.length).toBe(4);
|
||||
|
||||
// Check the order
|
||||
expect(result[0].addressId).toBe(1);
|
||||
expect(result[1].addressId).toBe(4);
|
||||
expect(result[2].addressId).toBe(3);
|
||||
expect(result[3].addressId).toBe(2);
|
||||
|
||||
// Check the coordinates format
|
||||
expect(result[0].latitude).toBe('10.111111');
|
||||
expect(result[0].longitude).toBe('-74.111111');
|
||||
});
|
||||
|
||||
it('should throw an error if no addresses are provided', async function() {
|
||||
let error;
|
||||
try {
|
||||
await models.OsrmConfig.optimize([], null);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
|
||||
expect(error).toBeDefined();
|
||||
expect(error.message).toBe('No address has coordinates');
|
||||
});
|
||||
});
|
|
@ -29,35 +29,34 @@ module.exports = Self => {
|
|||
});
|
||||
|
||||
Self.sendToSupport = async(ctx, reason, additionalData) => {
|
||||
const userId = ctx.req.accessToken.userId;
|
||||
const emailUser =
|
||||
await Self.app.models.EmailUser.findById(ctx.req.accessToken.userId, {fields: ['email']});
|
||||
await Self.app.models.EmailUser.findById(userId, {fields: ['email']});
|
||||
|
||||
let html = `<strong>Motivo</strong>:<br/>${reason}<br/>`;
|
||||
html += `<strong>Usuario</strong>:<br/>${ctx.req.accessToken.userId} ${emailUser.email}<br/>`;
|
||||
let html = `<h2>Motivo: ${reason}</h2>`;
|
||||
html += `<h3>Usuario: ${userId} ${emailUser.email}</h3>`;
|
||||
html += `<h3>Additional Data:</h3>`;
|
||||
html += '<ul>';
|
||||
for (const [key, val] of Object.entries(additionalData)) {
|
||||
if (key !== 'config') html += `<li>${key}: ${parse(val)}</li>`;
|
||||
else {
|
||||
html += `<li>${key}:</li><ul style="list-style-type: square;">`;
|
||||
for (const [confKey, confVal] of Object.entries(val))
|
||||
html += `<li>${confKey}: ${parse(confVal)}</li>`;
|
||||
html += '</ul>';
|
||||
}
|
||||
}
|
||||
html += '</ul>';
|
||||
|
||||
delete additionalData.backError.config.headers.Authorization;
|
||||
const httpRequest = JSON.parse(additionalData?.httpRequest);
|
||||
|
||||
if (httpRequest)
|
||||
delete httpRequest.config.headers.Authorization;
|
||||
additionalData.httpRequest = httpRequest;
|
||||
|
||||
for (const data in additionalData)
|
||||
html += `<strong>${data}</strong>:<br/>${tryParse(additionalData[data])}<br/>`;
|
||||
|
||||
const subjectReason = httpRequest?.data?.error;
|
||||
const {message, path, name} = additionalData;
|
||||
await smtp.send({
|
||||
to: `${config.app.reportEmail}, ${emailUser.email}`,
|
||||
subject:
|
||||
'[Support-Salix] ' +
|
||||
additionalData?.frontPath + ' ' +
|
||||
subjectReason?.name + ':' +
|
||||
subjectReason?.message,
|
||||
subject: `[Support-Salix] ${path} ${name}: ${message}`,
|
||||
html
|
||||
});
|
||||
};
|
||||
|
||||
function tryParse(value) {
|
||||
function parse(value) {
|
||||
try {
|
||||
try {
|
||||
value = JSON.parse(value);
|
||||
|
|
|
@ -1,88 +0,0 @@
|
|||
const axios = require('axios');
|
||||
const UserError = require('vn-loopback/util/user-error');
|
||||
const moment = require('moment');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('sendOrders', {
|
||||
description: 'Sends a set of orders',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'tickets',
|
||||
type: ['number'],
|
||||
required: true
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: 'string',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/sendOrders`,
|
||||
verb: 'POST'
|
||||
}
|
||||
});
|
||||
Self.sendOrders = async tickets => {
|
||||
const config = await Self.app.models.QuadmindsApiConfig.findOne();
|
||||
if (!config) throw new UserError('Config params not set');
|
||||
|
||||
if (tickets.length > config.maxObjects)
|
||||
throw new UserError(`Quadminds does not support more than ${config.maxObjects} tickets`);
|
||||
|
||||
let poisData = [];
|
||||
let isOk;
|
||||
for (let offset = 0; !isOk; offset = offset + config.limit) {
|
||||
const pois = await axios.get(`${config.url}pois/search?limit=${config.limit}&offset=${offset}`, {
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'X-Saas-Apikey': config.key
|
||||
}
|
||||
});
|
||||
pois.data.data.length ? poisData.push(...pois.data.data) : isOk = true;
|
||||
}
|
||||
|
||||
const poiMap = new Map(poisData.map(poi => [poi.code, poi._id]));
|
||||
|
||||
let orders = await Self.rawSql(`
|
||||
SELECT a.id poiCode,
|
||||
t.id code,
|
||||
t.shipped date,
|
||||
'PEDIDO' operation,
|
||||
t.totalWithVat totalAmount,
|
||||
t.totalWithoutVat totalAmountWithoutTaxes,
|
||||
SUM(sv.volume) volume
|
||||
FROM ticket t
|
||||
JOIN address a ON a.id = t.addressFk
|
||||
JOIN saleVolume sv ON sv.ticketFk = t.id
|
||||
WHERE t.id IN (?)
|
||||
GROUP BY t.id
|
||||
`, [tickets]);
|
||||
|
||||
// Transformo code en string ya que lo obtenermos como integer
|
||||
orders = orders.map(order => {
|
||||
return {
|
||||
...order,
|
||||
poiId: poiMap.get(order.poiCode.toString()) || undefined,
|
||||
code: order.code.toString(),
|
||||
date: moment(order.date).format('YYYY-MM-DD'),
|
||||
totalAmount: order.totalAmount || undefined,
|
||||
totalAmountWithoutTaxes: order.totalAmountWithoutTaxes || undefined,
|
||||
timeWindow: [{
|
||||
from: config.orderTimeFrom,
|
||||
to: config.orderTimeTo
|
||||
}],
|
||||
orderMeasures: [{
|
||||
constraintId: 3, // Volumen
|
||||
value: order.volume
|
||||
}]
|
||||
};
|
||||
});
|
||||
|
||||
await axios.post(`${config.url}orders`, orders, {
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'X-Saas-Apikey': config.key
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
|
@ -1,87 +0,0 @@
|
|||
const axios = require('axios');
|
||||
const UserError = require('vn-loopback/util/user-error');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('sendPois', {
|
||||
description: 'Sends a set of pois',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'tickets',
|
||||
type: ['number'],
|
||||
required: true
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: 'string',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/sendPois`,
|
||||
verb: 'POST'
|
||||
}
|
||||
});
|
||||
Self.sendPois = async tickets => {
|
||||
const config = await Self.app.models.QuadmindsApiConfig.findOne();
|
||||
if (!config) throw new UserError('Config params not set');
|
||||
|
||||
if (tickets.length > config.maxObjects)
|
||||
throw new UserError(`Quadminds does not support more than ${config.maxObjects} tickets`);
|
||||
|
||||
let pois = await Self.rawSql(`
|
||||
WITH deliveryNotes AS (
|
||||
SELECT t.id, t.routeFk, tn.description
|
||||
FROM ticket t
|
||||
JOIN ticketObservation tn ON tn.ticketFk = t.id
|
||||
JOIN observationType ot ON ot.id = tn.observationTypeFk
|
||||
WHERE ot.code = 'delivery'
|
||||
)
|
||||
SELECT a.id code,
|
||||
c.socialName name,
|
||||
IF(ABS(a.latitude - ROUND(a.latitude)) < 0.000001, NULL, a.latitude) latitude,
|
||||
IF(ABS(a.longitude - ROUND(a.longitude)) < 0.000001, NULL, a.longitude) longitude,
|
||||
a.street,
|
||||
a.city locality,
|
||||
p.name state,
|
||||
co.name country,
|
||||
CONCAT_WS(', ', IFNULL(a.street, ''), IFNULL(a.city, ''), IFNULL(p.name, '')) longAddress,
|
||||
CONCAT(IFNULL(a.mobile, c.mobile)) phoneNumber,
|
||||
dn.description poiDeliveryComments,
|
||||
c.email email
|
||||
FROM ticket t
|
||||
JOIN address a ON a.id = t.addressFk
|
||||
JOIN province p ON p.id = a.provinceFk
|
||||
JOIN country co ON co.id = p.countryFk
|
||||
JOIN client c ON c.id = t.clientFk
|
||||
LEFT JOIN deliveryNotes dn ON dn.id = t.id
|
||||
WHERE t.id IN (?)
|
||||
GROUP BY t.id
|
||||
`, [tickets]);
|
||||
|
||||
// Transformo code en string ya que lo obtenermos como integer
|
||||
pois = pois.map(poi => {
|
||||
return {
|
||||
...poi,
|
||||
code: poi.code.toString(),
|
||||
latitude: poi.latitude || undefined,
|
||||
longitude: poi.longitude || undefined,
|
||||
address: {
|
||||
street: poi.street || undefined,
|
||||
locality: poi.locality || undefined,
|
||||
state: poi.state || undefined,
|
||||
country: poi.country || undefined
|
||||
},
|
||||
poiDeliveryComments: poi.poiDeliveryComments || undefined,
|
||||
phoneNumber: poi.phoneNumber || undefined,
|
||||
email: poi.email || undefined
|
||||
};
|
||||
});
|
||||
|
||||
await axios.post(`${config.url}pois`, pois, {
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'X-Saas-Apikey': config.key
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
|
@ -88,6 +88,9 @@
|
|||
"Language": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"OsrmConfig": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"Machine": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
|
@ -121,9 +124,6 @@
|
|||
"Province": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"QuadmindsApiConfig": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"Autonomy": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
module.exports = Self => {
|
||||
require('../methods/osrm-config/optimize')(Self);
|
||||
};
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "OsrmConfig",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "osrmConfig"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"required": true
|
||||
},
|
||||
"url": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"tolerance": {
|
||||
"type": "number",
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
module.exports = Self => {
|
||||
require('../methods/quadminds-api-config/sendPois')(Self);
|
||||
require('../methods/quadminds-api-config/sendOrders')(Self);
|
||||
};
|
|
@ -1,34 +0,0 @@
|
|||
{
|
||||
"name": "QuadmindsApiConfig",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "quadmindsApiConfig"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"required": true
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
},
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"maxObjects": {
|
||||
"type": "number"
|
||||
},
|
||||
"limit": {
|
||||
"type": "number"
|
||||
},
|
||||
"orderTimeFrom": {
|
||||
"type": "string"
|
||||
},
|
||||
"orderTimeTo": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2128,7 +2128,7 @@ INSERT INTO `ACL` VALUES (746,'Claim','getSummary','READ','ALLOW','ROLE','claimV
|
|||
INSERT INTO `ACL` VALUES (747,'CplusRectificationType','*','READ','ALLOW','ROLE','administrative',NULL);
|
||||
INSERT INTO `ACL` VALUES (748,'SiiTypeInvoiceOut','*','READ','ALLOW','ROLE','salesPerson',NULL);
|
||||
INSERT INTO `ACL` VALUES (749,'InvoiceCorrectionType','*','READ','ALLOW','ROLE','salesPerson',NULL);
|
||||
INSERT INTO `ACL` VALUES (750,'InvoiceOut','transferInvoice','WRITE','ALLOW','ROLE','administrative',NULL);
|
||||
INSERT INTO `ACL` VALUES (750,'InvoiceOut','transfer','WRITE','ALLOW','ROLE','administrative',NULL);
|
||||
INSERT INTO `ACL` VALUES (751,'Application','executeProc','*','ALLOW','ROLE','employee',NULL);
|
||||
INSERT INTO `ACL` VALUES (752,'Application','executeFunc','*','ALLOW','ROLE','employee',NULL);
|
||||
INSERT INTO `ACL` VALUES (753,'NotificationSubscription','getList','READ','ALLOW','ROLE','employee',NULL);
|
||||
|
|
|
@ -428,10 +428,10 @@ INSERT INTO `vn`.`clientConfig`(`id`, `riskTolerance`, `maxCreditRows`, `maxPric
|
|||
|
||||
INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `provinceFk`, `phone`, `mobile`, `isActive`, `clientFk`, `agencyModeFk`, `longitude`, `latitude`, `isEqualizated`, `isDefaultAddress`)
|
||||
VALUES
|
||||
(1, 'Bruce Wayne', '1007 Mountain Drive, Gotham', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1101, 2, NULL, NULL, 0, 1),
|
||||
(2, 'Petter Parker', '20 Ingram Street', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1102, 2, NULL, NULL, 0, 1),
|
||||
(3, 'Clark Kent', '344 Clinton Street', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1103, 2, NULL, NULL, 0, 1),
|
||||
(4, 'Tony Stark', '10880 Malibu Point', 'Gotham', 46460, 1, 1111111111, 222222222, 1 , 1104, 2, NULL, NULL, 0, 1),
|
||||
(1, 'Bruce Wayne', '1007 Mountain Drive, Gotham', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1101, 2, -74.1111111, 10.1111111, 0, 1),
|
||||
(2, 'Petter Parker', '20 Ingram Street', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1102, 2, -74.2222222, 10.2222222, 0, 1),
|
||||
(3, 'Clark Kent', '344 Clinton Street', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1103, 2, -74.3333333, 10.3333333, 0, 1),
|
||||
(4, 'Tony Stark', '10880 Malibu Point', 'Gotham', 46460, 1, 1111111111, 222222222, 1 , 1104, 2, -74.4444444, 10.4444444, 0, 1),
|
||||
(5, 'Max Eisenhardt', 'Unknown Whereabouts', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1105, 2, NULL, NULL, 0, 1),
|
||||
(6, 'DavidCharlesHaller', 'Evil hideout', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1106, 2, NULL, NULL, 0, 1),
|
||||
(7, 'Hank Pym', 'Anthill', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1107, 2, NULL, NULL, 0, 1),
|
||||
|
@ -462,7 +462,7 @@ INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `pr
|
|||
(120, 'Somewhere in Montortal', 'address 20', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0),
|
||||
(121, 'the bat cave', 'address 21', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1101, 2, NULL, NULL, 0, 0),
|
||||
(122, 'NY roofs', 'address 22', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1102, 2, NULL, NULL, 0, 0),
|
||||
(123, 'The phone box', 'address 23', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1103, 2, NULL, NULL, 0, 0),
|
||||
(123, 'The phone box', 'address 23', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1103, 2, -74.555555, 10.555555, 0, 0),
|
||||
(124, 'Stark tower Gotham', 'address 24', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1104, 2, NULL, NULL, 0, 0),
|
||||
(125, 'The plastic cell', 'address 25', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1105, 2, NULL, NULL, 0, 0),
|
||||
(126, 'Many places', 'address 26', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1106, 2, NULL, NULL, 0, 0),
|
||||
|
@ -1516,21 +1516,24 @@ INSERT INTO `vn`.`travel`(`id`,`shipped`, `landed`, `warehouseInFk`, `warehouseO
|
|||
(8, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 1, 1, 50.00, 500, 'eight travel', 1, 2, 10, FALSE, NULL),
|
||||
(10, DATE_ADD(util.VN_CURDATE(), INTERVAL +5 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL +5 DAY), 5, 1, 1, 50.00, 500, 'nineth travel', 1, 2, 10, TRUE, 2),
|
||||
(11, util.VN_CURDATE() - INTERVAL 1 DAY , util.VN_CURDATE(), 6, 3, 0, 50.00, 500, 'eleventh travel', 1, 2, 4, FALSE, NULL),
|
||||
(12, util.VN_CURDATE() , util.VN_CURDATE() + INTERVAL 1 DAY, 6, 3, 0, 50.00, 500, 'eleventh travel', 1, 2, 4, FALSE, NULL);
|
||||
(12, util.VN_CURDATE() , util.VN_CURDATE() + INTERVAL 1 DAY, 6, 3, 0, 50.00, 500, 'eleventh travel', 1, 2, 4, FALSE, NULL),
|
||||
(13, util.VN_CURDATE() - INTERVAL 1 MONTH - INTERVAL 1 DAY, util.VN_CURDATE() - INTERVAL 1 MONTH, 6, 3, 0, 50.00, 500, 'eleventh travel', 1, 2, 4, FALSE, NULL);
|
||||
|
||||
INSERT INTO `vn`.`entry`(`id`, `supplierFk`, `created`, `travelFk`, `isConfirmed`, `companyFk`, `invoiceNumber`, `reference`, `isExcludedFromAvailable`, `evaNotes`, `typeFk`)
|
||||
VALUES
|
||||
(1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 1, 442, 'IN2001', 'Movement 1', 0, '', 'packaging'),
|
||||
(2, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 0, 442, 'IN2002', 'Movement 2', 0, 'observation two', 'product'),
|
||||
(1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 1, 442, 'IN2001', 'Movement 1', 0, '', 'packaging'),
|
||||
(2, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 0, 442, 'IN2002', 'Movement 2', 0, 'observation two' , 'product'),
|
||||
(3, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 3, 0, 442, 'IN2003', 'Movement 3', 0, 'observation three', 'product'),
|
||||
(4, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 0, 69, 'IN2004', 'Movement 4', 0, 'observation four', 'product'),
|
||||
(5, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 0, 442, 'IN2005', 'Movement 5', 0, 'observation five', 'product'),
|
||||
(6, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 6, 0, 442, 'IN2006', 'Movement 6', 0, 'observation six', 'product'),
|
||||
(4, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 0, 69, 'IN2004', 'Movement 4', 0, 'observation four' , 'product'),
|
||||
(5, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 0, 442, 'IN2005', 'Movement 5', 0, 'observation five' , 'product'),
|
||||
(6, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 6, 0, 442, 'IN2006', 'Movement 6', 0, 'observation six' , 'product'),
|
||||
(7, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2007', 'Movement 7', 0, 'observation seven', 'product'),
|
||||
(8, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2008', 'Movement 8', 1, '', 'product'),
|
||||
(9, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 9', 1, '', 'product'),
|
||||
(10, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 10', 1, '', 'product'),
|
||||
(99, 69, util.VN_CURDATE() - INTERVAL 1 MONTH, 11, 0, 442, 'IN2009', 'Movement 99', 0, '', 'product');
|
||||
(8, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2008', 'Movement 8', 1, '', 'product'),
|
||||
(9, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 9', 1, '', 'product'),
|
||||
(10, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2010', 'Movement 10',1, '', 'product'),
|
||||
(11, 4, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH), 1, 1, 442, 'IN2011', 'Movement 11',0, '', 'product'),
|
||||
(12, 4, util.VN_CURDATE() - INTERVAL 1 MONTH, 13, 1, 442, 'IN2012', 'Movement 12',0, '', 'product'),
|
||||
(99, 69, util.VN_CURDATE() - INTERVAL 1 MONTH, 11, 0, 442, 'IN2009', 'Movement 99',0, '', 'product');
|
||||
|
||||
INSERT INTO `vn`.`entryConfig` (`defaultEntry`, `inventorySupplierFk`, `defaultSupplierFk`)
|
||||
VALUES (2, 4, 1);
|
||||
|
@ -1570,7 +1573,9 @@ INSERT INTO `bs`.`waste`(`buyerFk`, `year`, `week`, `itemFk`, `itemTypeFk`, `sal
|
|||
(13, 7, 1, 50, 0, 3, 1, 2.000, 2.000, 0.000, 1, 1, 'packing', NULL, 0.00, 99.6, 99.4, 0, 1, 0, 4, util.VN_CURDATE()),
|
||||
(14, 7, 2, 5, 0, 3, 1, 2.000, 2.000, 0.000, 10, 10, 'grouping', NULL, 0.00, 7.30, 7.00, 0, 1, 0, 4, util.VN_CURDATE()),
|
||||
(15, 7, 4, 1.25, 0, 3, 1, 2.000, 2.000, 0.000, 10, 10, 'grouping', NULL, 0.00, 1.75, 1.67, 0, 1, 0, 4, util.VN_CURDATE()),
|
||||
(16, 99,1,50.0000, 5000, 4, 1, 1.500, 1.500, 0.000, 1, 1, 'packing', NULL, 0.00, 99.60, 99.40, 0, 1, 0, 1.00, '2024-07-30 08:13:51.000');
|
||||
(16, 99,1,50.0000, 5000, 4, 1, 1.500, 1.500, 0.000, 1, 1, 'packing', NULL, 0.00, 99.60, 99.40, 0, 1, 0, 1.00, '2024-07-30 08:13:51.000'),
|
||||
(17, 11, 1, 50, 5000, 4, 1, 1.500, 1.500, 0.000, 1, 1, 'packing', NULL, 0.00, 99.6, 99.4, 0, 1, 0, 1, util.VN_CURDATE() - INTERVAL 2 MONTH),
|
||||
(18, 12, 1, 50, 5000, 4, 1, 1.500, 1.500, 0.000, 1, 1, 'grouping', NULL, 0.00, 99.6, 99.4, 0, 1, 0, 1, util.VN_CURDATE() - INTERVAL 2 MONTH);
|
||||
|
||||
INSERT INTO `hedera`.`order`(`id`, `date_send`, `customer_id`, `delivery_method_id`, `agency_id`, `address_id`, `company_id`, `note`, `source_app`, `confirmed`,`total`, `date_make`, `first_row_stamp`, `confirm_date`)
|
||||
VALUES
|
||||
|
@ -1920,7 +1925,7 @@ INSERT INTO `vn`.`claimDestination`(`id`, `description`, `addressFk`)
|
|||
|
||||
INSERT INTO `vn`.`claimDevelopment`(`id`, `claimFk`, `claimResponsibleFk`, `workerFk`, `claimReasonFk`, `claimResultFk`, `claimRedeliveryFk`, `claimDestinationFk`)
|
||||
VALUES
|
||||
(1, 1, 1, 21, 1, 1, 2, 5),
|
||||
(1, 1, 1, 21, 7, 1, 2, 5),
|
||||
(2, 1, 2, 21, 7, 2, 2, 5),
|
||||
(3, 2, 7, 21, 9, 3, 2, 5),
|
||||
(4, 3, 7, 21, 15, 8, 2, 5),
|
||||
|
@ -4035,3 +4040,15 @@ INSERT IGNORE INTO vn.saySimpleConfig (url, defaultChannel)
|
|||
|
||||
INSERT INTO vn.workerIrpf (workerFk,spouseNif, geographicMobilityDate)
|
||||
VALUES (1106,'26493101E','2019-09-20');
|
||||
|
||||
INSERT INTO vn.referenceRate (currencyFk, dated, value)
|
||||
VALUES (2, '2000-12-01', 1.0495),
|
||||
(2, '2001-01-01', 1.0531),
|
||||
(2, '2001-02-01', 7.6347);
|
||||
|
||||
INSERT IGNORE INTO vn.osrmConfig (id,url,tolerance)
|
||||
VALUES (1,'https://router.project-osrm.org', 0.002);
|
||||
|
||||
INSERT IGNORE INTO vn.inventoryConfig
|
||||
SET id = 1,
|
||||
supplierFk = 4;
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
CREATE OR REPLACE DEFINER=`root`@`localhost`
|
||||
SQL SECURITY DEFINER
|
||||
VIEW `bi`.`rotacion`
|
||||
AS SELECT `ic`.`itemFk` AS `Id_Article`,
|
||||
`ic`.`warehouseFk` AS `warehouse_id`,
|
||||
`ic`.`quantity` AS `total`,
|
||||
`ic`.`rotation` AS `rotacion`,
|
||||
`ic`.`cm3` AS `cm3`,
|
||||
`ic`.`storage` AS `almacenaje`,
|
||||
`ic`.`handling` AS `manipulacion`,
|
||||
`ic`.`extraCharge` AS `auxiliar`,
|
||||
`ic`.`wasted` AS `mermas`,
|
||||
`ic`.`cm3delivery` AS `cm3reparto`,
|
||||
`ic`.`grams` AS `grams`
|
||||
FROM `vn`.`itemCost` `ic`
|
|
@ -4,10 +4,10 @@ BEGIN
|
|||
/**
|
||||
* Traslada la info de contabilidad relacionada con las facturas recibidas
|
||||
*
|
||||
* @vInvoiceInFk Factura recibida
|
||||
* @vXDiarioFk Id tabla XDiario
|
||||
* @param vInvoiceInFk Factura recibida
|
||||
* @param vXDiarioFk Id tabla XDiario
|
||||
*/
|
||||
DECLARE vInvoiceInOriginalFk INT;
|
||||
DECLARE vInvoiceInOriginalFk INT;
|
||||
DECLARE vDone BOOL DEFAULT FALSE;
|
||||
DECLARE vBase DOUBLE;
|
||||
DECLARE vVat DOUBLE;
|
||||
|
@ -205,9 +205,9 @@ BEGIN
|
|||
WHERE correctingFk = vInvoiceInFk;
|
||||
|
||||
IF vInvoiceInOriginalFk THEN
|
||||
|
||||
UPDATE movContaIVA mci
|
||||
JOIN vn.invoiceInRefund iir ON iir.invoiceInRefundFk = vInvoiceInFk
|
||||
JOIN vn.invoiceInCorrection iic ON iic.correctingFk = vInvoiceInFk
|
||||
JOIN vn.siiTypeInvoiceIn st ON st.id = iic.siiTypeInvoiceInFk
|
||||
JOIN (SELECT issued,
|
||||
SUM(sub.taxableBase) taxableBase,
|
||||
SUM(ROUND((sub.taxableBase * sub.PorcentajeIva) / 100 , 2)) vat
|
||||
|
@ -216,7 +216,7 @@ BEGIN
|
|||
ti.PorcentajeIva
|
||||
FROM vn.invoiceIn i
|
||||
JOIN vn.invoiceInTax iit ON iit.invoiceInFk = i.id
|
||||
JOIN sage.TiposIva ti ON ti.CodigoIva = iit.taxTypeSageFk
|
||||
JOIN TiposIva ti ON ti.CodigoIva = iit.taxTypeSageFk
|
||||
WHERE i.id = vInvoiceInOriginalFk
|
||||
GROUP BY ti.CodigoIva)sub
|
||||
)invoiceInOriginal
|
||||
|
@ -229,7 +229,6 @@ BEGIN
|
|||
mci.CuotaIvaOriginal = invoiceInOriginal.vat,
|
||||
mci.ClaveOperacionFactura = co.ClaveOperacionFactura_
|
||||
WHERE mci.id = vXDiarioFk;
|
||||
|
||||
END IF;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
|
|
@ -169,6 +169,7 @@ BEGIN
|
|||
UPDATE movContaIVA mci
|
||||
JOIN vn.invoiceOut i ON i.id = vInvoiceOutCorrectedFk
|
||||
JOIN vn.invoiceCorrection ic ON ic.correctedFk = vInvoiceOutCorrectedFk
|
||||
JOIN vn.siiTypeInvoiceOut st ON st.id = ic.siiTypeInvoiceOutFk
|
||||
JOIN (SELECT SUM(IF(IFNULL(e.vatFk, TRUE), iot.taxableBase, 0)) taxableBase,
|
||||
SUM(IF(IFNULL(e.vatFk, TRUE), iot.vat, 0)) vat,
|
||||
SUM(IF(IFNULL(e.vatFk, TRUE), 0, iot.vat)) equ
|
||||
|
@ -177,8 +178,8 @@ BEGIN
|
|||
WHERE iot.invoiceOutFk = vInvoiceOutCorrectedFk
|
||||
) tax
|
||||
JOIN ClavesOperacion co ON co.Descripcion = 'Factura rectificativa'
|
||||
SET mci.TipoRectificativa = 2,
|
||||
mci.ClaseAbonoRectificativas = 1,
|
||||
SET mci.TipoRectificativa = ic.cplusRectificationTypeFk,
|
||||
mci.ClaseAbonoRectificativas = REGEXP_REPLACE(st.`code`, '[^0-9]', ''),
|
||||
mci.FechaFacturaOriginal = i.issued,
|
||||
mci.FechaOperacion = i.issued,
|
||||
mci.BaseImponibleOriginal = tax.taxableBase,
|
||||
|
|
|
@ -11,6 +11,7 @@ BEGIN
|
|||
DECLARE vCurrentCommission INT;
|
||||
DECLARE vIsNotEUR INT;
|
||||
DECLARE vLastEntryFk INT;
|
||||
DECLARE vLanded INT;
|
||||
|
||||
SELECT count(*) INTO vIsNotEUR
|
||||
FROM currency c
|
||||
|
@ -26,23 +27,25 @@ BEGIN
|
|||
|
||||
RETURN IFNULL(vCommission, 0);
|
||||
ELSE
|
||||
SELECT landed INTO vLanded
|
||||
FROM travel
|
||||
WHERE id = vTravelFk;
|
||||
|
||||
SELECT e.id INTO vLastEntryFk
|
||||
FROM `entry` e
|
||||
JOIN travel tr ON tr.id = e.travelFk
|
||||
WHERE e.supplierFk = vSupplierFk
|
||||
ORDER BY tr.landed DESC
|
||||
LIMIT 1;
|
||||
WHERE e.supplierFk = vSupplierFk
|
||||
ORDER BY (vLanded <= tr.landed), tr.landed DESC
|
||||
LIMIT 1;
|
||||
|
||||
IF vLastEntryFk THEN
|
||||
SELECT commission INTO vCurrentCommission
|
||||
FROM `entry`
|
||||
WHERE id = vLastEntryFk;
|
||||
|
||||
ELSE
|
||||
SELECT commission INTO vCurrentCommission
|
||||
FROM supplier s
|
||||
WHERE s.id = vSupplierFk;
|
||||
|
||||
END IF;
|
||||
|
||||
RETURN vCurrentCommission;
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`inventoryFailureAdd`()
|
||||
BEGIN
|
||||
|
||||
DECLARE done BOOL DEFAULT FALSE;
|
||||
DECLARE vTicketFk INT;
|
||||
|
||||
DECLARE rs CURSOR FOR
|
||||
SELECT id FROM vn.ticket
|
||||
WHERE shipped = util.yesterday()
|
||||
AND clientFk = 400
|
||||
AND warehouseFk IN (1,44);
|
||||
|
||||
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
|
||||
|
||||
OPEN rs;
|
||||
|
||||
FETCH rs INTO vTicketFk;
|
||||
|
||||
WHILE NOT done DO
|
||||
|
||||
INSERT INTO vn.inventoryFailure(dated, itemFk, quantity, value, warehouseFk, throwerFk)
|
||||
SELECT t.shipped,
|
||||
s.itemFk,
|
||||
s.quantity,
|
||||
b.buyingValue + b.freightValue + b.packageValue + b.comissionValue,
|
||||
t.warehouseFk,
|
||||
w.id
|
||||
FROM vn.ticket t
|
||||
JOIN vn.sale s ON s.ticketFk = t.id
|
||||
LEFT JOIN cache.last_buy lb ON lb.warehouse_id = t.warehouseFk AND item_id = s.itemFk
|
||||
LEFT JOIN vn.buy b ON b.id = lb.buy_id
|
||||
LEFT JOIN vn.worker w ON w.code = LEFT(s.concept, 3)
|
||||
WHERE t.id = vTicketFk
|
||||
AND s.quantity > 0;
|
||||
|
||||
FETCH rs INTO vTicketFk;
|
||||
|
||||
END WHILE;
|
||||
|
||||
|
||||
CLOSE rs;
|
||||
|
||||
|
||||
|
||||
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -43,7 +43,7 @@ BEGIN
|
|||
ii.cplusTaxBreakFk,
|
||||
ii.cplusSubjectOpFk,
|
||||
ii.siiTypeInvoiceInFk,
|
||||
ii.cplusRectificationTypeFk,
|
||||
ic.cplusRectificationTypeFk,
|
||||
ii.booked,
|
||||
IFNULL(a.isUeeMember, c.isUeeMember) isUeeMember,
|
||||
(c.id = cc.id) isSameCountry,
|
||||
|
@ -66,6 +66,7 @@ BEGIN
|
|||
e.name expenseName
|
||||
FROM invoiceIn ii
|
||||
JOIN supplier s ON s.id = ii.supplierFk
|
||||
LEFT JOIN invoiceInCorrection ic ON ic.correctingFk = ii.id
|
||||
LEFT JOIN province p ON p.id = s.provinceFk
|
||||
LEFT JOIN autonomy a ON a.id = p.autonomyFk
|
||||
JOIN country c ON c.id = s.countryFk
|
||||
|
|
|
@ -164,10 +164,6 @@ BEGIN
|
|||
SET itemFk = vItemNew
|
||||
WHERE itemFk = vItemOld;
|
||||
|
||||
UPDATE inventoryFailure
|
||||
SET itemFk = vItemNew
|
||||
WHERE itemFk = vItemOld;
|
||||
|
||||
UPDATE genericAllocation
|
||||
SET itemFk = vItemNew
|
||||
WHERE itemFk = vItemOld;
|
||||
|
|
|
@ -52,7 +52,8 @@ BEGIN
|
|||
IFNULL(dest.nickname, origin.nickname) nickname,
|
||||
dest.landed,
|
||||
dest.preparation,
|
||||
origin.departmentFk
|
||||
origin.departmentFk,
|
||||
origin.saleClonedFk
|
||||
FROM (
|
||||
SELECT s.ticketFk,
|
||||
c.salesPersonFk workerFk,
|
||||
|
@ -73,11 +74,13 @@ BEGIN
|
|||
t.warehouseFk,
|
||||
t.companyFk,
|
||||
t.agencyModeFk,
|
||||
wd.departmentFk
|
||||
wd.departmentFk,
|
||||
sc.saleClonedFk
|
||||
FROM ticket t
|
||||
JOIN client c ON c.id = t.clientFk
|
||||
JOIN workerDepartment wd ON wd.workerFk = c.salesPersonFk
|
||||
JOIN sale s ON s.ticketFk = t.id
|
||||
LEFT JOIN saleCloned sc ON sc.saleClonedFk = s.id
|
||||
JOIN saleVolume sv ON sv.saleFk = s.id
|
||||
JOIN item i ON i.id = s.itemFk
|
||||
JOIN ticketState ts ON ts.ticketFk = t.id
|
||||
|
|
|
@ -3,24 +3,30 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`invoiceIn_afterUpdate`
|
|||
AFTER UPDATE ON `invoiceIn`
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
IF NEW.issued != OLD.issued
|
||||
OR NEW.currencyFk != OLD.currencyFk THEN
|
||||
DECLARE vIsEuro BOOL;
|
||||
|
||||
SELECT `code` = 'EUR' INTO vIsEuro
|
||||
FROM currency
|
||||
WHERE id = NEW.currencyFk;
|
||||
|
||||
IF (NOT NEW.issued <=> OLD.issued
|
||||
OR NEW.currencyFk <> OLD.currencyFk) THEN
|
||||
|
||||
UPDATE invoiceInTax iit
|
||||
JOIN invoiceIn ii ON ii.id = iit.invoiceInFk
|
||||
LEFT JOIN referenceRate rr ON rr.dated = ii.issued
|
||||
AND rr.currencyFk = ii.currencyFk
|
||||
SET iit.taxableBase = IF(iit.foreignValue IS NULL, iit.taxableBase, iit.foreignValue / rr.value)
|
||||
SET iit.taxableBase = IF(vIsEuro, iit.taxableBase, iit.foreignValue / rr.value),
|
||||
iit.foreignValue = IF(vIsEuro, NULL, iit.foreignValue)
|
||||
WHERE ii.id = NEW.id;
|
||||
|
||||
UPDATE invoiceInDueDay iidd
|
||||
JOIN invoiceIn ii ON ii.id = iidd.invoiceInFk
|
||||
LEFT JOIN referenceRate rr ON rr.dated = ii.issued
|
||||
AND rr.currencyFk = ii.currencyFk
|
||||
SET iidd.amount = IF(iidd.foreignValue IS NULL, iidd.amount, iidd.foreignValue / rr.value)
|
||||
SET iidd.amount = IF(vIsEuro, iidd.amount, iidd.foreignValue / rr.value),
|
||||
iidd.foreignValue = IF(vIsEuro, NULL, iidd.foreignValue)
|
||||
WHERE ii.id = NEW.id;
|
||||
|
||||
END IF;
|
||||
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
|
|
@ -0,0 +1,185 @@
|
|||
CREATE TABLE IF NOT EXISTS `vn`.`sim` (
|
||||
`code` VARCHAR(25) COMMENT 'No se ha puesto BIGINT por incompatibilidad con Access',
|
||||
`line` VARCHAR(15) NOT NULL CHECK (`line` REGEXP '^[0-9]+$'),
|
||||
`ext` INT(4) NOT NULL,
|
||||
`pin` VARCHAR(4) NOT NULL CHECK (`pin` REGEXP '^[0-9]+$'),
|
||||
`puk` VARCHAR(15) NOT NULL CHECK (`pin` REGEXP '^[0-9]+$'),
|
||||
PRIMARY KEY (`code`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
ALTER TABLE vn.deviceProductionUser CHANGE simSerialNumber simFk VARCHAR(25) DEFAULT NULL NULL;
|
||||
ALTER TABLE vn.deviceProductionUser MODIFY COLUMN simFk VARCHAR(25) DEFAULT NULL NULL;
|
||||
|
||||
INSERT IGNORE INTO `vn`.`sim` (`line`, `ext`, `pin`, `code`, `puk`) VALUES
|
||||
('621188151', 2209, '1486', '3456985220092508','14213470'),
|
||||
('621188152', 2210, '8765', '3456985220092509','99473093'),
|
||||
('621188153', 2211, '3064', '3456985220092510','52967210'),
|
||||
('621188759', 2081, '3700', '3456985220123637','56600999'),
|
||||
('621188760', 2082, '3259', '345698522023638','87492404'),
|
||||
('621188761', 2083, '2790', '3456985220123639','94009456'),
|
||||
('621188762', 2084, '2480', '3456985220123644','1484999'),
|
||||
('621188763', 2085, '6876', '3456985220123641','36577064'),
|
||||
('621188766', 2086, '7775', '3456985220123642','80761698'),
|
||||
('621188769', 2088, '4027', '3456985220123643','37921712'),
|
||||
('621188771', 2089, '8797', '3456985220123640','63092540'),
|
||||
('621188772', 2090, '8404', '3456985220123645','21014997'),
|
||||
('621188773', 2091, '5481', '3456985220123646','16317277'),
|
||||
('621188774', 2092, '9632', '3456985220123647','22235994'),
|
||||
('621188775', 2093, '4654', '3456985220123648','28506486'),
|
||||
('621188838', 2094, '1392', '3456985220123649','29498627'),
|
||||
('621188839', 2095, '7774', '3456985220123650','46263490'),
|
||||
('621188840', 2096, '7304', '3456985220123658','8212044'),
|
||||
('621188841', 2097, '5569', '3456985220123652','81597658'),
|
||||
('621188842', 2098, '4944', '3456985220123653','24961501'),
|
||||
('621188843', 2099, '5142', '3456985220123654','17035634'),
|
||||
('621188844', 2111, '7245', '3456985220123655','90231951'),
|
||||
('621188846', 2110, '6590', '3456985220123656','72201537'),
|
||||
('667680207', 2564, '4042', '34569832200759166','48401979'),
|
||||
('667680315', 2565, '7143', '34569832200759372','32143252'),
|
||||
('667680318', 2566, '6342', '34569832200759364','39597112'),
|
||||
('667680413', 2567, '5580', '34569832200759356','32786992'),
|
||||
('667680463', 2568, '0171', '34569832200759349','34240853'),
|
||||
('667688217', 2569, '2500', '34569832200759331','5687589'),
|
||||
('633603945', 2212, '7129', '34569832200759323','51554019'),
|
||||
('622130186', 2213, '4826', '34569832200759307','19623551'),
|
||||
('633973424', 2214, '8535', '34569832200759299','94619307'),
|
||||
('633703828', 2215, '8628', '34569832200759281','22468012'),
|
||||
('622025110', 2216, '2399', '34569832200759273','34602918'),
|
||||
('622924867', 2217, '5665', '34569832200759265','26920216'),
|
||||
('722409630', 2218, '5211', '34569832200759240','93750137'),
|
||||
('623590529', 2219, '0493', '34569832200759208','47077088'),
|
||||
('633243462', 2220, '6902', '34569832200759174','6421962'),
|
||||
('633047286', 2221, '5592', '34569832200759182','32069439'),
|
||||
('744716801', 2112, '9184', '34569832200759190','57049814'),
|
||||
('655995021', 2131, '8896', '34569852202049093','19497356'),
|
||||
('685522718', 2132, '1955', '34569852202049101','28519879'),
|
||||
('674587213', 2994, '2006', '34569332200223743','62360135'),
|
||||
('674587227', 2993, '9271', '34569332200223750','81628192'),
|
||||
('674587229', 2993, '0900', '34569332200223768','91119071'),
|
||||
('674587231', 2992, '5007', '34569332200223776','45826232'),
|
||||
('674587234', 2991, '1378', '34569332200223784','91245744'),
|
||||
('674587240', 2990, '0905', '34569332200223792','13083224'),
|
||||
('674587245', 2989, '9059', '34569332200223800','15291807'),
|
||||
('674587250', 2988, '8188', '34569332200223818','83017918'),
|
||||
('674587254', 2987, '2962', '34569332200223826','92809271'),
|
||||
('674587256', 2986, '0358', '34569332200223834','81067040'),
|
||||
('674592713', 2570, '2537', '34569332200230672','82325850'),
|
||||
('697832478', 2579, '0936', '34568732200494825','49658372'),
|
||||
('697832176', 2571, '5944', '34568732200494742','19039461'),
|
||||
('697832477', 2572, '5138', '34568732200494759','25712504'),
|
||||
('697832178', 2573, '4597', '34568732200494767','66241760'),
|
||||
('697832182', 2574, '9241', '34568732200494775','07342562'),
|
||||
('697832196', 2575, '2995', '34568732200494783','53929026'),
|
||||
('697832214', 2576, '7434', '34568732200494791','49698432'),
|
||||
('697832230', 2577, '7004', '34568732200494809','21578612'),
|
||||
('697832235', 2578, '9674', '34568732200494817','93090700'),
|
||||
('673420375', 2599, '5430', '34562052300117259','35911412'),
|
||||
('673420367', 2598, '8402', '34562052300117242','924654'),
|
||||
('673420361', 2597, '5125', '34562052300117234','12027970'),
|
||||
('673420355', 2596, '5069', '34562052300117226','34978149'),
|
||||
('673420348', 2595, '8911', '34562052300117218','4228121'),
|
||||
('673420346', 2594, '2461', '34562052300117200','67670772'),
|
||||
('673420345', 2593, '2226', '34562052300117192','90586404'),
|
||||
('673420306', 2592, '3355', '34562052300117184','97850017'),
|
||||
('673420257', 2591, '9395', '34562052300117176','50713786'),
|
||||
('673420231', 2590, '1378', '34562052300117168','50151763'),
|
||||
('673420223', 2589, '9580', '34562052300117150','99534550'),
|
||||
('673420216', 2588, '4955', '34562052300117143','317554'),
|
||||
('673420203', 2587, '6742', '34562052300117135','69321531'),
|
||||
('673420201', 2586, '1659', '34562052300117127','54720480'),
|
||||
('673420199', 2585, '7823', '34562052300117119','22923796'),
|
||||
('673420198', 2584, '1787', '34562052300117101','54414630'),
|
||||
('673420168', 2583, '6334', '34562052300117093','50694894'),
|
||||
('673420147', 2582, '8951', '34562052300117085','1402535'),
|
||||
('673420125', 2581, '3068', '34562052300117077','86216200'),
|
||||
('673420124', 2580, '9517', '34562052300117069','42504099'),
|
||||
('600294609', 2715, '7474', '34569832304894588','55923317'),
|
||||
('600084713', 2703, '8342', '34569832304894570','8392636'),
|
||||
('600084732', 2704, '1625', '34569832304894513','75477452'),
|
||||
('600084850', 2705, '9896', '34569832304894653','28589813'),
|
||||
('600084951', 2706, '5520', '34569832304894661','75353012'),
|
||||
('600084978', 2707, '2698', '34569832304894679','9005523'),
|
||||
('600085403', 2708, '0837', '34569832304894646','77051152'),
|
||||
('600085513', 2709, '3106', '34569832304894687','41571002'),
|
||||
('600293916', 2712, '8990', '34569832304894620','95188676'),
|
||||
('600294160', 2714, '6376', '34569832304894703','79879896'),
|
||||
('671919529', 2975, '9184', '34569832304806236','7535392'),
|
||||
('671919942', 2981, '0328', '34569832304806269','31052894'),
|
||||
('671919530', 2976, '0344', '34569832304806251','89860304'),
|
||||
('671919533', 2977, '0668', '34569832304806244','42921771'),
|
||||
('671919535', 2978, '0105', '34569832304806277','31009417'),
|
||||
('671919537', 2979, '0881', '34569832304806285','33479769'),
|
||||
('671919540', 2980, '9874', '34569832304806293','14103929'),
|
||||
('671919525', 2972, '2089', '34569832304806301','45903729'),
|
||||
('671919527', 2973, '8206', '34569832304806368','1586035'),
|
||||
('671919528', 2974, '2532', '34569832304806327','62310124'),
|
||||
('673668717', 2836, '7973', '34562032301044223','15635496'),
|
||||
('673668734', 2837, '4457', '34562032301044231','18313118'),
|
||||
('673668738', 2824, '2911', '34562032301044249','30875583'),
|
||||
('673668745', 2838, '7253', '34562032301044256','62754222'),
|
||||
('673668796', 2839, '0068', '34562032301044264','15556829'),
|
||||
('673668803', 2840, '2386', '34562032301044272','17572287'),
|
||||
('673669591', 2850, '3833', '34562032301044280','34828896'),
|
||||
('673668808', 2841, '3584', '34562032301044298','16234497'),
|
||||
('673670102', 2851, '3554', '34562032301044306','23652625'),
|
||||
('673670131', 2852, '4412', '34562032301044314','88611709'),
|
||||
('673670135', 2827, '6058', '34562032301044322','53918579'),
|
||||
('673670201', 2828, '8066', '34562032301044330','92369343'),
|
||||
('673670225', 2829, '4592', '34562032301044348','24126635'),
|
||||
('673670236', 2830, '2974', '34562032301044355','88608465'),
|
||||
('673671485', 2849, '0349', '34562032301044363','44944874'),
|
||||
('673461977', 2871, '1728', '34562032400157090','46975780'),
|
||||
('673461975', 2870, '4734', '34562032400157082','69628432'),
|
||||
('673461972', 2867, '6276', '34562032400157058','53338365'),
|
||||
('673461979', 2872, '6043', '34562032400157108','36525197'),
|
||||
('673461958', 2859, '3164', '34562032400156977','58947831'),
|
||||
('673461957', 2857, '8685', '34562032400156969','15826386'),
|
||||
('673461944', 2853, '1073', '34562032400156910','20452195'),
|
||||
('673461974', 2869, '7121', '34562032400157074','32044645'),
|
||||
('673461973', 2868, '8022', '34562032400157066','29282044'),
|
||||
('673461971', 2866, '3089', '34562032400157041','66149978'),
|
||||
('673461969', 2865, '7555', '34562032400157033','78391293'),
|
||||
('673461960', 2860, '5203', '34562032400156985','37138232'),
|
||||
('673461952', 2855, '6915', '34562032400156936','62724661'),
|
||||
('673461949', 2854, '8706', '34562032400156928','5594345'),
|
||||
('673461966', 2863, '2496', '34562032400157017','93450666'),
|
||||
('673461968', 2864, '3703', '34562032400157025','23208841'),
|
||||
('673461963', 2862, '9364', '34562032400157009','29712130'),
|
||||
('673462719', 2873, '9387', '34562032400156951','50434348'),
|
||||
('673461962', 2861, '8441', '34562032400156993','39686909'),
|
||||
('673461956', 2826, '5392', '34562032400156944','5496107'),
|
||||
('673465284', 2694, '1523', '34562032400171349','14554994'),
|
||||
('673465282', 2692, '4645', '34562032400171323','24871187'),
|
||||
('673465283', 2693, '5253', '34562032400171331','28303238'),
|
||||
('673465841', 2696, '0849', '34562032400171257','21673222'),
|
||||
('673465258', 2679, '4140', '34562032400171174','39793881'),
|
||||
('673465263', 2680, '6922', '34562032400171182','12253261'),
|
||||
('673465265', 2681, '9112', '34562032400171190','93894366'),
|
||||
('673465267', 2682, '3259', '34562032400171208','2342189'),
|
||||
('673465268', 2683, '8540', '34562032400171216','63886925'),
|
||||
('673465285', 2695, '4167', '34562032400171356','79227618'),
|
||||
('673465270', 2684, '4292', '34562032400171224','19216349'),
|
||||
('673465272', 2685, '4007', '34562032400171232','14396903'),
|
||||
('673465273', 2686, '6894', '34562032400171240','13569394'),
|
||||
('673465274', 2687, '5268', '34562032400171265','59453667'),
|
||||
('673465275', 2688, '0232', '34562032400171273','62324713'),
|
||||
('673465276', 2689, '2720', '34562032400171281','65977200'),
|
||||
('673465843', 2698, '4773', '34562032400171364','78387158'),
|
||||
('673465842', 2697, '3729', '34562032400171315','94201789'),
|
||||
('673465280', 2691, '0503', '34562032400171307','12298533'),
|
||||
('673465279', 2690, '8239', '34562032400171299','76183877');
|
||||
|
||||
UPDATE vn.deviceProductionUser
|
||||
SET simFk = NULL
|
||||
WHERE id IN (
|
||||
SELECT dpu.id
|
||||
FROM vn.deviceProductionUser dpu
|
||||
LEFT JOIN vn.sim s ON s.code = dpu.simFk
|
||||
WHERE s.code IS NULL
|
||||
AND dpu.simFk IS NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE vn.deviceProductionUser ADD CONSTRAINT deviceProductionUser_sim_FK
|
||||
FOREIGN KEY (simFk) REFERENCES vn.sim(code) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
GRANT SELECT, INSERT, DELETE, UPDATE ON TABLE vn.sim TO hr;
|
|
@ -0,0 +1,3 @@
|
|||
-- Place your SQL code here
|
||||
INSERT IGNORE INTO salix.ACL (model, property, accessType, permission, principalType, principalId)
|
||||
VALUES('InventoryConfig', 'find', 'READ', 'ALLOW', 'ROLE', 'buyer');
|
|
@ -0,0 +1,48 @@
|
|||
USE vn;
|
||||
|
||||
DROP TRIGGER IF EXISTS invoiceIn_beforeUpdate;
|
||||
|
||||
UPDATE invoiceIn
|
||||
SET cplusRectificationTypeFk = NULL
|
||||
WHERE cplusRectificationTypeFk = 1;
|
||||
|
||||
DELETE IGNORE FROM cplusRectificationType WHERE id = 1;
|
||||
|
||||
UPDATE cplusRectificationType
|
||||
SET id = 1
|
||||
WHERE id = 3;
|
||||
|
||||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`invoiceIn_beforeUpdate`
|
||||
BEFORE UPDATE ON `invoiceIn`
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
DECLARE vWithholdingSageFk INT;
|
||||
|
||||
IF NOT (NEW.supplierRef <=> OLD.supplierRef) AND NOT util.checkPrintableChars(NEW.supplierRef) THEN
|
||||
CALL util.throw('The invoiceIn reference contains invalid characters');
|
||||
END IF;
|
||||
|
||||
SET NEW.editorFk = account.myUser_getId();
|
||||
|
||||
IF (SELECT COUNT(*) FROM invoiceIn
|
||||
WHERE supplierRef = NEW.supplierRef
|
||||
AND supplierFk = NEW.supplierFk
|
||||
AND YEAR(issued) = YEAR(NEW.issued)
|
||||
AND id <> NEW.id
|
||||
) THEN
|
||||
CALL util.throw('reference duplicated');
|
||||
END IF;
|
||||
|
||||
IF NEW.supplierFk != OLD.supplierFk THEN
|
||||
CALL supplier_checkIsActive(NEW.supplierFk);
|
||||
SELECT withholdingSageFk INTO vWithholdingSageFk
|
||||
FROM supplier
|
||||
WHERE id = NEW.supplierFk;
|
||||
SET NEW.withholdingSageFk = vWithholdingSageFk;
|
||||
END IF;
|
||||
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
INSERT INTO salix.ACL (model, property, accessType, permission, principalType, principalId)
|
||||
VALUES('SiiTypeInvoiceIn', 'find', 'READ', 'ALLOW', 'ROLE', 'salesPerson');
|
||||
|
||||
DROP TABLE IF EXISTS vn.invoiceInCorrection;
|
||||
|
||||
CREATE TABLE `invoiceInCorrection` (
|
||||
`correctingFk` mediumint(8) unsigned NOT NULL COMMENT 'Factura rectificativa',
|
||||
`correctedFk` mediumint(8) unsigned NOT NULL COMMENT 'Factura rectificada',
|
||||
`cplusRectificationTypeFk` int(10) unsigned NOT NULL,
|
||||
`siiTypeInvoiceInFk` int(10) unsigned NOT NULL,
|
||||
`invoiceCorrectionTypeFk` int(11) NOT NULL DEFAULT 3,
|
||||
PRIMARY KEY (`correctingFk`),
|
||||
KEY `invoiceInCorrection_correctedFk` (`correctedFk`),
|
||||
KEY `invoiceInCorrection_cplusRectificationTypeFk` (`cplusRectificationTypeFk`),
|
||||
KEY `invoiceInCorrection_siiTypeInvoiceIn` (`siiTypeInvoiceInFk`),
|
||||
KEY `invoiceInCorrection_invoiceCorrectionTypeFk` (`invoiceCorrectionTypeFk`),
|
||||
CONSTRAINT `invoiceInCorrection_correctedFk` FOREIGN KEY (`correctedFk`) REFERENCES `invoiceIn` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
CONSTRAINT `invoiceInCorrection_correctingFk` FOREIGN KEY (`correctingFk`) REFERENCES `invoiceIn` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
CONSTRAINT `invoiceInCorrection_cplusRectificationTypeFk` FOREIGN KEY (`cplusRectificationTypeFk`) REFERENCES `cplusRectificationType` (`id`) ON UPDATE CASCADE,
|
||||
CONSTRAINT `invoiceInCorrection_invoiceCorrectionTypeFk` FOREIGN KEY (`invoiceCorrectionTypeFk`) REFERENCES `invoiceCorrectionType` (`id`) ON UPDATE CASCADE,
|
||||
CONSTRAINT `invoiceInCorrection_siiTypeInvoiceIn` FOREIGN KEY (`siiTypeInvoiceInFk`) REFERENCES `siiTypeInvoiceIn` (`id`) ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE vn.`zone` MODIFY COLUMN `price` DECIMAL(10,2);
|
||||
|
|
@ -0,0 +1 @@
|
|||
DROP TABLE vn.quadmindsApiConfig;
|
|
@ -0,0 +1,20 @@
|
|||
CREATE TABLE `vn`.`osrmConfig` (
|
||||
`id` int(10) unsigned NOT NULL,
|
||||
`url` varchar(100) NOT NULL COMMENT 'Dirección base de la API',
|
||||
`tolerance` decimal(6,6) NOT NULL DEFAULT 0 COMMENT 'Tolerancia entre las coordenadas enviadas y las retornadas',
|
||||
PRIMARY KEY (`id`),
|
||||
CONSTRAINT `osrmConfig_check` CHECK (`id` = 1)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
-- Para que no de error al añadir la FK de zone
|
||||
UPDATE vn.zone
|
||||
SET price = 0.1
|
||||
WHERE price = 0;
|
||||
|
||||
ALTER TABLE vn.`zone`
|
||||
ADD addressFk int(11) DEFAULT NULL COMMENT 'Punto de distribución de donde salen para repartir',
|
||||
ADD CONSTRAINT zone_address_FK FOREIGN KEY (addressFk) REFERENCES vn.address(id) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE vn.zoneConfig
|
||||
ADD defaultAddressFk int(11) DEFAULT NULL NULL COMMENT 'Punto de distribución por defecto',
|
||||
ADD CONSTRAINT zoneConfig_address_FK FOREIGN KEY (defaultAddressFk) REFERENCES vn.address(id) ON DELETE RESTRICT ON UPDATE CASCADE;
|
|
@ -0,0 +1,5 @@
|
|||
INSERT IGNORE INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
|
||||
VALUES ('OsrmConfig','optimize','READ','ALLOW','ROLE','employee'),
|
||||
('Route', 'optimizePriority','*','ALLOW','ROLE','employee');
|
||||
INSERT IGNORE INTO vn.osrmConfig (id,url,tolerance)
|
||||
VALUES (1,'https://router.project-osrm.org', 0.002);
|
|
@ -0,0 +1,3 @@
|
|||
ALTER TABLE vn.mistakeType
|
||||
ADD `time` int(10) NULL COMMENT 'Segundos que se suelen tardar en arreglar el fallo',
|
||||
ADD code varchar(50) DEFAULT NULL NULL AFTER id;
|
|
@ -0,0 +1,5 @@
|
|||
RENAME TABLE vn.inventoryFailure TO vn.inventoryFailure__;
|
||||
ALTER TABLE vn.inventoryFailure__ COMMENT='@deprecated 2024-12-16';
|
||||
|
||||
RENAME TABLE vn.inventoryFailureCause TO vn.inventoryFailureCause__;
|
||||
ALTER TABLE vn.inventoryFailureCause__ COMMENT='@deprecated 2024-12-16';
|
|
@ -27,18 +27,6 @@ export default class Controller extends Component {
|
|||
setTimeout(() => element.classList.add('shown'), 30);
|
||||
shape.element = element;
|
||||
|
||||
if (data.additionalData && this.vnToken.token) {
|
||||
this.additionalData = data.additionalData;
|
||||
let supportButton = document.createElement('i');
|
||||
supportButton.setAttribute('class', 'material-icons clickable');
|
||||
supportButton.addEventListener('click', () => this.$.supportDialog.show());
|
||||
element.appendChild(supportButton);
|
||||
|
||||
let buttonIcon = 'support_agent';
|
||||
buttonIcon = document.createTextNode(buttonIcon);
|
||||
supportButton.appendChild(buttonIcon);
|
||||
}
|
||||
|
||||
if (shape.type)
|
||||
element.classList.add(shape.type);
|
||||
|
||||
|
|
|
@ -9,13 +9,6 @@ export default class Controller extends Dialog {
|
|||
responseHandler(response) {
|
||||
if (response !== 'accept')
|
||||
return super.responseHandler(response);
|
||||
|
||||
this.$http.post('Ostickets/send-to-support', {
|
||||
reason: this.reason,
|
||||
additionalData: this.additionalData
|
||||
})
|
||||
.then(() => super.responseHandler(response))
|
||||
.then(() => this.vnApp.showSuccess(this.$t('Email sended!')));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -248,5 +248,6 @@
|
|||
"Payment method is required": "Payment method is required",
|
||||
"Sales already moved": "Sales already moved",
|
||||
"Holidays to past days not available": "Holidays to past days not available",
|
||||
"Price cannot be blank": "Price cannot be blank",
|
||||
"There are tickets to be invoiced": "There are tickets to be invoiced"
|
||||
}
|
||||
|
|
|
@ -388,9 +388,15 @@
|
|||
"You do not have permission to modify the booked field": "No tienes permisos para modificar el campo contabilizada",
|
||||
"ticketLostExpedition": "El ticket [{{ticketId}}]({{{ticketUrl}}}) tiene la siguiente expedición perdida:{{ expeditionId }}",
|
||||
"The web user's email already exists": "El correo del usuario web ya existe",
|
||||
"Sales already moved": "Ya han sido transferidas",
|
||||
"The raid information is not correct": "La información de la redada no es correcta",
|
||||
"Holidays to past days not available": "Las vacaciones a días pasados no están disponibles",
|
||||
"Sales already moved": "Ya han sido transferidas",
|
||||
"The raid information is not correct": "La información de la redada no es correcta",
|
||||
"No trips found because input coordinates are not connected": "No se encontraron rutas porque las coordenadas de entrada no están conectadas",
|
||||
"This request is not supported": "Esta solicitud no es compatible",
|
||||
"Invalid options or too many coordinates": "Opciones invalidas o demasiadas coordenadas",
|
||||
"No address has coordinates": "Ninguna dirección tiene coordenadas",
|
||||
"An item type with the same code already exists": "Un tipo con el mismo código ya existe",
|
||||
"Holidays to past days not available": "Las vacaciones a días pasados no están disponibles",
|
||||
"All tickets have a route order": "Todos los tickets tienen orden de ruta",
|
||||
"Price cannot be blank": "Price cannot be blank",
|
||||
"There are tickets to be invoiced": "La zona tiene tickets por facturar"
|
||||
}
|
||||
|
||||
|
|
|
@ -80,6 +80,12 @@ module.exports = Self => {
|
|||
description: 'The claimResponsible id',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'zoneFk',
|
||||
type: 'string',
|
||||
description: 'The zone name',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'myTeam',
|
||||
type: 'boolean',
|
||||
|
@ -174,6 +180,8 @@ module.exports = Self => {
|
|||
to.setHours(23, 59, 59, 999);
|
||||
|
||||
return {'cl.created': {between: [value, to]}};
|
||||
case 'zoneFk':
|
||||
return {'t.zoneFk': value};
|
||||
case 'myTeam':
|
||||
if (value)
|
||||
return {'cl.workerFk': {inq: teamMembersId}};
|
||||
|
@ -195,11 +203,15 @@ module.exports = Self => {
|
|||
u.name AS workerName,
|
||||
cs.code stateCode,
|
||||
cs.description stateDescription,
|
||||
cl.created
|
||||
cl.created,
|
||||
z.name zoneName,
|
||||
z.id zoneId
|
||||
FROM claim cl
|
||||
LEFT JOIN client c ON c.id = cl.clientFk
|
||||
LEFT JOIN account.user u ON u.id = cl.workerFk
|
||||
LEFT JOIN claimState cs ON cs.id = cl.claimStateFk`
|
||||
LEFT JOIN claimState cs ON cs.id = cl.claimStateFk
|
||||
LEFT JOIN ticket t ON t.id = cl.ticketFk
|
||||
LEFT JOIN zone z ON z.id = t.zoneFk`
|
||||
);
|
||||
|
||||
stmt.merge(conn.makeSuffix(filter));
|
||||
|
|
|
@ -72,6 +72,14 @@ module.exports = function(Self) {
|
|||
{
|
||||
arg: 'isLogifloraAllowed',
|
||||
type: 'boolean'
|
||||
},
|
||||
{
|
||||
arg: 'longitude',
|
||||
type: 'any',
|
||||
},
|
||||
{
|
||||
arg: 'latitude',
|
||||
type: 'any',
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
|
|
|
@ -38,8 +38,9 @@ describe('Entry filter()', () => {
|
|||
};
|
||||
|
||||
const result = await models.Entry.filter(ctx, options);
|
||||
const resultWithCurrency = result.filter(entry => entry.currencyFk === 1);
|
||||
|
||||
expect(result.length).toEqual(12);
|
||||
expect(result.length).toEqual(resultWithCurrency.length);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
|
@ -141,18 +142,21 @@ describe('Entry filter()', () => {
|
|||
it('should return the entry matching the company', async() => {
|
||||
const tx = await models.Entry.beginTransaction({});
|
||||
const options = {transaction: tx};
|
||||
const companyFk = 442;
|
||||
|
||||
try {
|
||||
const ctx = {
|
||||
args: {
|
||||
companyFk: 442
|
||||
companyFk
|
||||
},
|
||||
req: {accessToken: {userId: 9}}
|
||||
};
|
||||
|
||||
const result = await models.Entry.filter(ctx, options);
|
||||
|
||||
expect(result.length).toEqual(11);
|
||||
const resultWithCurrency = result.filter(entry => entry.companyFk === companyFk);
|
||||
|
||||
expect(result.length).toEqual(resultWithCurrency.length);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
|
|
|
@ -28,5 +28,8 @@
|
|||
},
|
||||
"StockBought": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"InventoryConfig": {
|
||||
"dataSource": "vn"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "InventoryConfig",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "inventoryConfig"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "number",
|
||||
"id": true
|
||||
},
|
||||
"supplierFk": {
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,4 +17,6 @@ columns:
|
|||
isVatDeductible: is VAT deductible
|
||||
withholdingSageFk: withholding
|
||||
expenseFkDeductible: expense deductible
|
||||
editorFk: editor
|
||||
editorFk: editor
|
||||
siiTrasCendencyInvoiceInFk: SII tax regime
|
||||
siiTypeInvoiceInFk: SII Type
|
|
@ -5,7 +5,7 @@ columns:
|
|||
serial: serie
|
||||
supplierFk: proveedor
|
||||
issued: fecha emisión
|
||||
supplierRef: referéncia proveedor
|
||||
supplierRef: referencia proveedor
|
||||
isBooked: facturado
|
||||
currencyFk: moneda
|
||||
created: creado
|
||||
|
@ -17,4 +17,6 @@ columns:
|
|||
isVatDeductible: impuesto deducible
|
||||
withholdingSageFk: código de retención
|
||||
expenseFkDeductible: gasto deducible
|
||||
editorFk: editor
|
||||
editorFk: editor
|
||||
siiTrasCendencyInvoiceInFk: régimen fiscal SII
|
||||
siiTypeInvoiceInFk: tipo SII
|
|
@ -44,7 +44,7 @@ module.exports = Self => {
|
|||
correctingFk: clone.id,
|
||||
correctedFk: id,
|
||||
cplusRectificationTypeFk: invoiceType,
|
||||
siiTypeInvoiceOutFk: invoiceClass,
|
||||
siiTypeInvoiceInFk: invoiceClass,
|
||||
invoiceCorrectionTypeFk: invoiceReason
|
||||
}, myOptions);
|
||||
|
||||
|
|
|
@ -91,6 +91,10 @@ module.exports = Self => {
|
|||
{
|
||||
arg: 'supplierActivityFk',
|
||||
type: 'string',
|
||||
},
|
||||
{
|
||||
arg: 'companyFk',
|
||||
type: 'number',
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
|
@ -161,8 +165,8 @@ module.exports = Self => {
|
|||
: {'ii.id': {nin: correcteds.map(x => x.correctingFk)}};
|
||||
case 'correctedFk':
|
||||
return {'ii.id': {inq: correctings.map(x => x.correctingFk)}};
|
||||
case 'supplierActivityFk':
|
||||
return {'s.supplierActivityFk': value};
|
||||
case 'companyFk':
|
||||
return {'ii.companyFk': value};
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -184,7 +188,9 @@ module.exports = Self => {
|
|||
s.name supplierName,
|
||||
s.account,
|
||||
SUM(iid.amount) amount,
|
||||
sub.code awbCode
|
||||
sub.code awbCode,
|
||||
c.code,
|
||||
MIN(iid.dueDated) dueDated
|
||||
FROM invoiceIn ii
|
||||
JOIN supplier s ON s.id = ii.supplierFk
|
||||
LEFT JOIN invoiceInDueDay iid ON iid.invoiceInFk = ii.id
|
||||
|
@ -199,7 +205,8 @@ module.exports = Self => {
|
|||
GROUP BY de.duaFk
|
||||
) sub ON sub.duaFk = d.id
|
||||
LEFT JOIN company co ON co.id = ii.companyFk
|
||||
LEFT JOIN dms dm ON dm.id = ii.docFk`
|
||||
LEFT JOIN dms dm ON dm.id = ii.docFk
|
||||
JOIN company c ON c.id = ii.companyFk`,
|
||||
);
|
||||
|
||||
const sqlWhere = conn.makeWhere(filter.where);
|
||||
|
|
|
@ -15,11 +15,11 @@ describe('invoiceIn corrective()', () => {
|
|||
await tx.rollback();
|
||||
});
|
||||
|
||||
it('La función corrective debería devolver un id cuando se ejecuta correctamente', async() => {
|
||||
it('should return an id when executed correctly', async() => {
|
||||
const originalId = 1;
|
||||
const invoiceReason = 3;
|
||||
const invoiceType = 2;
|
||||
const invoiceClass = 1;
|
||||
const invoiceClass = 8;
|
||||
const cloneId = await models.InvoiceIn.corrective(ctx,
|
||||
originalId, invoiceReason, invoiceType, invoiceClass, options);
|
||||
|
||||
|
@ -30,7 +30,7 @@ describe('invoiceIn corrective()', () => {
|
|||
}, options);
|
||||
|
||||
expect(correction.cplusRectificationTypeFk).toEqual(invoiceType);
|
||||
expect(correction.siiTypeInvoiceOutFk).toEqual(invoiceClass);
|
||||
expect(correction.siiTypeInvoiceInFk).toEqual(invoiceClass);
|
||||
expect(correction.invoiceCorrectionTypeFk).toEqual(invoiceReason);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -166,4 +166,21 @@ describe('InvoiceIn filter()', () => {
|
|||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should return the invoice in matching companyFk', async() => {
|
||||
const tx = await models.InvoiceIn.beginTransaction({});
|
||||
const options = {transaction: tx};
|
||||
|
||||
try {
|
||||
const company = await models.Company.findOne({}, options);
|
||||
const invoicesByCompany = await models.InvoiceIn.find({where: {companyFk: company.id}}, options);
|
||||
const filteredInvoices = await models.InvoiceIn.filter({args: {companyFk: company.id}}, {}, options);
|
||||
|
||||
expect(filteredInvoices.length).toEqual(invoicesByCompany.length);
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
describe('invoiceIn', () => {
|
||||
let options;
|
||||
let tx;
|
||||
const invoiceId = 1;
|
||||
const supplierId = 791;
|
||||
const currencyId = 1;
|
||||
const companyId = 442;
|
||||
|
||||
beforeEach(async() => {
|
||||
tx = await models.InvoiceIn.beginTransaction({});
|
||||
options = {transaction: tx};
|
||||
});
|
||||
|
||||
afterEach(async() => {
|
||||
await tx.rollback();
|
||||
});
|
||||
|
||||
it('should allow insert for new instance', async() => {
|
||||
const newInvoice = {
|
||||
supplierFk: supplierId,
|
||||
issued: Date.vnNew(),
|
||||
operated: Date.vnNew(),
|
||||
currencyFk: currencyId,
|
||||
companyFk: companyId,
|
||||
isBooked: false
|
||||
};
|
||||
|
||||
const createdInvoice = await models.InvoiceIn.create(newInvoice, options);
|
||||
|
||||
expect(createdInvoice).toBeDefined();
|
||||
expect(createdInvoice.id).toBeDefined();
|
||||
});
|
||||
|
||||
it('should throw an error if trying to update a booked invoice', async() => {
|
||||
const invoice = await models.InvoiceIn.findById(invoiceId, null, options);
|
||||
await invoice.updateAttribute('isBooked', true, options);
|
||||
|
||||
let error;
|
||||
try {
|
||||
await invoice.updateAttribute('supplierFk', supplierId, options);
|
||||
} catch (err) {
|
||||
error = err;
|
||||
}
|
||||
|
||||
expect(error.message).toBe('InvoiceIn is already booked');
|
||||
});
|
||||
|
||||
it('should throw an error if trying to delete a booked invoice', async() => {
|
||||
const invoice = await models.InvoiceIn.findById(invoiceId, null, options);
|
||||
await invoice.updateAttribute('isBooked', true, options);
|
||||
|
||||
let error;
|
||||
try {
|
||||
await models.InvoiceIn.deleteById(invoiceId, options);
|
||||
} catch (err) {
|
||||
error = err;
|
||||
}
|
||||
|
||||
expect(error.message).toBe('InvoiceIn is already booked');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,74 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
describe('invoiceInTax', () => {
|
||||
let options;
|
||||
let tx;
|
||||
const invoiceInId = 1;
|
||||
const invoiceInTaxId = 1;
|
||||
beforeEach(async() => {
|
||||
tx = await models.InvoiceInTax.beginTransaction({});
|
||||
options = {transaction: tx};
|
||||
});
|
||||
|
||||
afterEach(async() => {
|
||||
await tx.rollback();
|
||||
});
|
||||
|
||||
it('should throw an error if trying to save a tax from a booked invoice', async() => {
|
||||
const invoiceIn = await models.InvoiceIn.findById(invoiceInId, null, options);
|
||||
await invoiceIn.updateAttributes({isBooked: true}, options);
|
||||
const invoiceInTax = await models.InvoiceInTax.findById(invoiceInTaxId, null, options);
|
||||
let error;
|
||||
try {
|
||||
await invoiceInTax.updateAttribute('taxableBase', 100, options);
|
||||
} catch (err) {
|
||||
error = err;
|
||||
}
|
||||
|
||||
expect(error.message).toBe('InvoiceIn is already booked');
|
||||
});
|
||||
|
||||
it('should allow save if the invoice is not booked', async() => {
|
||||
const invoiceIn = await models.InvoiceIn.findById(invoiceInId, null, options);
|
||||
await invoiceIn.updateAttribute('isBooked', false, options);
|
||||
|
||||
const invoiceInTax = await models.InvoiceInTax.findById(invoiceInTaxId, null, options);
|
||||
await invoiceInTax.updateAttribute('taxableBase', 100, options);
|
||||
|
||||
const updatedInvoiceInTax = await models.InvoiceInTax.findById(invoiceInTaxId, null, options);
|
||||
|
||||
expect(updatedInvoiceInTax.taxableBase).toBe(100);
|
||||
});
|
||||
|
||||
it('should throw an error if trying to delete a tax from a booked invoice', async() => {
|
||||
const invoiceIn = await models.InvoiceIn.findById(invoiceInId, null, options);
|
||||
await invoiceIn.updateAttribute('isBooked', true, options);
|
||||
|
||||
let error;
|
||||
try {
|
||||
await models.InvoiceInTax.destroyById(invoiceInTaxId, options);
|
||||
} catch (err) {
|
||||
error = err;
|
||||
}
|
||||
|
||||
expect(error).toBeDefined();
|
||||
expect(error.message).toBe('InvoiceIn is already booked');
|
||||
});
|
||||
|
||||
it('should allow delete if the invoice is not booked', async() => {
|
||||
const invoiceIn = await models.InvoiceIn.findById(invoiceInId, null, options);
|
||||
await invoiceIn.updateAttribute('isBooked', false, options);
|
||||
|
||||
let error;
|
||||
try {
|
||||
await models.InvoiceInTax.destroyById(invoiceInTaxId, options);
|
||||
} catch (err) {
|
||||
error = err;
|
||||
}
|
||||
|
||||
const deletedInvoiceInTax = await models.InvoiceInTax.findById(invoiceInTaxId, null, options);
|
||||
|
||||
expect(error).toBeUndefined();
|
||||
expect(deletedInvoiceInTax).toBeNull();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,59 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
const invoiceInId = 1;
|
||||
const supplierId = 791;
|
||||
describe('invoiceIn updateInvoiceIn()', () => {
|
||||
const ctx = beforeAll.getCtx();
|
||||
let options;
|
||||
let tx;
|
||||
|
||||
beforeEach(async() => {
|
||||
options = {transaction: tx};
|
||||
tx = await models.Sale.beginTransaction({});
|
||||
options.transaction = tx;
|
||||
});
|
||||
|
||||
afterEach(async() => {
|
||||
await tx.rollback();
|
||||
});
|
||||
|
||||
it('should update the invoice', async() => {
|
||||
const invoiceBefore = await models.InvoiceIn.findById(invoiceInId, null, options);
|
||||
await update(ctx, options);
|
||||
const invoiceAfter = await models.InvoiceIn.findById(invoiceInId, null, options);
|
||||
|
||||
expect(invoiceAfter.supplierFk).not.toBe(invoiceBefore.supplierFk);
|
||||
expect(invoiceAfter.supplierFk).toBe(supplierId);
|
||||
});
|
||||
|
||||
it('should not update the invoice if is booked', async() => {
|
||||
let error;
|
||||
try {
|
||||
await models.InvoiceIn.toBook(ctx, invoiceInId, options);
|
||||
await update(ctx, options);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
|
||||
expect(error.message).toBe('InvoiceIn is already booked');
|
||||
});
|
||||
});
|
||||
|
||||
async function update(ctx, opts) {
|
||||
const supplierRef = 'mockRef';
|
||||
const currencyId = 1;
|
||||
await models.InvoiceIn.updateInvoiceIn(ctx,
|
||||
invoiceInId,
|
||||
supplierId,
|
||||
supplierRef,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
currencyId,
|
||||
undefined,
|
||||
undefined,
|
||||
opts);
|
||||
}
|
|
@ -37,7 +37,13 @@ module.exports = Self => {
|
|||
{
|
||||
relation: 'supplier',
|
||||
scope: {
|
||||
fields: ['id', 'name']
|
||||
fields: ['id', 'name', 'isVies', 'countryFk'],
|
||||
include: [{
|
||||
relation: 'country',
|
||||
scope: {
|
||||
fields: ['id', 'code']
|
||||
}
|
||||
}]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -52,7 +52,8 @@ module.exports = Self => {
|
|||
accountingEntries = await models.Xdiario.count({ASIEN: asien}, myOptions);
|
||||
|
||||
await models.Xdiario.destroyAll({ASIEN: asien}, myOptions);
|
||||
await Self.updateAll({id: invoiceInId}, {isBooked: false}, myOptions);
|
||||
const invoiceIn = await Self.findById(invoiceInId, myOptions);
|
||||
await invoiceIn.updateAttribute('isBooked', false, myOptions);
|
||||
} else {
|
||||
const linkedBookEntry = await models.Xdiario.findOne({
|
||||
fields: ['ASIEN'],
|
||||
|
|
|
@ -82,7 +82,7 @@ module.exports = Self => {
|
|||
|
||||
try {
|
||||
const invoiceIn = await Self.findById(id, null, myOptions);
|
||||
invoiceIn.updateAttributes({supplierFk,
|
||||
await invoiceIn.updateAttributes({supplierFk,
|
||||
supplierRef,
|
||||
issued,
|
||||
operated,
|
||||
|
@ -94,6 +94,7 @@ module.exports = Self => {
|
|||
companyFk,
|
||||
withholdingSageFk
|
||||
}, myOptions);
|
||||
|
||||
if (tx) await tx.commit();
|
||||
return invoiceIn;
|
||||
} catch (e) {
|
||||
|
|
|
@ -28,11 +28,10 @@
|
|||
"model": "InvoiceCorrectionType",
|
||||
"foreignKey": "invoiceCorrectionTypeFk"
|
||||
},
|
||||
"siiTypeInvoiceOut": {
|
||||
"siiTypeInvoiceIn": {
|
||||
"type": "belongsTo",
|
||||
"model": "SiiTypeInvoiceOut",
|
||||
"foreignKey": "siiTypeInvoiceOutFk"
|
||||
"model": "SiiTypeInvoiceIn",
|
||||
"foreignKey": "siiTypeInvoiceInFk"
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.observe('before save', async function(ctx) {
|
||||
if (ctx.isNewInstance) return;
|
||||
|
||||
const models = Self.app.models;
|
||||
const invoiceIn = await models.InvoiceIn.findById(ctx.currentInstance.invoiceInFk, null, ctx.options);
|
||||
if (invoiceIn.isBooked) throw new UserError('InvoiceIn is already booked');
|
||||
});
|
||||
|
||||
Self.observe('before delete', async function(ctx) {
|
||||
const models = Self.app.models;
|
||||
const invoiceInTax = await Self.findById(ctx.where.id, null, ctx.options);
|
||||
const invoiceIn = await models.InvoiceIn.findById(invoiceInTax.invoiceInFk, null, ctx.options);
|
||||
if (invoiceIn.isBooked) throw new UserError('InvoiceIn is already booked');
|
||||
});
|
||||
};
|
|
@ -22,12 +22,11 @@
|
|||
"type": "number"
|
||||
},
|
||||
"expenseFk": {
|
||||
"type": "number"
|
||||
"type": "string"
|
||||
},
|
||||
"created": {
|
||||
"type": "date"
|
||||
}
|
||||
|
||||
},
|
||||
"relations": {
|
||||
"invoiceIn": {
|
||||
|
@ -51,4 +50,4 @@
|
|||
"foreignKey": "transactionTypeSageFk"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,4 +19,25 @@ module.exports = Self => {
|
|||
return new UserError(`This invoice has a linked vehicle.`);
|
||||
return err;
|
||||
});
|
||||
|
||||
Self.observe('before save', async function(ctx) {
|
||||
if (ctx.isNewInstance) return;
|
||||
|
||||
const changes = ctx.data || ctx.instance;
|
||||
const orgData = ctx.currentInstance;
|
||||
let isNotEditable = orgData.isBooked || (!orgData.isBooked && changes.isBooked);
|
||||
|
||||
if (isNotEditable) {
|
||||
for (const [key, value] of Object.entries(changes)) {
|
||||
if (key !== 'isBooked' && value !== orgData[key])
|
||||
throw new UserError('InvoiceIn is already booked');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Self.observe('before delete', async function(ctx) {
|
||||
const invoiceIn = await Self.findById(ctx.where.id, null, ctx.options);
|
||||
if (invoiceIn.isBooked) throw new UserError('InvoiceIn is already booked');
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -43,5 +43,8 @@
|
|||
},
|
||||
"SiiTypeInvoiceOut": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"SiiTypeInvoiceIn": {
|
||||
"dataSource": "vn"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "SiiTypeInvoiceIn",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "siiTypeInvoiceIn"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"id": true,
|
||||
"type": "number",
|
||||
"description": "Identifier"
|
||||
},
|
||||
"code": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,9 +17,6 @@
|
|||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"code": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
name: Minimum Quantity
|
||||
columns:
|
||||
ended: Ended
|
||||
code: Code
|
||||
started: Started
|
|
@ -0,0 +1,5 @@
|
|||
name: Cantidad Mínima
|
||||
columns:
|
||||
ended: Finaliza
|
||||
quantity: Cantidad
|
||||
started: Comienza
|
|
@ -46,4 +46,4 @@ columns:
|
|||
itemFk: item
|
||||
density: density
|
||||
compression: compression
|
||||
|
||||
minQuantity: min quantity
|
||||
|
|
|
@ -46,4 +46,4 @@ columns:
|
|||
itemFk: artículo
|
||||
density: densidad
|
||||
compression: compresión
|
||||
|
||||
minQuantity: Cantidad mínima
|
||||
|
|
|
@ -178,17 +178,18 @@ module.exports = Self => {
|
|||
i.isFloramondo,
|
||||
i.recycledPlastic,
|
||||
i.nonRecycledPlastic,
|
||||
pr.name AS producer,
|
||||
it.name AS typeName,
|
||||
it.workerFk AS buyerFk,
|
||||
u.name AS userName,
|
||||
ori.code AS origin,
|
||||
ic.name AS category,
|
||||
pr.name producer,
|
||||
it.name typeName,
|
||||
it.workerFk buyerFk,
|
||||
u.name userName,
|
||||
ori.code origin,
|
||||
ic.name category,
|
||||
i.intrastatFk,
|
||||
intr.description AS intrastat,
|
||||
intr.description intrastat,
|
||||
b.grouping,
|
||||
b.packing,
|
||||
lb.landing AS landed
|
||||
lb.landing landed,
|
||||
it.name typeName
|
||||
FROM item i
|
||||
LEFT JOIN itemType it ON it.id = i.typeFk
|
||||
LEFT JOIN itemCategory ic ON ic.id = it.categoryFk
|
||||
|
|
|
@ -29,10 +29,12 @@ module.exports = Self => {
|
|||
Object.assign(myOptions, options);
|
||||
|
||||
const stmt = new ParameterizedSQL(
|
||||
`SELECT w.id AS warehouseFk,
|
||||
w.name AS warehouse,
|
||||
tr.landed,
|
||||
b.id AS buyFk,
|
||||
`SELECT i.id itemFk,
|
||||
w.id warehouseFk,
|
||||
w.name warehouse,
|
||||
CAST(tr.landed AS CHAR) landed,
|
||||
tr.landed landedDate,
|
||||
b.id buyFk,
|
||||
b.entryFk,
|
||||
b.isIgnored,
|
||||
b.price2,
|
||||
|
@ -47,14 +49,18 @@ module.exports = Self => {
|
|||
b.buyingValue +
|
||||
b.freightValue +
|
||||
b.comissionValue +
|
||||
b.packageValue AS cost,
|
||||
b.packageValue cost,
|
||||
b.buyingValue,
|
||||
b.freightValue,
|
||||
b.comissionValue,
|
||||
b.packageValue,
|
||||
b.packagingFk ,
|
||||
s.id AS supplierFk,
|
||||
s.name AS supplier
|
||||
s.id supplierFk,
|
||||
s.name supplier,
|
||||
b.printedStickers,
|
||||
c.inventoried,
|
||||
ic.supplierFk inventorySupplierFk,
|
||||
s.id = ic.supplierFk isInventorySupplier
|
||||
FROM itemType it
|
||||
RIGHT JOIN (entry e
|
||||
LEFT JOIN supplier s ON s.id = e.supplierFk
|
||||
|
@ -65,9 +71,14 @@ module.exports = Self => {
|
|||
LEFT JOIN warehouse w ON w.id = tr.warehouseInFk
|
||||
LEFT JOIN origin o ON o.id = i.originFk
|
||||
) ON it.id = i.typeFk
|
||||
LEFT JOIN edi.ekt ek ON b.ektFk = ek.id`
|
||||
LEFT JOIN edi.ekt ek ON b.ektFk = ek.id
|
||||
JOIN config c
|
||||
JOIN inventoryConfig ic`
|
||||
);
|
||||
stmt.merge(conn.makeSuffix(filter));
|
||||
|
||||
stmt.merge(conn.makeWhere(filter.where));
|
||||
stmt.merge('AND IF(s.id = ic.supplierFk, tr.landed = DATE(c.inventoried), TRUE)');
|
||||
stmt.merge(conn.makePagination(filter));
|
||||
|
||||
return conn.executeStmt(stmt, myOptions);
|
||||
};
|
||||
|
|
|
@ -1,16 +1,22 @@
|
|||
const {models} = require('vn-loopback/server/server');
|
||||
const itemFk = 1;
|
||||
|
||||
const today = Date.vnNew();
|
||||
today.setHours(23, 59, 59, 999);
|
||||
|
||||
const twoMonthsAgo = Date.vnNew();
|
||||
twoMonthsAgo.setHours(0, 0, 0, 0);
|
||||
twoMonthsAgo.setMonth(twoMonthsAgo.getMonth() - 2, 1);
|
||||
describe('item lastEntriesFilter()', () => {
|
||||
it('should return two entry for the given item', async() => {
|
||||
const minDate = Date.vnNew();
|
||||
minDate.setHours(0, 0, 0, 0);
|
||||
const maxDate = Date.vnNew();
|
||||
maxDate.setHours(23, 59, 59, 59);
|
||||
|
||||
const tx = await models.Item.beginTransaction({});
|
||||
const options = {transaction: tx};
|
||||
|
||||
try {
|
||||
const filter = {where: {itemFk: 1, landed: {between: [minDate, maxDate]}}};
|
||||
const filter = {where: {itemFk, landed: {between: [minDate, today]}}};
|
||||
const result = await models.Item.lastEntriesFilter(filter, options);
|
||||
|
||||
expect(result.length).toEqual(2);
|
||||
|
@ -23,21 +29,61 @@ describe('item lastEntriesFilter()', () => {
|
|||
});
|
||||
|
||||
it('should return six entries for the given item', async() => {
|
||||
const minDate = Date.vnNew();
|
||||
minDate.setHours(0, 0, 0, 0);
|
||||
minDate.setMonth(minDate.getMonth() - 2, 1);
|
||||
|
||||
const maxDate = Date.vnNew();
|
||||
maxDate.setHours(23, 59, 59, 59);
|
||||
|
||||
const tx = await models.Item.beginTransaction({});
|
||||
const options = {transaction: tx};
|
||||
|
||||
try {
|
||||
const filter = {where: {itemFk: 1, landed: {between: [minDate, maxDate]}}};
|
||||
const filter = {where: {itemFk, landed: {between: [twoMonthsAgo, today]}}};
|
||||
const result = await models.Item.lastEntriesFilter(filter, options);
|
||||
const twoMonthsAgoUtc = twoMonthsAgo.getTime();
|
||||
const todayUtc = today.getTime();
|
||||
|
||||
const resultMatch = (
|
||||
await Promise.all(
|
||||
result.map(async item => {
|
||||
const itemRecord = await models.Buy.findOne({
|
||||
fields: ['id'],
|
||||
where: {id: item.id},
|
||||
options,
|
||||
});
|
||||
|
||||
const isItemFkValid = itemRecord?.id === itemFk;
|
||||
const landedDate = Date.vnNew(item.landed).getTime();
|
||||
const isLandedValid = landedDate >= twoMonthsAgoUtc && landedDate <= todayUtc;
|
||||
|
||||
return isItemFkValid && isLandedValid;
|
||||
})
|
||||
)
|
||||
).filter(Boolean).length;
|
||||
|
||||
expect(result.length).toEqual(resultMatch);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should return just the inventoried inventory', async() => {
|
||||
const tx = await models.Item.beginTransaction({});
|
||||
const options = {transaction: tx};
|
||||
|
||||
try {
|
||||
const filter = {where: {itemFk, landed: {between: [twoMonthsAgo, today]}}};
|
||||
const result = await models.Item.lastEntriesFilter(filter, options);
|
||||
|
||||
expect(result.length).toEqual(6);
|
||||
const {supplierFk} = await models.InventoryConfig.findOne(options);
|
||||
const {inventoried} = await models.Config.findOne(options);
|
||||
|
||||
let hasInventoriedDate = false;
|
||||
result.forEach(entry => {
|
||||
if (entry.supplierFk === supplierFk &&
|
||||
entry.landedDate.getTime() === inventoried.getTime()
|
||||
)hasInventoriedDate = true;
|
||||
});
|
||||
|
||||
expect(hasInventoriedDate).toEqual(true);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
let UserError = require('vn-loopback/util/user-error');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.rewriteDbError(function(err) {
|
||||
if (err.code === 'ER_DUP_ENTRY')
|
||||
return new UserError(`An item type with the same code already exists`);
|
||||
return err;
|
||||
});
|
||||
};
|
|
@ -89,10 +89,20 @@ module.exports = Self => {
|
|||
type: 'number',
|
||||
description: `The alert level of the tickets`
|
||||
},
|
||||
{
|
||||
arg: 'packing',
|
||||
type: 'string',
|
||||
description: `The packing of the items`
|
||||
},
|
||||
{
|
||||
arg: 'countryFk',
|
||||
type: 'number',
|
||||
description: 'The country id filter'
|
||||
},
|
||||
{
|
||||
arg: 'payMethod',
|
||||
type: 'string',
|
||||
description: 'The payment method filter'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
|
@ -160,6 +170,8 @@ module.exports = Self => {
|
|||
case 'clientFk':
|
||||
param = `t.${param}`;
|
||||
return {[param]: value};
|
||||
case 'payMethod':
|
||||
return {'c.payMethodFk': value};
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -174,7 +186,7 @@ module.exports = Self => {
|
|||
stmt = new ParameterizedSQL(`
|
||||
CREATE OR REPLACE TEMPORARY TABLE tmp.filter
|
||||
(PRIMARY KEY (id))
|
||||
ENGINE = MEMORY
|
||||
ENGINE = InnoDB
|
||||
SELECT t.id,
|
||||
t.shipped,
|
||||
CAST(DATE(t.shipped) AS CHAR) shippedDate,
|
||||
|
@ -200,10 +212,20 @@ module.exports = Self => {
|
|||
u.name userName,
|
||||
c.salesPersonFk,
|
||||
c.credit,
|
||||
c.payMethodFk payMethodFk,
|
||||
pm.id payMethodId,
|
||||
pm.name payMethod,
|
||||
z.hour zoneLanding,
|
||||
z.name zoneName,
|
||||
z.id zoneFk,
|
||||
st.classColor,
|
||||
d.id departmentFk,
|
||||
d.name department,
|
||||
(SELECT GROUP_CONCAT(DISTINCT i.itemPackingTypeFk ORDER BY i.itemPackingTypeFk SEPARATOR ',')
|
||||
FROM sale s
|
||||
JOIN item i ON i.id = s.itemFk
|
||||
WHERE s.ticketFk = t.id
|
||||
) AS packing,
|
||||
TIME_FORMAT(t.shipped, '%H:%i') preparationHour,
|
||||
TIME_FORMAT(z.hour, '%H:%i') theoreticalhour,
|
||||
TIME_FORMAT(zed.etc, '%H:%i') practicalHour
|
||||
|
@ -217,7 +239,10 @@ module.exports = Self => {
|
|||
LEFT JOIN ticketState ts ON ts.ticketFk = t.id
|
||||
LEFT JOIN state st ON st.id = ts.stateFk
|
||||
LEFT JOIN client c ON c.id = t.clientFk
|
||||
LEFT JOIN payMethod pm ON pm.id = c.payMethodFk
|
||||
LEFT JOIN worker wk ON wk.id = c.salesPersonFk
|
||||
LEFT JOIN workerDepartment wd ON wd.workerFk = wk.id
|
||||
LEFT JOIN department d ON d.id = wd.departmentFk
|
||||
LEFT JOIN account.user u ON u.id = wk.id
|
||||
LEFT JOIN (
|
||||
SELECT zoneFk,
|
||||
|
@ -362,6 +387,7 @@ module.exports = Self => {
|
|||
}
|
||||
case 'agencyModeFk':
|
||||
case 'warehouseFk':
|
||||
case 'packing':
|
||||
case 'countryFk':
|
||||
param = `f.${param}`;
|
||||
return {[param]: value};
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('optimizePriority', {
|
||||
description: 'Updates the ticket priority of tickets without priority',
|
||||
accepts: {
|
||||
arg: 'id',
|
||||
type: 'number',
|
||||
required: true,
|
||||
description: 'Route id',
|
||||
http: {source: 'path'}
|
||||
},
|
||||
returns: {
|
||||
type: 'object',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: '/:id/optimizePriority',
|
||||
verb: 'POST'
|
||||
}
|
||||
});
|
||||
|
||||
Self.optimizePriority = async(id, options) => {
|
||||
const models = Self.app.models;
|
||||
const myOptions = {};
|
||||
let tx;
|
||||
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
const tickets = await models.Ticket.find({
|
||||
where: {routeFk: id}
|
||||
}, myOptions);
|
||||
|
||||
let ticketAddress = [];
|
||||
for (const ticket of tickets) {
|
||||
ticketAddress.push({
|
||||
ticketId: ticket.id,
|
||||
addressId: ticket.addressFk,
|
||||
zoneId: ticket.zoneFk,
|
||||
priority: ticket.priority
|
||||
});
|
||||
}
|
||||
|
||||
// Igualamos los priority del mismo addressId
|
||||
const addressPriorityMap = ticketAddress.reduce((acc, {addressId, priority}) => {
|
||||
if (priority !== null) {
|
||||
acc[addressId] = acc[addressId] === undefined
|
||||
? priority
|
||||
: Math.max(acc[addressId], priority);
|
||||
}
|
||||
return acc;
|
||||
});
|
||||
ticketAddress.forEach(item => {
|
||||
const maxPriority = addressPriorityMap[item.addressId];
|
||||
if (maxPriority) item.priority = maxPriority;
|
||||
});
|
||||
|
||||
// Añadimos las direcciones a optimizar
|
||||
let addressIds = [];
|
||||
ticketAddress.forEach(h => {
|
||||
if (!addressIds.includes(h.addressId) && !h.priority)
|
||||
addressIds.push(h.addressId);
|
||||
});
|
||||
if (!addressIds.length) throw new UserError('All tickets have a route order');
|
||||
|
||||
// Obtenemos el zoneId más frecuente
|
||||
const zoneFrequency = ticketAddress.reduce((acc, {zoneId}) => {
|
||||
if (zoneId != null) acc[zoneId] = (acc[zoneId] || 0) + 1;
|
||||
return acc;
|
||||
}, {});
|
||||
const [mostFrequentZoneId] = Object.entries(zoneFrequency)
|
||||
.reduce((maxEntry, entry) => entry[1] > maxEntry[1] ? entry : maxEntry, [null, 0]);
|
||||
|
||||
// Obtenemos los address inicio y fin
|
||||
const maxPosition = Math.max(...ticketAddress.map(g => g.priority));
|
||||
let firstAddress = (await models.Zone.findById(mostFrequentZoneId, myOptions))?.addressFk
|
||||
|| (await models.ZoneConfig.findOne())?.defaultAddressFk;
|
||||
const lastAddress = firstAddress;
|
||||
if (maxPosition) firstAddress = ticketAddress.find(g => g.priority === maxPosition)?.addressId;
|
||||
|
||||
// Revisamos las coincidencias y actualizamos la prioridad en el array
|
||||
const addressPositions = await models.OsrmConfig.optimize(addressIds, firstAddress, lastAddress, myOptions);
|
||||
await Promise.all(ticketAddress.map(async i => {
|
||||
const foundPosition = addressPositions.find(item => item.addressId === i.addressId);
|
||||
if (foundPosition) i.priority = foundPosition.position + (maxPosition + 1);
|
||||
}));
|
||||
|
||||
// Suavizado de prioridad para que no hayan escalones
|
||||
const allPriorities = ticketAddress
|
||||
.map(item => item.priority)
|
||||
.filter(p => p !== null);
|
||||
const uniquePriorities = [...new Set(allPriorities)].sort((a, b) => a - b);
|
||||
const priorityMap = {};
|
||||
uniquePriorities.forEach((p, index) => {
|
||||
priorityMap[p] = index + 1;
|
||||
});
|
||||
ticketAddress.forEach(item => {
|
||||
if (item.priority !== null) item.priority = priorityMap[item.priority];
|
||||
});
|
||||
|
||||
if (!myOptions.transaction) {
|
||||
tx = await Self.beginTransaction({});
|
||||
myOptions.transaction = tx;
|
||||
}
|
||||
|
||||
// Realizamos el update en la base de datos
|
||||
try {
|
||||
await Promise.all(ticketAddress.map(async y => {
|
||||
if (y.priority) {
|
||||
const ticket = await models.Ticket.findById(y.ticketId);
|
||||
await ticket.updateAttribute('priority', y.priority, myOptions);
|
||||
}
|
||||
}));
|
||||
if (tx) await tx.commit();
|
||||
return;
|
||||
} catch (err) {
|
||||
if (tx) await tx.rollback();
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
};
|
|
@ -0,0 +1,36 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
const routeId = 1;
|
||||
|
||||
describe('route optimizePriority())', function() {
|
||||
it('should execute without throwing errors', async function() {
|
||||
const tx = await models.Route.beginTransaction({});
|
||||
let error;
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
await models.Ticket.updateAll(
|
||||
{routeFk: routeId},
|
||||
{priority: null},
|
||||
options
|
||||
);
|
||||
await models.Route.optimizePriority(routeId, options);
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
error = e;
|
||||
await tx.rollback();
|
||||
}
|
||||
|
||||
expect(error).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should execute with error', async function() {
|
||||
let error;
|
||||
try {
|
||||
await models.Route.optimizePriority(routeId);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
|
||||
expect(error).toBeDefined();
|
||||
expect(error.message).toBe('All tickets have a route order');
|
||||
});
|
||||
});
|
|
@ -16,4 +16,5 @@ module.exports = Self => {
|
|||
require('../methods/route/downloadZip')(Self);
|
||||
require('../methods/route/getExpeditionSummary')(Self);
|
||||
require('../methods/route/getByWorker')(Self);
|
||||
require('../methods/route/optimizePriority')(Self);
|
||||
};
|
||||
|
|
|
@ -49,7 +49,8 @@ module.exports = Self => {
|
|||
es.workerFk expeditionScanWorkerFk,
|
||||
su.name scannerUserName,
|
||||
es.scanned,
|
||||
est.description state
|
||||
est.description state,
|
||||
de.longName
|
||||
FROM vn.expedition e
|
||||
LEFT JOIN vn.expeditionStateType est ON est.id = e.stateTypeFk
|
||||
INNER JOIN vn.item i1 ON i1.id = e.freightItemFk
|
||||
|
@ -59,6 +60,7 @@ module.exports = Self => {
|
|||
LEFT JOIN account.user u ON u.id = e.workerFk
|
||||
LEFT JOIN vn.expeditionScan es ON es.expeditionFk = e.id
|
||||
LEFT JOIN account.user su ON su.id = es.workerFk
|
||||
LEFT JOIN dipole.expedition_PrintOut de ON de.expeditionFk = e.id
|
||||
) e
|
||||
`);
|
||||
stmt.merge(conn.makeWhere(filter.where));
|
||||
|
|
|
@ -54,9 +54,17 @@ module.exports = Self => {
|
|||
throw new UserError(`That item doesn't exists`);
|
||||
|
||||
const request = await models.TicketRequest.findById(ctx.args.id, {
|
||||
include: {relation: 'ticket'}
|
||||
include: {
|
||||
relation: 'ticket',
|
||||
scope: {
|
||||
include: {
|
||||
relation: 'client',
|
||||
scope: {
|
||||
fields: ['id', 'name', 'salesPersonFk']
|
||||
}
|
||||
}
|
||||
}}
|
||||
}, myOptions);
|
||||
|
||||
const itemStock = await models.Item.getVisibleAvailable(
|
||||
ctx.args.itemFk,
|
||||
request.ticket().warehouseFk,
|
||||
|
@ -89,19 +97,19 @@ module.exports = Self => {
|
|||
const query = `CALL vn.sale_calculateComponent(?, NULL)`;
|
||||
await Self.rawSql(query, [sale.id], myOptions);
|
||||
|
||||
const url = await Self.app.models.Url.getUrl();
|
||||
const requesterId = request.requesterFk;
|
||||
|
||||
const message = $t('Bought units from buy request', {
|
||||
quantity: sale.quantity,
|
||||
concept: sale.concept,
|
||||
itemId: sale.itemFk,
|
||||
ticketId: sale.ticketFk,
|
||||
url: `${url}ticket/${sale.ticketFk}/summary`,
|
||||
urlItem: `${url}item/${sale.itemFk}/summary`
|
||||
});
|
||||
await models.Chat.sendCheckingPresence(ctx, requesterId, message, myOptions);
|
||||
|
||||
const salesPerson = request.ticket().client().salesPersonFk;
|
||||
if (salesPerson) {
|
||||
const url = await Self.app.models.Url.getUrl();
|
||||
const message = $t('Bought units from buy request', {
|
||||
quantity: sale.quantity,
|
||||
concept: sale.concept,
|
||||
itemId: sale.itemFk,
|
||||
ticketId: sale.ticketFk,
|
||||
url: `${url}ticket/${sale.ticketFk}/summary`,
|
||||
urlItem: `${url}item/${sale.itemFk}/summary`
|
||||
});
|
||||
await models.Chat.sendCheckingPresence(ctx, salesPerson, message, myOptions);
|
||||
}
|
||||
if (tx) await tx.commit();
|
||||
|
||||
return sale;
|
||||
|
|
|
@ -1,18 +1,22 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('deny', {
|
||||
description: 'sets a ticket request to denied and returns the changes',
|
||||
description: 'Sets a ticket request to denied and returns the changes',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'id',
|
||||
type: 'number',
|
||||
required: true,
|
||||
description: 'The request ID',
|
||||
}, {
|
||||
arg: 'observation',
|
||||
type: 'String',
|
||||
required: true,
|
||||
description: 'The request observation',
|
||||
}],
|
||||
accepts: [
|
||||
{
|
||||
arg: 'id',
|
||||
type: 'number',
|
||||
required: true,
|
||||
description: 'The request ID',
|
||||
},
|
||||
{
|
||||
arg: 'observation',
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: 'The request observation',
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: 'number',
|
||||
root: true
|
||||
|
@ -29,7 +33,7 @@ module.exports = Self => {
|
|||
const myOptions = {};
|
||||
let tx;
|
||||
|
||||
if (typeof options == 'object')
|
||||
if (typeof options === 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
if (!myOptions.transaction) {
|
||||
|
@ -39,7 +43,7 @@ module.exports = Self => {
|
|||
|
||||
try {
|
||||
const userId = ctx.req.accessToken.userId;
|
||||
const worker = await Self.app.models.Worker.findOne({where: {id: userId}}, myOptions);
|
||||
const worker = await models.Worker.findById(userId, {fields: ['id']}, myOptions);
|
||||
|
||||
const params = {
|
||||
isOk: false,
|
||||
|
@ -47,19 +51,32 @@ module.exports = Self => {
|
|||
response: ctx.args.observation,
|
||||
};
|
||||
|
||||
const request = await Self.app.models.TicketRequest.findById(ctx.args.id, null, myOptions);
|
||||
await request.updateAttributes(params, myOptions);
|
||||
const request = await models.TicketRequest.findById(ctx.args.id, {
|
||||
include: {
|
||||
relation: 'ticket',
|
||||
scope: {
|
||||
include: {
|
||||
relation: 'client',
|
||||
scope: {
|
||||
fields: ['id', 'name', 'salesPersonFk']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, myOptions);
|
||||
|
||||
const url = await Self.app.models.Url.getUrl();
|
||||
const requesterId = request.requesterFk;
|
||||
const salesPerson = request.ticket().client().salesPersonFk;
|
||||
if (salesPerson) {
|
||||
const url = await models.Url.getUrl();
|
||||
const message = $t('Deny buy request', {
|
||||
ticketId: request.ticketFk,
|
||||
url: `${url}ticket/${request.ticketFk}/request/index`,
|
||||
observation: params.response
|
||||
});
|
||||
|
||||
const message = $t('Deny buy request', {
|
||||
ticketId: request.ticketFk,
|
||||
url: `${url}ticket/${request.ticketFk}/request/index`,
|
||||
observation: params.response
|
||||
});
|
||||
|
||||
await models.Chat.sendCheckingPresence(ctx, requesterId, message, myOptions);
|
||||
await models.Chat.sendCheckingPresence(ctx, salesPerson, message, myOptions);
|
||||
await request.updateAttributes(params, myOptions);
|
||||
}
|
||||
|
||||
if (tx) await tx.commit();
|
||||
|
||||
|
|
|
@ -55,6 +55,11 @@ module.exports = Self => {
|
|||
type: 'number',
|
||||
description: 'Department identifier'
|
||||
},
|
||||
{
|
||||
arg: 'onlyWithDestination',
|
||||
type: 'Boolean',
|
||||
description: 'True when only tickets with destination are returned'
|
||||
},
|
||||
{
|
||||
arg: 'filter',
|
||||
type: 'object',
|
||||
|
@ -103,6 +108,8 @@ module.exports = Self => {
|
|||
return {'f.isFullMovable': value};
|
||||
case 'departmentFk':
|
||||
return {'f.departmentFk': value};
|
||||
case 'onlyWithDestination':
|
||||
return {'f.id': value ? {neq: null} : null};
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
|
|||
tomorrow.setDate(today.getDate() + 1);
|
||||
const salesDeptId = 43;
|
||||
const spain1DeptId = 95;
|
||||
const warehouseId = 1;
|
||||
beforeAll.mockLoopBackContext();
|
||||
|
||||
it('should return the tickets passing the required data', async() => {
|
||||
|
@ -19,7 +20,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
|
|||
const args = {
|
||||
dateFuture: tomorrow,
|
||||
dateToAdvance: today,
|
||||
warehouseFk: 1,
|
||||
warehouseFk: warehouseId,
|
||||
};
|
||||
|
||||
ctx.args = args;
|
||||
|
@ -42,7 +43,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
|
|||
const args = {
|
||||
dateFuture: tomorrow,
|
||||
dateToAdvance: today,
|
||||
warehouseFk: 1,
|
||||
warehouseFk: warehouseId,
|
||||
isFullMovable: true
|
||||
};
|
||||
|
||||
|
@ -67,7 +68,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
|
|||
const args = {
|
||||
dateFuture: tomorrow,
|
||||
dateToAdvance: today,
|
||||
warehouseFk: 1,
|
||||
warehouseFk: warehouseId,
|
||||
isFullMovable: false
|
||||
};
|
||||
|
||||
|
@ -92,7 +93,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
|
|||
const args = {
|
||||
dateFuture: tomorrow,
|
||||
dateToAdvance: today,
|
||||
warehouseFk: 1,
|
||||
warehouseFk: warehouseId,
|
||||
ipt: 'V'
|
||||
};
|
||||
|
||||
|
@ -117,7 +118,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
|
|||
const args = {
|
||||
dateFuture: tomorrow,
|
||||
dateToAdvance: today,
|
||||
warehouseFk: 1,
|
||||
warehouseFk: warehouseId,
|
||||
tfIpt: 'V'
|
||||
};
|
||||
|
||||
|
@ -141,7 +142,7 @@ describe('TicketFuture getTicketsAdvance()', () => {
|
|||
ctx.args = {
|
||||
dateFuture: tomorrow,
|
||||
dateToAdvance: today,
|
||||
warehouseFk: 1,
|
||||
warehouseFk: warehouseId,
|
||||
};
|
||||
|
||||
await models.Ticket.updateAll({id: {inq: [12, 31]}}, {clientFk: 1}, options);
|
||||
|
@ -167,4 +168,56 @@ describe('TicketFuture getTicketsAdvance()', () => {
|
|||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should return the tickets with only destination', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const args = {
|
||||
dateFuture: today,
|
||||
dateToAdvance: today.setHours(23, 59, 59, 999),
|
||||
warehouseFk: warehouseId,
|
||||
};
|
||||
ctx.args = args;
|
||||
|
||||
const allTickets = await models.Ticket.getTicketsAdvance(ctx, options);
|
||||
ctx.args.onlyWithDestination = true;
|
||||
const withDestinationTickets = await models.Ticket.getTicketsAdvance(ctx, options);
|
||||
|
||||
expect(allTickets.filter(ticket => ticket.id).length).toBe(withDestinationTickets.length);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should return the tickets without only destination', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const args = {
|
||||
dateFuture: today,
|
||||
dateToAdvance: today.setHours(23, 59, 59, 999),
|
||||
warehouseFk: warehouseId,
|
||||
};
|
||||
ctx.args = args;
|
||||
|
||||
const allTickets = await models.Ticket.getTicketsAdvance(ctx, options);
|
||||
ctx.args.onlyWithDestination = false;
|
||||
const withoutDestinationTickets = await models.Ticket.getTicketsAdvance(ctx, options);
|
||||
|
||||
expect(allTickets.filter(ticket => !ticket.id).length).toBe(withoutDestinationTickets.length);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -3,9 +3,10 @@ const models = require('vn-loopback/server/server').models;
|
|||
describe('travel getEntries()', () => {
|
||||
const travelId = 1;
|
||||
it('should check the response contains the id', async() => {
|
||||
const entries = await models.Travel.getEntries(travelId);
|
||||
const result = await models.Travel.getEntries(travelId);
|
||||
const entries = await models.Entry.find({where: {travelFk: travelId}});
|
||||
|
||||
expect(entries.length).toEqual(1);
|
||||
expect(entries.length).toEqual(result.length);
|
||||
expect(entries[0].id).toEqual(1);
|
||||
});
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
"userFk": {
|
||||
"type": "number"
|
||||
},
|
||||
"simSerialNumber": {
|
||||
"simFk": {
|
||||
"type": "string"
|
||||
},
|
||||
"created": {
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
"ZoneClosure": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"ZoneConfig": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"ZoneEvent": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"name": "ZoneConfig",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "zoneConfig"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
"scope": {
|
||||
"type": "number"
|
||||
},
|
||||
"forwardDays": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
"address": {
|
||||
"type": "belongsTo",
|
||||
"model": "Address",
|
||||
"foreignKey": "defaultAddressFk"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,4 +14,18 @@ module.exports = Self => {
|
|||
Self.validatesPresenceOf('agencyModeFk', {
|
||||
message: `Agency cannot be blank`
|
||||
});
|
||||
|
||||
Self.validatesPresenceOf('price', {
|
||||
message: 'Price cannot be blank'
|
||||
});
|
||||
Self.validateAsync('price', priceIsValid, {
|
||||
message: 'Price must be greater than 0'
|
||||
});
|
||||
|
||||
async function priceIsValid(err, done) {
|
||||
if (this.price <= 0)
|
||||
err();
|
||||
|
||||
done();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"name": "Zone",
|
||||
"base": "VnModel",
|
||||
"mixins": {
|
||||
"Loggable": true
|
||||
},
|
||||
"mixins": {
|
||||
"Loggable": true
|
||||
},
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "zone"
|
||||
|
@ -48,30 +48,35 @@
|
|||
}
|
||||
},
|
||||
"relations": {
|
||||
"agencyMode": {
|
||||
"type": "belongsTo",
|
||||
"model": "AgencyMode",
|
||||
"foreignKey": "agencyModeFk"
|
||||
"agencyMode": {
|
||||
"type": "belongsTo",
|
||||
"model": "AgencyMode",
|
||||
"foreignKey": "agencyModeFk"
|
||||
},
|
||||
"events": {
|
||||
"type": "hasMany",
|
||||
"model": "ZoneEvent",
|
||||
"foreignKey": "zoneFk"
|
||||
},
|
||||
"type": "hasMany",
|
||||
"model": "ZoneEvent",
|
||||
"foreignKey": "zoneFk"
|
||||
},
|
||||
"exclusions": {
|
||||
"type": "hasMany",
|
||||
"model": "ZoneExclusion",
|
||||
"type": "hasMany",
|
||||
"model": "ZoneExclusion",
|
||||
"foreignKey": "zoneFk"
|
||||
},
|
||||
"warehouses": {
|
||||
"type": "hasMany",
|
||||
"model": "ZoneWarehouse",
|
||||
"foreignKey": "zoneFk"
|
||||
},
|
||||
},
|
||||
"closures": {
|
||||
"type": "hasMany",
|
||||
"model": "ZoneClosure",
|
||||
"foreignKey": "zoneFk"
|
||||
}
|
||||
}
|
||||
},
|
||||
"address": {
|
||||
"type": "belongsTo",
|
||||
"model": "Address",
|
||||
"foreignKey": "addressFk"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "salix-back",
|
||||
"version": "24.50.0",
|
||||
"version": "24.52.0",
|
||||
"author": "Verdnatura Levante SL",
|
||||
"description": "Salix backend",
|
||||
"license": "GPL-3.0",
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
subject: Incoterms Authorization
|
||||
title: Incoterms Authorization
|
||||
description:
|
||||
dear: Dear customer
|
||||
instructions: Please find attached the Incoterms authorization form, which you must complete and sign.
|
||||
conclusion: Thank you for your attention!
|
|
@ -0,0 +1,16 @@
|
|||
reportName: balance-compensation
|
||||
Place: Algemesí, on
|
||||
Compensation: Compensation of debtor and creditor balances
|
||||
In one hand: On one hand
|
||||
CIF: with CIF
|
||||
NIF: with NIF
|
||||
Home: and address located at
|
||||
In other hand: On the other hand
|
||||
Sr: Mr./Ms.
|
||||
Agree: Agree
|
||||
Date: On the date of
|
||||
Compensate: the balance of has been compensated
|
||||
From client: from the client/supplier
|
||||
Against the balance of: against the balance of
|
||||
Reception: Please confirm receipt of this compensation at the email
|
||||
Greetings: Best regards,
|
|
@ -0,0 +1,39 @@
|
|||
reportName: autorization-incoterms
|
||||
description: '<em>{socialName}</em> a duly constituted and responsible company <em>limited</em>
|
||||
and registered under corporate law {country} and here represented by {socialName}, with address in {address},
|
||||
CIF <em>{fiscalID}</em>. Hereinafter referred to as {name}.'
|
||||
issued: 'In {0}, on {1} of {2} of {3}'
|
||||
client: 'Customer {0}'
|
||||
declaration: '<em>{socialName}</em> hereby declares that:'
|
||||
declarations:
|
||||
- 'All purchases made by {socialName} with {companyName} They are delivered according to the conditions defined in the Incoterm.'
|
||||
- '{socialName} recognizes that it is important for {companyName} have
|
||||
proof of intra-community delivery of the goods to {destinationCountry} to
|
||||
be able to invoice with 0% VAT.'
|
||||
- 'Therefore, by signing this agreement, {socialName} declares that all goods
|
||||
purchased from {companyName} will be delivered to {destinationCountry}.'
|
||||
- 'Besides, {socialName} shall, at the first request of {companyName},
|
||||
provide proof that all products purchased from {companyName} have
|
||||
been delivered in {destinationCountry}.'
|
||||
- 'In addition to the above, {companyName} will provide to {socialName}
|
||||
a monthly summary that includes all bills (and corresponding deliveries).
|
||||
{socialName} will sign and return the monthly summary to {companyName},
|
||||
S.L. within 5 days of receiving the summary.'
|
||||
signer:
|
||||
representative: Representative
|
||||
representativeRole: Position of the representative
|
||||
signed: Date of signature
|
||||
manager: Manager
|
||||
months:
|
||||
- 'January'
|
||||
- 'February'
|
||||
- 'March'
|
||||
- 'April'
|
||||
- 'May'
|
||||
- 'June'
|
||||
- 'July'
|
||||
- 'August'
|
||||
- 'September'
|
||||
- 'October'
|
||||
- 'November'
|
||||
- 'December'
|
Loading…
Reference in New Issue