Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 6276-createNewWarehouse
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Jorge Penadés 2024-01-18 13:53:26 +01:00
commit d41d57143f
26 changed files with 714 additions and 88 deletions

View File

@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [2406.01] - 2024-02-08
### Added
### Changed
### Fixed
## [2404.01] - 2024-01-25
### Added

View File

@ -20,7 +20,7 @@ module.exports = Self => {
}
});
Self.internationalExpedition = async expeditionFk => {
Self.internationalExpedition = async (expeditionFk) => {
const models = Self.app.models;
const viaexpressConfig = await models.ViaexpressConfig.findOne({

View File

@ -20,11 +20,11 @@ module.exports = Self => {
}
});
Self.renderer = async expeditionFk => {
Self.renderer = async (expeditionFk) => {
const models = Self.app.models;
const viaexpressConfig = await models.ViaexpressConfig.findOne({
fields: ['client', 'user', 'password', 'defaultWeight', 'deliveryType']
fields: ['client', 'user', 'password', 'defaultWeight', 'deliveryType', 'agencyModeFk']
});
const expedition = await models.Expedition.findOne({
@ -34,7 +34,7 @@ module.exports = Self => {
{
relation: 'ticket',
scope: {
fields: ['shipped', 'addressFk', 'clientFk', 'companyFk'],
fields: ['shipped', 'addressFk', 'clientFk', 'companyFk', 'agencyModeFk'],
include: [
{
relation: 'client',
@ -102,7 +102,6 @@ module.exports = Self => {
}
]
}
}
]
});
@ -110,13 +109,15 @@ module.exports = Self => {
const ticket = expedition.ticket();
const sender = ticket.company().client();
const shipped = ticket.shipped.toISOString();
const isInterdia = (ticket.agencyModeFk === viaexpressConfig.agencyModeFk)
const data = {
viaexpressConfig,
sender,
senderAddress: sender.defaultAddress(),
client: ticket.client(),
address: ticket.address(),
shipped
shipped,
isInterdia
};
const template = fs.readFileSync(__dirname + '/template.ejs', 'utf-8');

View File

@ -13,7 +13,7 @@
<Asegurado>0</Asegurado>
<Imprimir>0</Imprimir>
<ConDevolucionAlbaran>0</ConDevolucionAlbaran>
<Intradia>0</Intradia>
<Intradia><%= isInterdia %></Intradia>
<Observaciones></Observaciones>
<AlbaranRemitente></AlbaranRemitente>
<Modo>0</Modo>

View File

@ -29,6 +29,9 @@
},
"deliveryType": {
"type": "string"
},
"agencyModeFk": {
"type": "number"
}
}
}

View File

@ -0,0 +1,589 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`sale_calculateComponent`(vSelf INT, vOption VARCHAR(25))
proc: BEGIN
/**
* Crea tabla temporal para vn.sale_recalcComponent() para recalcular los componentes
*
* @param vSelf Id de la venta
* @param vOption indica en que componente pone el descuadre, NULL en casos habituales
*/
CREATE OR REPLACE TEMPORARY TABLE tmp.recalculateSales
SELECT s.id
FROM sale s
WHERE s.id = vSelf;
CALL sale_recalcComponent(vOption);
DROP TEMPORARY TABLE tmp.recalculateSales;
END$$
DELIMITER ;
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`sale_checkNoComponents`(vCreatedFrom DATETIME, vCreatedTo DATETIME)
BEGIN
/**
* Comprueba que las ventas creadas entre un rango de fechas tienen componentes
*
* @param vCreatedFrom inicio del rango
* @param vCreatedTo fin del rango
*/
DECLARE v_done BOOL DEFAULT FALSE;
DECLARE vSaleFk INTEGER;
DECLARE vTicketFk INTEGER;
DECLARE vConcept VARCHAR(50);
DECLARE vCur CURSOR FOR
SELECT s.id
FROM sale s
JOIN ticket t ON t.id = s.ticketFk
JOIN item i ON i.id = s.itemFk
JOIN itemType tp ON tp.id = i.typeFk
JOIN itemCategory ic ON ic.id = tp.categoryFk
LEFT JOIN tmp.coste c ON c.id = s.id
WHERE s.created >= vCreatedFrom AND s.created <= vCreatedTo
AND c.id IS NULL
AND t.agencyModeFk IS NOT NULL
AND t.isDeleted IS FALSE
AND t.warehouseFk = 60
AND ic.merchandise != FALSE
GROUP BY s.id;
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET v_done = TRUE;
DROP TEMPORARY TABLE IF EXISTS tmp.coste;
DROP TEMPORARY TABLE IF EXISTS tmp.coste;
CREATE TEMPORARY TABLE tmp.coste
(PRIMARY KEY (id)) ENGINE = MEMORY
SELECT s.id
FROM sale s
JOIN item i ON i.id = s.itemFk
JOIN itemType tp ON tp.id = i.typeFk
JOIN itemCategory ic ON ic.id = tp.categoryFk
JOIN saleComponent sc ON sc.saleFk = s.id
JOIN component c ON c.id = sc.componentFk
JOIN componentType ct ON ct.id = c.typeFk AND ct.id = 6
WHERE s.created >= vCreatedFrom
AND ic.merchandise != FALSE;
OPEN vCur;
l: LOOP
SET v_done = FALSE;
FETCH vCur INTO vSaleFk;
IF v_done THEN
LEAVE l;
END IF;
SELECT ticketFk, concept
INTO vTicketFk, vConcept
FROM sale
WHERE id = vSaleFk;
CALL sale_calculateComponent(vSaleFk, 'renewPrices');
END LOOP;
CLOSE vCur;
DROP TEMPORARY TABLE tmp.coste;
END$$
DELIMITER ;
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`sale_recalcComponent`(vOption VARCHAR(25))
proc: BEGIN
/**
* Este procedimiento recalcula los componentes de un conjunto de sales,
* eliminando los componentes existentes e insertandolos de nuevo
*
* @param vOption si no se quiere forzar llamar con NULL
* @table tmp.recalculateSales (id)
*/
DECLARE vShipped DATE;
DECLARE vWarehouseFk SMALLINT;
DECLARE vAgencyModeFk INT;
DECLARE vAddressFk INT;
DECLARE vTicketFk INT;
DECLARE vLanded DATE;
DECLARE vIsEditable BOOLEAN;
DECLARE vZoneFk INTEGER;
DECLARE vDone BOOL DEFAULT FALSE;
DECLARE vCur CURSOR FOR
SELECT DISTINCT s.ticketFk
FROM tmp.recalculateSales rs
JOIN vn.sale s ON s.id = rs.id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
OPEN vCur;
l: LOOP
SET vDone = FALSE;
FETCH vCur INTO vTicketFk;
IF vDone THEN
LEAVE l;
END IF;
SELECT (hasToRecalcPrice OR ts.alertLevel IS NULL) AND t.refFk IS NULL,
t.zoneFk,
t.warehouseFk,
t.shipped,
t.addressFk,
t.agencyModeFk,
t.landed
INTO vIsEditable,
vZoneFk,
vWarehouseFk,
vShipped,
vAddressFk,
vAgencyModeFk,
vLanded
FROM ticket t
LEFT JOIN ticketState ts ON t.id = ts.ticketFk
LEFT JOIN alertLevel al ON al.id = ts.alertLevel
WHERE t.id = vTicketFk;
CALL zone_getLanded(vShipped, vAddressFk, vAgencyModeFk, vWarehouseFk, TRUE);
IF NOT EXISTS (SELECT TRUE FROM tmp.zoneGetLanded LIMIT 1) THEN
CALL util.throw(CONCAT('There is no zone for these parameters ', vTicketFk));
END IF;
IF vLanded IS NULL OR vZoneFk IS NULL THEN
UPDATE ticket t
SET t.landed = (SELECT landed FROM tmp.zoneGetLanded LIMIT 1)
WHERE t.id = vTicketFk AND t.landed IS NULL;
IF vZoneFk IS NULL THEN
SELECT zoneFk INTO vZoneFk FROM tmp.zoneGetLanded LIMIT 1;
UPDATE ticket t
SET t.zoneFk = vZoneFk
WHERE t.id = vTicketFk AND t.zoneFk IS NULL;
END IF;
END IF;
DROP TEMPORARY TABLE tmp.zoneGetLanded;
-- rellena la tabla buyUltimate con la ultima compra
CALL buyUltimate (vWarehouseFk, vShipped);
CREATE OR REPLACE TEMPORARY TABLE tmp.sale
(PRIMARY KEY (saleFk)) ENGINE = MEMORY
SELECT s.id saleFk, vWarehouseFk warehouseFk
FROM sale s
JOIN tmp.recalculateSales rs ON s.id = rs.id
WHERE s.ticketFk = vTicketFk;
CREATE OR REPLACE TEMPORARY TABLE tmp.ticketLot
SELECT vWarehouseFk warehouseFk, NULL available, s.itemFk, bu.buyFk, vZoneFk zoneFk
FROM sale s
JOIN tmp.recalculateSales rs ON s.id = rs.id
LEFT JOIN tmp.buyUltimate bu ON bu.itemFk = s.itemFk
WHERE s.ticketFk = vTicketFk
GROUP BY s.itemFk;
CALL catalog_componentPrepare();
CALL catalog_componentCalculate(vZoneFk, vAddressFk, vShipped, vWarehouseFk);
IF vOption IS NULL THEN
SET vOption = IF(vIsEditable, 'renewPrices', 'imbalance');
END IF;
CALL ticketComponentUpdateSale(vOption);
CALL catalog_componentPurge();
DROP TEMPORARY TABLE tmp.buyUltimate;
DROP TEMPORARY TABLE tmp.sale;
END LOOP;
CLOSE vCur;
END$$
DELIMITER ;
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticketCalculateClon`(IN vTicketNew INT, vTicketOld INT)
BEGIN
/*
* Recalcula los componentes un ticket clonado,
* las lineas a precio cero fuerza para que tengan precio, el resto lo respeta
* @param vTicketNew nuevo ticket clonado
* @param vTicketOld icket original, a partir del qual se clonara el nuevo
*/
REPLACE INTO orderTicket(orderFk,ticketFk)
SELECT orderFk, vTicketNew
FROM orderTicket
WHERE ticketFk = vTicketOld;
-- Bionizamos lineas con Preu = 0
CREATE OR REPLACE TEMPORARY TABLE tmp.recalculateSales
(PRIMARY KEY (id)) ENGINE = MEMORY
SELECT id
FROM sale
WHERE ticketFk = vTicketNew AND price = 0;
CALL sale_recalcComponent('renewPrices');
-- Bionizamos lineas con Preu > 0
CREATE OR REPLACE TEMPORARY TABLE tmp.recalculateSales
(PRIMARY KEY (id)) ENGINE = MEMORY
SELECT id
FROM sale
WHERE ticketFk = vTicketNew AND price > 0;
CALL sale_recalcComponent('imbalance');
DROP TEMPORARY TABLE IF EXISTS tmp.recalculateSales;
END$$
DELIMITER ;
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticketComponentUpdate`(
vTicketFk INT,
vClientFk INT,
vAgencyModeFk INT,
vAddressFk INT,
vWarehouseFk TINYINT,
vCompanyFk SMALLINT,
vShipped DATETIME,
vLanded DATE,
vIsDeleted BOOLEAN,
vHasToBeUnrouted BOOLEAN,
vOption VARCHAR(25))
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
RESIGNAL;
END;
START TRANSACTION;
IF (SELECT addressFk FROM ticket WHERE id = vTicketFk) <> vAddressFk THEN
UPDATE ticket t
JOIN address a ON a.id = vAddressFk
SET t.nickname = a.nickname
WHERE t.id = vTicketFk;
END IF;
UPDATE ticket t
SET
t.clientFk = vClientFk,
t.agencyModeFk = vAgencyModeFk,
t.addressFk = vAddressFk,
t.warehouseFk = vWarehouseFk,
t.companyFk = vCompanyFk,
t.landed = vLanded,
t.shipped = vShipped,
t.isDeleted = vIsDeleted
WHERE
t.id = vTicketFk;
IF vHasToBeUnrouted THEN
UPDATE ticket t SET t.routeFk = NULL
WHERE t.id = vTicketFk;
END IF;
DROP TEMPORARY TABLE IF EXISTS tmp.sale;
CREATE TEMPORARY TABLE tmp.sale
(PRIMARY KEY (saleFk))
ENGINE = MEMORY
SELECT id AS saleFk, vWarehouseFk warehouseFk
FROM sale s WHERE s.ticketFk = vTicketFk;
CALL ticketComponentUpdateSale (vOption);
DROP TEMPORARY TABLE tmp.sale;
COMMIT;
END$$
DELIMITER ;
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticketComponentUpdateSale`(vCode VARCHAR(25))
BEGIN
/**
* A partir de la tabla tmp.sale, crea los Movimientos_componentes
* y modifica el campo Preu de la tabla Movimientos
*
* @param i_option integer tipo de actualizacion
* @param table tmp.sale tabla memory con el campo saleFk, warehouseFk
**/
DECLARE vComponentFk INT;
IF vCode <> 'renewPrices' THEN
SELECT id INTO vComponentFk FROM component WHERE `code` = vCode;
END IF;
DELETE sc.*
FROM tmp.sale tmps
JOIN saleComponent sc ON sc.saleFk = tmps.saleFk
JOIN `component` c ON c.id = sc.componentFk
WHERE c.isRenewable;
REPLACE INTO saleComponent(saleFk, componentFk, value)
SELECT s.id, tc.componentFk, tc.cost
FROM sale s
JOIN tmp.sale tmps ON tmps.saleFk = s.id
JOIN tmp.ticketComponent tc ON tc.itemFk = s.itemFk AND tc.warehouseFk = tmps.warehouseFk
LEFT JOIN saleComponent sc ON sc.saleFk = s.id
AND sc.componentFk = tc.componentFk
LEFT JOIN `component` c ON c.id = tc.componentFk
WHERE IF(sc.componentFk IS NULL AND NOT c.isRenewable, FALSE, TRUE);
-- Añadir componente venta por paquete
REPLACE INTO saleComponent(saleFk, componentFk, value)
SELECT t.id, t.componentFk, t.cost
FROM (
SELECT s.id, tc.componentFk, tc.cost, MOD(s.quantity, b.packing) as resto
FROM vn.sale s
JOIN tmp.sale tmps ON tmps.saleFk = s.id
JOIN cache.last_buy lb ON lb.item_id = s.itemFk AND tmps.warehouseFk = lb.warehouse_id
JOIN vn.buy b ON b.id = buy_id
JOIN tmp.ticketComponent tc ON tc.itemFk = s.itemFk AND tc.warehouseFk = tmps.warehouseFk
JOIN `component` c ON c.id = tc.componentFk AND c.code = 'salePerPackage'
LEFT JOIN (
SELECT s.id
FROM vn.sale s
JOIN tmp.sale tmps ON tmps.saleFk = s.id
JOIN tmp.ticketComponent tc ON tc.itemFk = s.itemFk AND tc.warehouseFk = tmps.warehouseFk
JOIN saleComponent sc ON sc.saleFk = s.id AND sc.componentFk = tc.componentFk
JOIN `component` c ON c.id = sc.componentFk AND c.code = 'lastUnitsDiscount'
) tp ON tp.id = s.id
WHERE tp.id IS NULL
HAVING resto <> 0) t;
IF vCode <> 'renewPrices' THEN
REPLACE INTO saleComponent(saleFk, componentFk, value)
SELECT s.id, vComponentFk, ROUND((s.price * (100 - s.discount) / 100) - SUM(sc.value), 3) dif
FROM sale s
JOIN tmp.sale tmps ON tmps.saleFk = s.id
LEFT JOIN saleComponent sc ON sc.saleFk = s.id
WHERE sc.saleFk <> vComponentFk
GROUP BY s.id
HAVING dif <> 0;
ELSE
UPDATE sale s
JOIN item i on i.id = s.itemFk
JOIN itemType it on it.id = i.typeFk
JOIN (SELECT SUM(sc.value) sumValue, sc.saleFk
FROM saleComponent sc
JOIN tmp.sale tmps ON tmps.saleFk = sc.saleFk
GROUP BY sc.saleFk) sc ON sc.saleFk = s.id
SET s.price = sumValue / ((100 - s.discount) / 100)
WHERE it.code != 'PRT' ;
REPLACE INTO saleComponent(saleFk, componentFk, value)
SELECT s.id, 21, ROUND((s.price * (100 - s.discount) / 100) - SUM(value), 3) saleValue
FROM sale s
JOIN tmp.sale tmps ON tmps.saleFk = s.id
LEFT JOIN saleComponent sc ON sc.saleFk = s.id
WHERE sc.componentFk != 21
GROUP BY s.id
HAVING ROUND(saleValue, 4) <> 0;
END IF;
UPDATE sale s
JOIN (
SELECT SUM(sc.value) sumValue, sc.saleFk
FROM saleComponent sc
JOIN tmp.sale tmps ON tmps.saleFk = sc.saleFk
JOIN `component` c ON c.id = sc.componentFk
JOIN componentType ct on ct.id = c.typeFk AND ct.isBase
GROUP BY sc.saleFk) sc ON sc.saleFk = s.id
SET s.priceFixed = sumValue, s.isPriceFixed = 1;
DELETE sc.*
FROM saleComponent sc
JOIN tmp.sale tmps ON tmps.saleFk = sc.saleFk
JOIN sale s on s.id = sc.saleFk
JOIN item i ON i.id = s.itemFk
JOIN itemType it ON it.id = i.typeFk
WHERE it.code = 'PRT';
INSERT INTO saleComponent(saleFk, componentFk, value)
SELECT s.id, 15, s.price
FROM sale s
JOIN tmp.sale tmps ON tmps.saleFk = s.id
JOIN item i ON i.id = s.itemFK
JOIN itemType it ON it.id = i.typeFk
WHERE it.code = 'PRT' AND s.price > 0;
END$$
DELIMITER ;
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_checkNoComponents`(vShippedFrom DATETIME, vShippedTo DATETIME)
BEGIN
/**
* Comprueba que los tickets entre un rango de fechas tienen componentes
* y recalcula sus componentes
*
* @param vShippedFrom rango inicial de fecha
* @param vShippedTo rango final de fecha
*/
CREATE OR REPLACE TEMPORARY TABLE tmp.coste
(primary key (id)) ENGINE = MEMORY
SELECT s.id
FROM ticket t
JOIN sale s ON s.ticketFk = t.id
JOIN item i ON i.id = s.itemFk
JOIN itemType tp ON tp.id = i.typeFk
JOIN itemCategory ic ON ic.id = tp.categoryFk
JOIN saleComponent sc ON sc.saleFk = s.id
JOIN component c ON c.id = sc.componentFk
JOIN componentType ct ON ct.id = c.typeFk AND ct.id = 1
WHERE t.shipped BETWEEN vShippedFrom AND vShippedTo
AND ic.merchandise;
CREATE OR REPLACE TEMPORARY TABLE tmp.recalculateSales
(primary key (id)) ENGINE = MEMORY
SELECT DISTINCT s.id
FROM ticket t
JOIN sale s ON s.ticketFk = t.id
JOIN item i ON i.id = s.itemFk
JOIN itemType tp ON tp.id = i.typeFk
JOIN itemCategory ic ON ic.id = tp.categoryFk
LEFT JOIN tmp.coste c ON c.id = s.id
WHERE t.shipped >= vShippedFrom AND t.shipped <= vShippedTo
AND c.id IS NULL
AND ic.merchandise;
CALL sale_recalcComponent('renewPrices');
DROP TEMPORARY TABLE tmp.recalculateSales;
DROP TEMPORARY TABLE tmp.coste;
END$$
DELIMITER ;
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_componentMakeUpdate`(
vTicketFk INT,
vClientFk INT,
vNickname VARCHAR(50),
vAgencyModeFk INT,
vAddressFk INT,
vZoneFk INT,
vWarehouseFk INT,
vCompanyFk INT,
vShipped DATETIME,
vLanded DATE,
vIsDeleted BOOLEAN,
vHasToBeUnrouted BOOLEAN,
vOption VARCHAR(25))
BEGIN
/**
* Modifica en el ticket los campos que se le pasan por parámetro
* y cambia sus componentes
*
* @param vTicketFk Id del ticket a modificar
* @param vClientFk nuevo cliente
* @param vNickname nuevo alias
* @param vAgencyModeFk nueva agencia
* @param vAddressFk nuevo consignatario
* @param vZoneFk nueva zona
* @param vWarehouseFk nuevo almacen
* @param vCompanyFk nueva empresa
* @param vShipped nueva fecha del envio de mercancia
* @param vLanded nueva fecha de recepcion de mercancia
* @param vIsDeleted si se borra el ticket
* @param vHasToBeUnrouted si se le elimina la ruta al ticket
* @param vOption opcion para el case del proc ticketComponentUpdateSale
*/
DECLARE vPrice DECIMAL(10,2);
DECLARE vBonus DECIMAL(10,2);
CALL ticket_componentPreview (vTicketFk, vLanded, vAddressFk, vZoneFk, vWarehouseFk);
IF (SELECT addressFk FROM ticket WHERE id = vTicketFk) <> vAddressFk THEN
UPDATE ticket t
JOIN address a ON a.id = vAddressFk
SET t.nickname = a.nickname
WHERE t.id = vTicketFk;
END IF;
CALL zone_getShipped(vLanded, vAddressFk, vAgencyModeFk, TRUE);
SELECT zoneFk, price, bonus INTO vZoneFk, vPrice, vBonus
FROM tmp.zoneGetShipped
WHERE shipped BETWEEN DATE(vShipped) AND util.dayEnd(vShipped) AND warehouseFk = vWarehouseFk LIMIT 1;
UPDATE ticket t
SET
t.clientFk = vClientFk,
t.nickname = vNickname,
t.agencyModeFk = vAgencyModeFk,
t.addressFk = vAddressFk,
t.zoneFk = vZoneFk,
t.zonePrice = vPrice,
t.zoneBonus = vBonus,
t.warehouseFk = vWarehouseFk,
t.companyFk = vCompanyFk,
t.landed = vLanded,
t.shipped = vShipped,
t.isDeleted = vIsDeleted
WHERE
t.id = vTicketFk;
IF vHasToBeUnrouted THEN
UPDATE ticket t SET t.routeFk = NULL
WHERE t.id = vTicketFk;
END IF;
DROP TEMPORARY TABLE IF EXISTS tmp.sale;
CREATE TEMPORARY TABLE tmp.sale
(PRIMARY KEY (saleFk))
ENGINE = MEMORY
SELECT id AS saleFk, vWarehouseFk warehouseFk
FROM sale s WHERE s.ticketFk = vTicketFk;
DROP TEMPORARY TABLE IF EXISTS tmp.ticketComponent;
CREATE TEMPORARY TABLE tmp.ticketComponent
SELECT * FROM tmp.ticketComponentPreview;
CALL ticketComponentUpdateSale (vOption);
DROP TEMPORARY TABLE tmp.sale;
DROP TEMPORARY TABLE IF EXISTS tmp.ticketComponent;
DROP TEMPORARY TABLE tmp.zoneGetShipped, tmp.ticketComponentPreview;
END$$
DELIMITER ;
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_recalcComponents`(vSelf INT, vOption VARCHAR(25))
proc: BEGIN
/**
* Crea tabla temporal para sale_recalcComponent() para recalcular los componentes
*
* @param vSelf Id del ticket
* @param vOption si no se quiere forzar llamar con NULL
*/
CREATE OR REPLACE TEMPORARY TABLE tmp.recalculateSales
SELECT s.id
FROM sale s
WHERE s.ticketFk = vSelf;
CALL sale_recalcComponent(vOption);
DROP TEMPORARY TABLE tmp.recalculateSales;
END$$
DELIMITER ;
TRUNCATE TABLE `vn`.`ticketUpdateAction`;
INSERT INTO `vn`.`ticketUpdateAction` (id, description, code) VALUES(1, 'Cambiar los precios en el ticket', 'renewPrice');
INSERT INTO `vn`.`ticketUpdateAction` (id, description, code) VALUES(2, 'Convertir en maná', 'mana');

View File

View File

@ -0,0 +1,2 @@
ALTER TABLE `vn`.`viaexpressConfig` ADD agencyModeFk int DEFAULT NULL NULL COMMENT 'Indica el agencyMode que es interdia';
ALTER TABLE `vn`.`viaexpressConfig` ADD CONSTRAINT viaexpressConfig_agencyMode_Fk FOREIGN KEY (agencyModeFK) REFERENCES vn.agencyMode(id) ON DELETE RESTRICT ON UPDATE RESTRICT;

View File

@ -1,4 +1,4 @@
REVOKE UPDATE ON TABLE `vn`.`item` FROM `employee`;
GRANT UPDATE(id, equivalent, stems, minPrice, isToPrint, family, box, category, doPhoto, image, inkFk, intrastatFk, hasMinPrice, created, comment, typeFk, generic, producerFk, description, density, relevancy, expenseFk, isActive, subName, tag5, value5, tag6, value6, tag7, value7, tag8, value8, tag9, value9, tag10, value10, minimum, upToDown, supplyResponseFk, hasKgPrice, isFloramondo, isFragile, numberOfItemsPerCask, embalageCode, quality, stemMultiplier, itemPackingTypeFk, packingOut, genericFk, packingShelve, isLaid, lastUsed, weightByPiece, weightByPiece, editorFk, recycledPlastic, nonRecycledPlastic, minQuantity) ON TABLE vn.item TO employee;
GRANT UPDATE(id, equivalent, stems, minPrice, isToPrint, family, box, category, doPhoto, image, inkFk, intrastatFk, hasMinPrice, created, comment, typeFk, generic, producerFk, description, density, relevancy, expenseFk, isActive, subName, tag5, value5, tag6, value6, tag7, value7, tag8, value8, tag9, value9, tag10, value10, minimum, upToDown, supplyResponseFk, hasKgPrice, isFloramondo, isFragile, numberOfItemsPerCask, embalageCode, quality, stemMultiplier, itemPackingTypeFk, packingOut, genericFk, packingShelve, isLaid, lastUsed, weightByPiece, weightByPiece, editorFk, recycledPlastic, nonRecycledPlastic, minQuantity) ON TABLE `vn`.`item` TO `employee`;

View File

@ -1,4 +1,4 @@
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId) VALUES
INSERT INTO `salix`.`ACL` (model,property,accessType,permission,principalType,principalId) VALUES
('VnRole','*','READ','ALLOW','ROLE','employee'),
('VnRole','*','WRITE','ALLOW','ROLE','it');

View File

@ -1,2 +1,2 @@
ALTER TABLE vn.productionConfig ADD itemPreviousDefaultSize int NULL COMMENT 'Altura por defecto para los artículos de previa';
UPDATE IGNORE vn.productionConfig SET itemPreviousDefaultSize = 40 WHERE id = 1;
ALTER TABLE `vn`.`productionConfig` ADD itemPreviousDefaultSize int NULL COMMENT 'Altura por defecto para los artículos de previa';
UPDATE IGNORE `vn`.`productionConfig` SET itemPreviousDefaultSize = 40 WHERE id = 1;

View File

@ -1,9 +1,9 @@
UPDATE vn.supplierAccount sa
JOIN vn.country c ON sa.countryFk = c.id AND c.code = 'FR'
UPDATE `vn`.`supplierAccount` sa
JOIN `vn`.`country` c ON sa.countryFk = c.id AND c.code = 'FR'
SET countryFk = c.id
WHERE iban = 'FR7630003012690002801121597';
UPDATE vn.supplierAccount sa
JOIN vn.country c ON sa.countryFk = c.id AND c.code = 'PT'
UPDATE `vn`.`supplierAccount` sa
JOIN `vn`.`country` c ON sa.countryFk = c.id AND c.code = 'PT'
SET countryFk = c.id
WHERE iban = 'PT50001000005813059150168';

View File

@ -1,2 +1,2 @@
ALTER TABLE vn.invoiceOutConfig
ALTER TABLE `vn`.`invoiceOutConfig`
ADD IF NOT EXISTS refLen TINYINT UNSIGNED DEFAULT 5 NOT NULL COMMENT 'Invoice reference identifier length';

View File

View File

@ -270,8 +270,8 @@ class VnMySQL extends MySQL {
isLoggable(model) {
const Model = this.getModelDefinition(model).model;
const settings = Model.definition.settings;
return settings.base && settings.base === 'Loggable';
const {settings} = Model.definition;
return settings?.mixins?.Loggable;
}
invokeMethod(method, args, model, ctx, opts, cb) {
@ -291,7 +291,7 @@ class VnMySQL extends MySQL {
}
try {
const userId = opts.httpCtx && opts.httpCtx.active.accessToken.userId;
const userId = opts.httpCtx && opts.httpCtx.active?.accessToken?.userId;
if (userId) {
const user = await Model.app.models.VnUser.findById(userId, {fields: ['name']}, opts);
await this.executeP(`CALL account.myUser_loginWithName(?)`, [user.name], opts);

View File

@ -14,17 +14,30 @@ module.exports = Self => {
}
try {
const salesFilter = {
where: {id: {inq: salesIds}},
include: {
relation: 'components',
scope: {
fields: ['saleFk', 'componentFk', 'value']
let sales;
let services;
if (salesIds && salesIds.length) {
sales = await models.Sale.find({
where: {id: {inq: salesIds}},
include: {
relation: 'components',
scope: {
fields: ['saleFk', 'componentFk', 'value']
}
}
}
};
const sales = await models.Sale.find(salesFilter, myOptions);
let ticketsIds = [...new Set(sales.map(sale => sale.ticketFk))];
}, myOptions);
}
if (servicesIds && servicesIds.length) {
services = await models.TicketService.find({
where: {id: {inq: servicesIds}}
}, myOptions);
}
let ticketsIds = sales ?
[...new Set(sales.map(sale => sale.ticketFk))] :
[...new Set(services.map(service => service.ticketFk))];
const mappedTickets = new Map();
@ -39,32 +52,28 @@ module.exports = Self => {
newTickets.push(newTicket);
mappedTickets.set(ticketId, newTicket.id);
}
if (sales) {
for (const sale of sales) {
const newTicketId = mappedTickets.get(sale.ticketFk);
for (const sale of sales) {
const newTicketId = mappedTickets.get(sale.ticketFk);
const createdSale = await models.Sale.create({
ticketFk: newTicketId,
itemFk: sale.itemFk,
quantity: negative ? - sale.quantity : sale.quantity,
concept: sale.concept,
price: sale.price,
discount: sale.discount,
}, myOptions);
const createdSale = await models.Sale.create({
ticketFk: newTicketId,
itemFk: sale.itemFk,
quantity: negative ? - sale.quantity : sale.quantity,
concept: sale.concept,
price: sale.price,
discount: sale.discount,
}, myOptions);
const components = sale.components();
for (const component of components)
component.saleFk = createdSale.id;
const components = sale.components();
for (const component of components)
component.saleFk = createdSale.id;
await models.SaleComponent.create(components, myOptions);
await models.SaleComponent.create(components, myOptions);
}
}
if (servicesIds && servicesIds.length) {
const servicesFilter = {
where: {id: {inq: servicesIds}}
};
const services = await models.TicketService.find(servicesFilter, myOptions);
if (services) {
for (const service of services) {
const newTicketId = mappedTickets.get(service.ticketFk);

View File

@ -6,7 +6,6 @@ module.exports = Self => {
{
arg: 'salesIds',
type: ['number'],
required: true
},
{
arg: 'servicesIds',

View File

@ -44,24 +44,7 @@ describe('Sale refund()', () => {
const tickets = await models.Sale.refund(ctx, salesIds, servicesIds, withWarehouse, options);
const refundedTicket = await models.Ticket.findOne({
where: {
id: tickets[0].id
},
include: [
{
relation: 'ticketSales',
scope: {
include: {
relation: 'components'
}
}
},
{
relation: 'ticketServices',
}
]
}, options);
const refundedTicket = await getTicketRefund(tickets[0].id, options);
const ticketsAfter = await models.Ticket.find({}, options);
const salesLength = refundedTicket.ticketSales().length;
const componentsLength = refundedTicket.ticketSales()[0].components().length;
@ -77,4 +60,42 @@ describe('Sale refund()', () => {
throw e;
}
});
it('should create a ticket without sales', async() => {
const servicesIds = [4];
const tx = await models.Sale.beginTransaction({});
const options = {transaction: tx};
try {
const tickets = await models.Sale.refund(ctx, null, servicesIds, withWarehouse, options);
const refundedTicket = await getTicketRefund(tickets[0].id, options);
expect(refundedTicket).toBeDefined();
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});
async function getTicketRefund(id, options) {
return models.Ticket.findOne({
where: {
id
},
include: [
{
relation: 'ticketSales',
scope: {
include: {
relation: 'components'
}
}
},
{
relation: 'ticketServices',
}
]
}, options);
}

View File

@ -74,8 +74,8 @@ module.exports = Self => {
},
{
arg: 'option',
type: 'number',
description: 'Action id'
type: 'string',
description: 'Action code'
},
{
arg: 'isWithoutNegatives',

View File

@ -60,7 +60,7 @@ describe('ticket componentUpdate()', () => {
shipped: today,
landed: tomorrow,
isDeleted: false,
option: 1,
option: 'renewPrices',
isWithoutNegatives: false
};
@ -110,7 +110,7 @@ describe('ticket componentUpdate()', () => {
shipped: today,
landed: tomorrow,
isDeleted: false,
option: 1,
option: 'renewPrices',
isWithoutNegatives: false
};
@ -176,7 +176,7 @@ describe('ticket componentUpdate()', () => {
shipped: newDate,
landed: tomorrow,
isDeleted: false,
option: 1,
option: 'renewPrices',
isWithoutNegatives: true
};
@ -235,7 +235,7 @@ describe('ticket componentUpdate()', () => {
shipped: newDate,
landed: tomorrow,
isDeleted: false,
option: 1,
option: 'renewPrices',
isWithoutNegatives: false,
keepPrice: true
};
@ -288,7 +288,7 @@ describe('ticket componentUpdate()', () => {
shipped: newDate,
landed: tomorrow,
isDeleted: false,
option: 1,
option: 'renewPrices',
isWithoutNegatives: false,
keepPrice: false
};

View File

@ -76,7 +76,7 @@
<vn-radio
ng-model="$ctrl.ticket.option"
label="{{::action.description}}"
val={{::action.id}}>
val={{::action.code}}>
</vn-radio>
</div>
</div>

View File

@ -25,12 +25,7 @@ class Controller extends Component {
loadDefaultTicketAction() {
const isSalesAssistant = this.aclService.hasAny(['salesAssistant']);
const defaultOption = isSalesAssistant ? 'turnInMana' : 'changePrice';
const filter = {where: {code: defaultOption}};
this.$http.get(`TicketUpdateActions`, {filter}).then(response => {
return this.ticket.option = response.data[0].id;
});
this.ticket.option = isSalesAssistant ? 'mana' : 'buyerDiscount';
}
onStepChange() {
@ -112,7 +107,7 @@ class Controller extends Component {
shipped: this.ticket.shipped,
landed: this.ticket.landed,
isDeleted: this.ticket.isDeleted,
option: parseInt(this.ticket.option),
option: this.ticket.option,
isWithoutNegatives: this.ticket.withoutNegatives,
withWarningAccept: this.ticket.withWarningAccept,
keepPrice: false

View File

@ -3,7 +3,7 @@ const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethodCtx('updateTimeEntry', {
description: 'Updates a time entry for a worker if the user role is above the worker',
accessType: 'READ',
accessType: 'WRITE',
accepts: [{
arg: 'id',
type: 'number',

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "salix-back",
"version": "24.04.01",
"version": "24.06.01",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "salix-back",
"version": "24.04.01",
"version": "24.06.01",
"license": "GPL-3.0",
"dependencies": {
"axios": "^1.2.2",

View File

@ -1,6 +1,6 @@
{
"name": "salix-back",
"version": "24.04.01",
"version": "24.06.01",
"author": "Verdnatura Levante SL",
"description": "Salix backend",
"license": "GPL-3.0",