Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 3245-print_refactor
gitea/salix/pipeline/head There was a failure building this commit Details

This commit is contained in:
Joan Sanchez 2022-01-18 13:57:26 +01:00
commit 352c3205bf
59 changed files with 2622 additions and 25486 deletions

View File

@ -120,7 +120,7 @@ module.exports = Self => {
} }
const defaultOptions = { const defaultOptions = {
body: params form: params
}; };
if (options) Object.assign(defaultOptions, options); if (options) Object.assign(defaultOptions, options);

View File

@ -1,4 +0,0 @@
DELETE FROM `salix`.`ACL` WHERE id = 48;
DELETE FROM `salix`.`ACL` WHERE id = 49;
DELETE FROM `salix`.`ACL` WHERE id = 50;
DELETE FROM `salix`.`ACL` WHERE id = 107;

View File

@ -1,197 +0,0 @@
drop procedure `vn`.`sale_getProblems`;
DELIMITER $$
$$
create
definer = root@`%` procedure `vn`.`sale_getProblems`(IN vIsTodayRelative tinyint(1))
BEGIN
/**
* Calcula los problemas de cada venta
* para un conjunto de tickets.
*
* @table tmp.sale_getProblems(ticketFk, clientFk, warehouseFk, shipped) Identificadores de los tickets a calcular
* @return tmp.sale_problems
*/
DECLARE vWarehouse INT;
DECLARE vDate DATE;
DECLARE vAvailableCache INT;
DECLARE vDone INT DEFAULT 0;
DECLARE vComponentCount INT;
DECLARE vCursor CURSOR FOR
SELECT DISTINCT tt.warehouseFk, IF(vIsTodayRelative, CURDATE(), date(tt.shipped))
FROM tmp.sale_getProblems tt
WHERE DATE(tt.shipped) BETWEEN CURDATE()
AND TIMESTAMPADD(DAY, IF(vIsTodayRelative, 9.9, 1.9), CURDATE());
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = 1;
DROP TEMPORARY TABLE IF EXISTS tmp.sale_problems;
CREATE TEMPORARY TABLE tmp.sale_problems (
ticketFk INT(11),
saleFk INT(11),
isFreezed INTEGER(1) DEFAULT 0,
risk DECIMAL(10,2) DEFAULT 0,
hasHighRisk TINYINT(1) DEFAULT 0,
hasTicketRequest INTEGER(1) DEFAULT 0,
isAvailable INTEGER(1) DEFAULT 1,
itemShortage VARCHAR(250),
isTaxDataChecked INTEGER(1) DEFAULT 1,
itemDelay VARCHAR(250),
hasComponentLack INTEGER(1),
PRIMARY KEY (ticketFk, saleFk)
) ENGINE = MEMORY;
DROP TEMPORARY TABLE IF EXISTS tmp.ticket_list;
CREATE TEMPORARY TABLE tmp.ticket_list
(PRIMARY KEY (ticketFk))
ENGINE = MEMORY
SELECT tp.ticketFk, c.id clientFk
FROM tmp.sale_getProblems tp
JOIN vn.client c ON c.id = tp.clientFk;
SELECT COUNT(*) INTO vComponentCount
FROM vn.component c
WHERE c.isRequired;
INSERT INTO tmp.sale_problems(ticketFk, hasComponentLack, saleFk)
SELECT tl.ticketFk, (COUNT(DISTINCT s.id) * vComponentCount > COUNT(c.id)), s.id
FROM tmp.ticket_list tl
JOIN vn.sale s ON s.ticketFk = tl.ticketFk
LEFT JOIN vn.saleComponent sc ON sc.saleFk = s.id
LEFT JOIN vn.component c ON c.id = sc.componentFk AND c.isRequired
JOIN vn.ticket t ON t.id = tl.ticketFk
JOIN vn.agencyMode am ON am.id = t.agencyModeFk
JOIN vn.deliveryMethod dm ON dm.id = am.deliveryMethodFk
WHERE dm.code IN('AGENCY','DELIVERY','PICKUP')
GROUP BY tl.ticketFk, s.id;
INSERT INTO tmp.sale_problems(ticketFk, isFreezed)
SELECT DISTINCT tl.ticketFk, TRUE
FROM tmp.ticket_list tl
JOIN vn.client c ON c.id = tl.clientFk
WHERE c.isFreezed
ON DUPLICATE KEY UPDATE
isFreezed = c.isFreezed;
DROP TEMPORARY TABLE IF EXISTS tmp.clientGetDebt;
CREATE TEMPORARY TABLE tmp.clientGetDebt
(PRIMARY KEY (clientFk))
ENGINE = MEMORY
SELECT DISTINCT clientFk
FROM tmp.ticket_list;
CALL clientGetDebt(CURDATE());
INSERT INTO tmp.sale_problems(ticketFk, risk, hasHighRisk)
SELECT DISTINCT tl.ticketFk, r.risk, ((r.risk - cc.riskTolerance) > c.credit + 10)
FROM tmp.ticket_list tl
JOIN vn.ticket t ON t.id = tl.ticketFk
JOIN vn.agencyMode a ON t.agencyModeFk = a.id
JOIN tmp.risk r ON r.clientFk = t.clientFk
JOIN vn.client c ON c.id = t.clientFk
JOIN vn.clientConfig cc
WHERE r.risk > c.credit + 10
AND a.isRiskFree = FALSE
ON DUPLICATE KEY UPDATE
risk = r.risk, hasHighRisk = ((r.risk - cc.riskTolerance) > c.credit + 10);
INSERT INTO tmp.sale_problems(ticketFk, hasTicketRequest)
SELECT DISTINCT tl.ticketFk, TRUE
FROM tmp.ticket_list tl
JOIN vn.ticketRequest tr ON tr.ticketFk = tl.ticketFk
WHERE tr.isOK IS NULL
ON DUPLICATE KEY UPDATE
hasTicketRequest = TRUE;
OPEN vCursor;
WHILE NOT vDone
DO
FETCH vCursor INTO vWarehouse, vDate;
CALL cache.available_refresh(vAvailableCache, FALSE, vWarehouse, vDate);
INSERT INTO tmp.sale_problems(ticketFk, isAvailable, saleFk)
SELECT tl.ticketFk, FALSE, s.id
FROM tmp.ticket_list tl
JOIN vn.ticket t ON t.id = tl.ticketFk
JOIN vn.sale s ON s.ticketFk = t.id
JOIN vn.item i ON i.id = s.itemFk
JOIN vn.itemType it on it.id = i.typeFk
LEFT JOIN cache.available av ON av.item_id = i.id
AND av.calc_id = vAvailableCache
WHERE date(t.shipped) = vDate
AND it.categoryFk != 6
AND IFNULL(av.available, 0) < 0
AND s.isPicked = FALSE
AND NOT i.generic
AND vWarehouse = t.warehouseFk
GROUP BY tl.ticketFk
ON DUPLICATE KEY UPDATE
isAvailable = FALSE, saleFk = VALUES(saleFk);
INSERT INTO tmp.sale_problems(ticketFk, itemShortage, saleFk)
SELECT ticketFk, problem, saleFk
FROM (
SELECT tl.ticketFk, CONCAT('F: ',GROUP_CONCAT(i.id, ' ', i.longName, ' ')) problem, s.id AS saleFk
FROM tmp.ticket_list tl
JOIN vn.ticket t ON t.id = tl.ticketFk
JOIN vn.sale s ON s.ticketFk = t.id
JOIN vn.item i ON i.id = s.itemFk
JOIN vn.itemType it on it.id = i.typeFk
LEFT JOIN vn.itemShelvingStock_byWarehouse issw ON issw.itemFk = i.id AND issw.warehouseFk = t.warehouseFk
LEFT JOIN cache.available av ON av.item_id = i.id AND av.calc_id = vAvailableCache
WHERE IFNULL(av.available, 0) < 0
AND s.quantity > IFNULL(issw.visible, 0)
AND s.quantity > 0
AND s.isPicked = FALSE
AND s.reserved = FALSE
AND it.categoryFk != 6
AND IF(vIsTodayRelative, TRUE, date(t.shipped) = vDate)
AND NOT i.generic
AND CURDATE() = vDate
AND t.warehouseFk = vWarehouse
GROUP BY tl.ticketFk LIMIT 1) sub
ON DUPLICATE KEY UPDATE
itemShortage = sub.problem, saleFk = sub.saleFk;
INSERT INTO tmp.sale_problems(ticketFk, itemDelay, saleFk)
SELECT ticketFk, problem, saleFk
FROM (
SELECT tl.ticketFk, GROUP_CONCAT('I: ',i.id, ' ', i.longName, ' ') problem, s.id AS saleFk
FROM tmp.ticket_list tl
JOIN vn.ticket t ON t.id = tl.ticketFk
JOIN vn.sale s ON s.ticketFk = t.id
JOIN vn.item i ON i.id = s.itemFk
JOIN vn.itemType it on it.id = i.typeFk
LEFT JOIN vn.itemShelvingStock_byWarehouse issw ON issw.itemFk = i.id AND issw.warehouseFk = t.warehouseFk
WHERE s.quantity > IFNULL(issw.visible, 0)
AND s.quantity > 0
AND s.isPicked = FALSE
AND s.reserved = FALSE
AND it.categoryFk != 6
AND IF(vIsTodayRelative, TRUE, date(t.shipped) = vDate)
AND NOT i.generic
AND CURDATE() = vDate
AND t.warehouseFk = vWarehouse
GROUP BY tl.ticketFk LIMIT 1) sub
ON DUPLICATE KEY UPDATE
itemDelay = sub.problem, saleFk = sub.saleFk;
END WHILE;
CLOSE vCursor;
INSERT INTO tmp.sale_problems(ticketFk, isTaxDataChecked)
SELECT DISTINCT tl.ticketFk, FALSE
FROM tmp.ticket_list tl
JOIN vn.client c ON c.id = tl.clientFk
WHERE c.isTaxDataChecked = FALSE
ON DUPLICATE KEY UPDATE
isTaxDataChecked = FALSE;
DROP TEMPORARY TABLE
tmp.clientGetDebt,
tmp.ticket_list;
END;;$$
DELIMITER ;

View File

@ -1,48 +0,0 @@
drop procedure `vn`.`ticket_getProblems`;
DELIMITER $$
$$
create
definer = root@`%` procedure `vn`.`ticket_getProblems`(IN vIsTodayRelative tinyint(1))
BEGIN
/**
* Calcula los problemas para un conjunto de tickets.
* Agrupados por ticket
*
* @table tmp.sale_getProblems(ticketFk, clientFk, warehouseFk, shipped) Identificadores de los tickets a calcular
* @return tmp.ticket_problems
*/
CALL sale_getProblems(vIsTodayRelative);
DROP TEMPORARY TABLE IF EXISTS tmp.ticket_problems;
CREATE TEMPORARY TABLE tmp.ticket_problems
(INDEX (ticketFk))
ENGINE = MEMORY
SELECT
ticketFk,
MAX(p.isFreezed) AS isFreezed,
MAX(p.risk) AS risk,
MAX(p.hasHighRisk) AS hasHighRisk,
MAX(p.hasTicketRequest) AS hasTicketRequest,
MIN(p.isAvailable) AS isAvailable,
MAX(p.itemShortage) AS itemShortage,
MIN(p.isTaxDataChecked) AS isTaxDataChecked,
MAX(p.hasComponentLack) AS hasComponentLack,
0 AS totalProblems
FROM tmp.sale_problems p
GROUP BY ticketFk;
UPDATE tmp.ticket_problems tp
SET tp.totalProblems = (
(tp.isFreezed) +
IF(tp.risk, TRUE, FALSE) +
(tp.hasTicketRequest) +
(tp.isAvailable = 0) +
(tp.isTaxDataChecked = 0) +
(tp.hasComponentLack)
);
DROP TEMPORARY TABLE
tmp.sale_problems;
END;;$$
DELIMITER ;

View File

@ -1 +0,0 @@
alter table `vn`.`travelThermograph` modify `temperature` enum('COOL', 'WARM') null;

View File

@ -1 +0,0 @@
UPDATE salix.ACL t SET t.principalId = 'employee' WHERE t.id = 269;

View File

@ -1,3 +0,0 @@
ALTER TABLE vn.accountingType ADD maxAmount INT DEFAULT NULL NULL;
UPDATE vn.accountingType SET maxAmount = 1000 WHERE code = 'cash';

View File

@ -1,4 +0,0 @@
ALTER TABLE vn.payMethod CHANGE ibanRequired ibanRequiredForClients tinyint(3) DEFAULT 0 NULL;
ALTER TABLE vn.payMethod ADD ibanRequiredForSuppliers tinyint(3) DEFAULT 0 NULL;
ALTER TABLE vn.payMethod CHANGE ibanRequiredForSuppliers ibanRequiredForSuppliers tinyint(3) DEFAULT 0 NULL AFTER ibanRequiredForClients;
UPDATE vn.payMethod SET ibanRequiredForSuppliers = 1 WHERE code = 'wireTransfer';

View File

@ -1,2 +0,0 @@
ALTER TABLE vn.silexACL MODIFY module VARCHAR(50) NOT NULL;
ALTER TABLE vn.silexACL MODIFY method VARCHAR(50) NOT NULL;

View File

@ -1,48 +0,0 @@
drop procedure `vn`.`ticket_getProblems`;
DELIMITER $$
$$
create
definer = root@`%` procedure `vn`.`ticket_getProblems`(IN vIsTodayRelative tinyint(1))
BEGIN
/**
* Calcula los problemas para un conjunto de tickets.
* Agrupados por ticket
*
* @table tmp.sale_getProblems(ticketFk, clientFk, warehouseFk, shipped) Identificadores de los tickets a calcular
* @return tmp.ticket_problems
*/
CALL sale_getProblems(vIsTodayRelative);
DROP TEMPORARY TABLE IF EXISTS tmp.ticket_problems;
CREATE TEMPORARY TABLE tmp.ticket_problems
(PRIMARY KEY (ticketFk))
ENGINE = MEMORY
SELECT
ticketFk,
MAX(p.isFreezed) AS isFreezed,
MAX(p.risk) AS risk,
MAX(p.hasHighRisk) AS hasHighRisk,
MAX(p.hasTicketRequest) AS hasTicketRequest,
MIN(p.isAvailable) AS isAvailable,
MAX(p.itemShortage) AS itemShortage,
MIN(p.isTaxDataChecked) AS isTaxDataChecked,
MAX(p.hasComponentLack) AS hasComponentLack,
0 AS totalProblems
FROM tmp.sale_problems p
GROUP BY ticketFk;
UPDATE tmp.ticket_problems tp
SET tp.totalProblems = (
(tp.isFreezed) +
IF(tp.risk, TRUE, FALSE) +
(tp.hasTicketRequest) +
(tp.isAvailable = 0) +
(tp.isTaxDataChecked = 0) +
(tp.hasComponentLack)
);
DROP TEMPORARY TABLE
tmp.sale_problems;
END;;$$
DELIMITER ;

View File

@ -1,14 +0,0 @@
CREATE TABLE `salix`.`defaultViewConfig`
(
tableCode VARCHAR(25) not null,
columns JSON not null
)
comment 'The default configuration of columns for views';
INSERT INTO `salix`.`defaultViewConfig` (tableCode, columns)
VALUES
('itemsIndex', '{"intrastat":false,"stemMultiplier":false,"landed":false}'),
('latestBuys', '{"intrastat":false,"description":false,"density":false,"isActive":false,"freightValue":false,"packageValue":false,"isIgnored":false,"price2":false,"minPrice":true,"ektFk":false,"weight":false,"id":true,"packing":true,"grouping":true,"quantity":true,"size":false,"name":true,"code":true,"origin":true,"family":true,"entryFk":true,"buyingValue":true,"comissionValue":false,"price3":true,"packageFk":true,"packingOut":true}'),
('ticketsMonitor', '{"id":false}');

View File

@ -0,0 +1,38 @@
USE vn;
DELIMITER $$
$$
CREATE OR REPLACE
ALGORITHM = UNDEFINED VIEW `vn`.`saleVolume` AS
select
`s`.`ticketFk` AS `ticketFk`,
`s`.`id` AS `saleFk`,
round(`ic`.`cm3delivery` * `s`.`quantity` / 1000, 0) AS `litros`,
`t`.`routeFk` AS `routeFk`,
`t`.`shipped` AS `shipped`,
`t`.`landed` AS `landed`,
`s`.`quantity` * `ic`.`cm3delivery` / 1000000 AS `volume`,
`s`.`quantity` * `ic`.`grams` / 1000 AS `physicalWeight`,
`s`.`quantity` * `ic`.`cm3delivery` * greatest(`i`.`density`, 167) / 1000000 AS `weight`,
`s`.`quantity` * `ic`.`cm3delivery` / 1000000 AS `physicalVolume`,
`s`.`quantity` * `ic`.`cm3delivery` * ifnull(`t`.`zonePrice`, `z`.`price`) / (`vc`.`standardFlowerBox` * 1000) AS `freight`,
`t`.`zoneFk` AS `zoneFk`,
`t`.`clientFk` AS `clientFk`,
`s`.`isPicked` AS `isPicked`,
`s`.`quantity` * `s`.`price` * (100 - `s`.`discount`) / 100 AS `eurosValue`,
`i`.`itemPackingTypeFk` AS `itemPackingTypeFk`
from
(((((`sale` `s`
join `item` `i` on
(`i`.`id` = `s`.`itemFk`))
join `ticket` `t` on
(`t`.`id` = `s`.`ticketFk`))
join `zone` `z` on
(`z`.`id` = `t`.`zoneFk`))
join `volumeConfig` `vc`)
join `itemCost` `ic` on
(`ic`.`itemFk` = `s`.`itemFk`
and `ic`.`warehouseFk` = `t`.`warehouseFk`))
where
`s`.`quantity` > 0;
$$
DELIMITER ;

View File

@ -0,0 +1,5 @@
ALTER TABLE `vn`.`smsConfig` ADD apiKey varchar(50) NULL;
ALTER TABLE `vn`.`smsConfig` CHANGE `user` user__ varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL;
ALTER TABLE `vn`.`smsConfig` CHANGE password password__ varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL;
ALTER TABLE `vn`.`sms` MODIFY COLUMN statusCode smallint(9) DEFAULT 0 NULL;
ALTER TABLE `vn`.`sms` MODIFY COLUMN status varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT 'OK' NULL;

View File

@ -0,0 +1,25 @@
ALTER TABLE `postgresql`.`business` ADD payedHolidays INT NULL;
ALTER TABLE `postgresql`.`business` CHANGE payedHolidays payedHolidays INT NULL AFTER reasonEndFk;
CREATE OR REPLACE
ALGORITHM = UNDEFINED VIEW `vn`.`workerLabour` AS
select
`b`.`business_id` AS `businessFk`,
`p`.`id_trabajador` AS `workerFk`,
`bl`.`workcenter_id` AS `workCenterFk`,
`b`.`date_start` AS `started`,
`b`.`date_end` AS `ended`,
`d`.`id` AS `departmentFk`,
`b`.`payedHolidays` AS `payedHolidays`
from
((((`postgresql`.`person` `p`
join `postgresql`.`profile` `pr` on
((`pr`.`person_id` = `p`.`person_id`)))
join `postgresql`.`business` `b` on
((`b`.`client_id` = `pr`.`profile_id`)))
join `postgresql`.`business_labour` `bl` on
((`b`.`business_id` = `bl`.`business_id`)))
join `vn`.`department` `d` on
((`d`.`id` = `bl`.`department_id`)))
order by
`b`.`date_start` desc

View File

@ -0,0 +1,7 @@
UPDATE `vn`.`smsConfig`
SET `uri` = 'https://api.gateway360.com/api/3.0/sms/send'
WHERE `id` = 1;
UPDATE `vn`.`smsConfig`
SET `apiKey` = '5715476da95b46d686a5a255e6459523'
WHERE `id` = 1;

File diff suppressed because one or more lines are too long

View File

@ -801,25 +801,25 @@ INSERT INTO `vn`.`itemFamily`(`code`, `description`)
('VT', 'Sales'); ('VT', 'Sales');
INSERT INTO `vn`.`item`(`id`, `typeFk`, `size`, `inkFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `expenceFk`, INSERT INTO `vn`.`item`(`id`, `typeFk`, `size`, `inkFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `expenceFk`,
`comment`, `relevancy`, `image`, `subName`, `minPrice`, `stars`, `family`, `isFloramondo`, `genericFk`) `comment`, `relevancy`, `image`, `subName`, `minPrice`, `stars`, `family`, `isFloramondo`, `genericFk`, `itemPackingTypeFk`)
VALUES VALUES
(1, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '1', NULL, 0, 1, 'VT', 0, NULL), (1, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '1', NULL, 0, 1, 'VT', 0, NULL, 'V'),
(2, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '2', NULL, 0, 2, 'VT', 0, NULL), (2, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '2', NULL, 0, 2, 'VT', 0, NULL, 'H'),
(3, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '3', NULL, 0, 5, 'VT', 0, NULL), (3, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '3', NULL, 0, 5, 'VT', 0, NULL, NULL),
(4, 1, 60, 'YEL', 1, 1, 'Increases block', 1, 05080000, 4751000000, NULL, 0, '4', NULL, 0, 3, 'VT', 0, NULL), (4, 1, 60, 'YEL', 1, 1, 'Increases block', 1, 05080000, 4751000000, NULL, 0, '4', NULL, 0, 3, 'VT', 0, NULL, NULL),
(5, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '5', NULL, 0, 3, 'VT', 0, NULL), (5, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '5', NULL, 0, 3, 'VT', 0, NULL, NULL),
(6, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '6', NULL, 0, 4, 'VT', 0, NULL), (6, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '6', NULL, 0, 4, 'VT', 0, NULL, NULL),
(7, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '7', NULL, 0, 4, 'VT', 0, NULL), (7, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '7', NULL, 0, 4, 'VT', 0, NULL, NULL),
(8, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '8', NULL, 0, 5, 'VT', 0, NULL), (8, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '8', NULL, 0, 5, 'VT', 0, NULL, NULL),
(9, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '9', NULL, 0, 4, 'VT', 1, NULL), (9, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '9', NULL, 0, 4, 'VT', 1, NULL, NULL),
(10, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '10', NULL, 0, 4, 'VT', 0, NULL), (10, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '10', NULL, 0, 4, 'VT', 0, NULL, NULL),
(11, 1, 60, 'YEL', 1, 1, NULL, 1, 05080000, 4751000000, NULL, 0, '11', NULL, 0, 4, 'VT', 0, NULL), (11, 1, 60, 'YEL', 1, 1, NULL, 1, 05080000, 4751000000, NULL, 0, '11', NULL, 0, 4, 'VT', 0, NULL, NULL),
(12, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '12', NULL, 0, 3, 'VT', 0, NULL), (12, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '12', NULL, 0, 3, 'VT', 0, NULL, NULL),
(13, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '13', NULL, 0, 2, 'VT', 1, NULL), (13, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '13', NULL, 0, 2, 'VT', 1, NULL, NULL),
(14, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 4, 'VT', 1, NULL), (14, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 4, 'VT', 1, NULL, NULL),
(15, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'EMB', 0, NULL), (15, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'EMB', 0, NULL, NULL),
(16, 6, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'EMB', 0, NULL), (16, 6, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'EMB', 0, NULL, NULL),
(71, 6, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'VT', 0, NULL); (71, 6, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'VT', 0, NULL, NULL);
-- Update the taxClass after insert of the items -- Update the taxClass after insert of the items
UPDATE `vn`.`itemTaxCountry` SET `taxClassFk` = 2 UPDATE `vn`.`itemTaxCountry` SET `taxClassFk` = 2
@ -1294,11 +1294,11 @@ INSERT INTO `vn`.`supplierAddress`(`id`, `supplierFk`, `nickname`, `street`, `pr
(5, 442, 'GCR building', 'Bristol district', 1, '46000', 'Gotham', '111111111', '222222222'), (5, 442, 'GCR building', 'Bristol district', 1, '46000', 'Gotham', '111111111', '222222222'),
(6, 442, 'The Gotham Tonight building', 'Bristol district', 1, '46000', 'Gotham', '111111111', '222222222'); (6, 442, 'The Gotham Tonight building', 'Bristol district', 1, '46000', 'Gotham', '111111111', '222222222');
INSERT INTO `vn`.`supplier`(`id`, `name`, `nickname`,`account`,`countryFk`,`nif`,`isFarmer`,`commission`, `created`, `isActive`, `street`, `city`, `provinceFk`, `postCode`, `payMethodFk`, `payDemFk`, `payDay`, `taxTypeSageFk`, `withholdingSageFk`, `transactionTypeSageFk`, `workerFk`, `supplierActivityFk`, `isPayMethodChecked`) INSERT INTO `vn`.`supplier`(`id`, `name`, `nickname`,`account`,`countryFk`,`nif`, `commission`, `created`, `isActive`, `street`, `city`, `provinceFk`, `postCode`, `payMethodFk`, `payDemFk`, `payDay`, `taxTypeSageFk`, `withholdingSageFk`, `transactionTypeSageFk`, `workerFk`, `supplierActivityFk`, `isPayMethodChecked`)
VALUES VALUES
(1, 'Plants SL', 'Plants nick', 4100000001, 1, '06089160W', 0, 0, CURDATE(), 1, 'supplier address 1', 'PONTEVEDRA', 1, 15214, 1, 1, 15, 4, 1, 1, 18, 'flowerPlants', 1), (1, 'Plants SL', 'Plants nick', 4100000001, 1, '06089160W', 0, CURDATE(), 1, 'supplier address 1', 'PONTEVEDRA', 1, 15214, 1, 1, 15, 4, 1, 1, 18, 'flowerPlants', 1),
(2, 'Farmer King', 'The farmer', 4000020002, 1, '87945234L', 1, 0, CURDATE(), 1, 'supplier address 2', 'SILLA', 2, 43022, 1, 2, 10, 93, 2, 8, 18, 'animals', 1), (2, 'Farmer King', 'The farmer', 4000020002, 1, '87945234L', 0, CURDATE(), 1, 'supplier address 2', 'SILLA', 2, 43022, 1, 2, 10, 93, 2, 8, 18, 'animals', 1),
(442, 'Verdnatura Levante SL', 'Verdnatura', 5115000442, 1, '06815934E', 0, 0, CURDATE(), 1, 'supplier address 3', 'SILLA', 1, 43022, 1, 2, 15, 6, 9, 3, 18, 'flowerPlants', 1); (442, 'Verdnatura Levante SL', 'Verdnatura', 5115000442, 1, '06815934E', 0, CURDATE(), 1, 'supplier address 3', 'SILLA', 1, 43022, 1, 2, 15, 6, 9, 3, 18, 'flowerPlants', 1);
INSERT INTO `vn`.`supplierContact`(`id`, `supplierFk`, `phone`, `mobile`, `email`, `observation`, `name`) INSERT INTO `vn`.`supplierContact`(`id`, `supplierFk`, `phone`, `mobile`, `email`, `observation`, `name`)
VALUES VALUES
@ -1908,9 +1908,9 @@ INSERT INTO `postgresql`.`calendar_employee` (`business_id`, `calendar_state_id`
(1107, 1, IF(MONTH(CURDATE()) >= 1 AND DAY(CURDATE()) > 20, DATE_ADD(CURDATE(), INTERVAL -14 DAY), DATE_ADD(CURDATE(), INTERVAL 9 DAY))), (1107, 1, IF(MONTH(CURDATE()) >= 1 AND DAY(CURDATE()) > 20, DATE_ADD(CURDATE(), INTERVAL -14 DAY), DATE_ADD(CURDATE(), INTERVAL 9 DAY))),
(1107, 2, IF(MONTH(CURDATE()) >= 1 AND DAY(CURDATE()) > 20, DATE_ADD(CURDATE(), INTERVAL -15 DAY), DATE_ADD(CURDATE(), INTERVAL 7 DAY))); (1107, 2, IF(MONTH(CURDATE()) >= 1 AND DAY(CURDATE()) > 20, DATE_ADD(CURDATE(), INTERVAL -15 DAY), DATE_ADD(CURDATE(), INTERVAL 7 DAY)));
INSERT INTO `vn`.`smsConfig` (`id`, `uri`, `title`) INSERT INTO `vn`.`smsConfig` (`id`, `uri`, `title`, `apiKey`)
VALUES VALUES
('1', 'https://websms.xtratelecom.es/api_php/server.wsdl', 'Verdnatura'); ('1', 'https://api.gateway360.com/api/3.0/sms/send', 'Verdnatura', '5715476da95b46d686a5a255e6459523');
INSERT INTO `vn`.`sharingClient`(`id`, `workerFk`, `started`, `ended`, `clientFk`) INSERT INTO `vn`.`sharingClient`(`id`, `workerFk`, `started`, `ended`, `clientFk`)
VALUES VALUES

File diff suppressed because it is too large Load Diff

View File

@ -23,371 +23,398 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.icon-100:before { .icon-isTooLittle:before {
content: "\e976";
}
.icon-account:before {
content: "\e900";
}
.icon-actions:before {
content: "\e901";
}
.icon-addperson:before {
content: "\e902";
}
.icon-agency:before {
content: "\e903";
}
.icon-albaran:before {
content: "\e904";
}
.icon-anonymous:before {
content: "\e905";
}
.icon-apps:before {
content: "\e906";
}
.icon-artificial:before {
content: "\e907";
}
.icon-attach:before {
content: "\e908";
}
.icon-barcode:before {
content: "\e909";
}
.icon-basket:before {
content: "\e90a";
}
.icon-basketadd:before {
content: "\e90b";
}
.icon-bin:before {
content: "\e90c";
}
.icon-botanical:before {
content: "\e90d";
}
.icon-bucket:before {
content: "\e90e";
}
.icon-buscaman:before {
content: "\e90f";
}
.icon-buyrequest:before {
content: "\e910";
}
.icon-calc_volum .path1:before {
content: "\e911";
color: rgb(0, 0, 0);
}
.icon-calc_volum .path2:before {
content: "\e912";
margin-left: -1em;
color: rgb(0, 0, 0);
}
.icon-calc_volum .path3:before {
content: "\e913";
margin-left: -1em;
color: rgb(0, 0, 0);
}
.icon-calc_volum .path4:before {
content: "\e914";
margin-left: -1em;
color: rgb(0, 0, 0);
}
.icon-calc_volum .path5:before {
content: "\e915";
margin-left: -1em;
color: rgb(0, 0, 0);
}
.icon-calc_volum .path6:before {
content: "\e916";
margin-left: -1em;
color: rgb(255, 255, 255);
}
.icon-calendar:before {
content: "\e917";
}
.icon-catalog:before {
content: "\e918";
}
.icon-claims:before {
content: "\e919";
}
.icon-client:before {
content: "\e91a";
}
.icon-clone:before {
content: "\e91b"; content: "\e91b";
} }
.icon-columnadd:before {
content: "\e91c";
}
.icon-columndelete:before {
content: "\e91d";
}
.icon-accessory:before {
content: "\e91e";
}
.icon-components:before {
content: "\e91f";
}
.icon-handmade:before {
content: "\e920";
}
.icon-consignatarios:before {
content: "\e921";
}
.icon-control:before {
content: "\e922";
}
.icon-credit:before {
content: "\e923";
}
.icon-deletedTicket:before {
content: "\e924";
}
.icon-deleteline:before {
content: "\e925";
}
.icon-delivery:before {
content: "\e926";
}
.icon-deliveryprices:before {
content: "\e927";
}
.icon-details:before {
content: "\e928";
}
.icon-dfiscales:before {
content: "\e929";
}
.icon-doc:before {
content: "\e92a";
}
.icon-entry:before {
content: "\e92b";
}
.icon-exit:before {
content: "\e92c";
}
.icon-eye:before {
content: "\e92d";
}
.icon-fixedPrice:before {
content: "\e92e";
}
.icon-flower:before {
content: "\e92f";
}
.icon-frozen:before { .icon-frozen:before {
content: "\e930"; content: "\e900";
}
.icon-fruit:before {
content: "\e931";
}
.icon-funeral:before {
content: "\e932";
}
.icon-greuge:before {
content: "\e933";
}
.icon-grid:before {
content: "\e934";
}
.icon-handmadeArtificial:before {
content: "\e935";
}
.icon-headercol:before {
content: "\e936";
}
.icon-history:before {
content: "\e937";
}
.icon-disabled:before {
content: "\e938";
}
.icon-info:before {
content: "\e939";
}
.icon-inventory:before {
content: "\e93a";
}
.icon-invoice:before {
content: "\e93b";
}
.icon-invoice-in:before {
content: "\e93c";
}
.icon-invoice-in-create:before {
content: "\e93d";
}
.icon-invoice-out:before {
content: "\e93e";
}
.icon-item:before {
content: "\e93f";
}
.icon-languaje:before {
content: "\e940";
}
.icon-lines:before {
content: "\e941";
}
.icon-linesprepaired:before {
content: "\e942";
}
.icon-logout:before {
content: "\e943";
}
.icon-mana:before {
content: "\e944";
}
.icon-mandatory:before {
content: "\e945";
}
.icon-net:before {
content: "\e946";
}
.icon-niche:before {
content: "\e947";
}
.icon-no036:before {
content: "\e948";
}
.icon-notes:before {
content: "\e949";
}
.icon-noweb:before {
content: "\e94a";
}
.icon-onlinepayment:before {
content: "\e94b";
}
.icon-package:before {
content: "\e94c";
}
.icon-payment:before {
content: "\e94d";
}
.icon-pbx:before {
content: "\e94e";
} }
.icon-Person:before { .icon-Person:before {
content: "\e94f"; content: "\e901";
} }
.icon-pets:before { .icon-handmadeArtificial:before {
content: "\e950"; content: "\e902";
} }
.icon-photo:before { .icon-fruit:before {
content: "\e951"; content: "\e903";
} }
.icon-plant:before { .icon-funeral:before {
content: "\e952"; content: "\e904";
}
.icon-stowaway:before {
content: "\e953";
}
.icon-preserved:before {
content: "\e954";
}
.icon-recovery:before {
content: "\e955";
}
.icon-regentry:before {
content: "\e956";
}
.icon-reserve:before {
content: "\e957";
}
.icon-revision:before {
content: "\e958";
}
.icon-risk:before {
content: "\e959";
}
.icon-services:before {
content: "\e95a";
}
.icon-settings:before {
content: "\e95b";
}
.icon-shipment-01 .path1:before {
content: "\e95c";
color: rgb(225, 225, 225);
}
.icon-shipment-01 .path2:before {
content: "\e95d";
margin-left: -1em;
color: rgb(0, 0, 0);
}
.icon-sign:before {
content: "\e95e";
}
.icon-sms:before {
content: "\e95f";
}
.icon-solclaim:before {
content: "\e960";
}
.icon-solunion:before {
content: "\e961";
}
.icon-splitline:before {
content: "\e962";
}
.icon-splur:before {
content: "\e963";
}
.icon-supplier:before {
content: "\e965";
}
.icon-supplierfalse:before {
content: "\e966";
}
.icon-tags:before {
content: "\e967";
}
.icon-tax:before {
content: "\e968";
}
.icon-thermometer:before {
content: "\e969";
}
.icon-ticket:before {
content: "\e96a";
}
.icon-traceability:before {
content: "\e96b";
}
.icon-transaction:before {
content: "\e96c";
} }
.icon-treatments:before { .icon-treatments:before {
content: "\e96d"; content: "\e905";
} }
.icon-unavailable:before { .icon-preserved:before {
content: "\e96e"; content: "\e906";
} }
.icon-greenery:before { .icon-greenery:before {
content: "\e96f"; content: "\e907";
} }
.icon-volume:before { .icon-plant:before {
content: "\e970"; content: "\e908";
} }
.icon-wand:before { .icon-handmade:before {
content: "\e971"; content: "\e909";
} }
.icon-web:before { .icon-accessory:before {
content: "\e972"; content: "\e90a";
} }
.icon-wiki:before { .icon-artificial:before {
content: "\e973"; content: "\e90b";
} }
.icon-worker:before { .icon-flower:before {
content: "\e974"; content: "\e90c";
}
.icon-fixedPrice:before {
content: "\e90d";
}
.icon-addperson:before {
content: "\e90e";
}
.icon-supplierfalse:before {
content: "\e90f";
}
.icon-invoice-out:before {
content: "\e910";
}
.icon-invoice-in:before {
content: "\e911";
}
.icon-invoice-in-create:before {
content: "\e912";
}
.icon-basketadd:before {
content: "\e913";
}
.icon-basket:before {
content: "\e914";
}
.icon-calc_volum .path1:before {
content: "\e915";
}
.icon-calc_volum .path2:before {
content: "\e916";
margin-left: -1em;
}
.icon-calc_volum .path3:before {
content: "\e917";
margin-left: -1em;
}
.icon-calc_volum .path4:before {
content: "\e918";
margin-left: -1em;
}
.icon-calc_volum .path5:before {
content: "\e919";
margin-left: -1em;
}
.icon-calc_volum .path6:before {
content: "\e91a";
margin-left: -1em;
}
.icon-deliveryprices:before {
content: "\e91c";
}
.icon-onlinepayment:before {
content: "\e91d";
}
.icon-risk:before {
content: "\e91e";
}
.icon-noweb:before {
content: "\e91f";
}
.icon-no036:before {
content: "\e920";
}
.icon-inactive:before {
content: "\e921";
}
.icon-unavailable:before {
content: "\e922";
}
.icon-invoice-01:before {
content: "\e923";
}
.icon-invoice:before {
content: "\e924";
}
.icon-supplier:before {
content: "\e925";
}
.icon-client2:before {
content: "\e926";
}
.icon-supplier2:before {
content: "\e927";
}
.icon-client:before {
content: "\e928";
}
.icon-shipment-01:before {
content: "\e929";
}
.icon-inventory:before {
content: "\e92b";
} }
.icon-zone:before { .icon-zone:before {
content: "\e92c";
}
.icon-wiki:before {
content: "\e92d";
}
.icon-attach:before {
content: "\e92e";
}
.icon-zone2:before {
content: "\e92f";
}
.icon-anonymous:before {
content: "\e930";
}
.icon-net:before {
content: "\e931";
}
.icon-buyrequest:before {
content: "\e932";
}
.icon-thermometer:before {
content: "\e933";
}
.icon-entry:before {
content: "\e934";
}
.icon-deletedTicket:before {
content: "\e935";
}
.icon-deliveryprices-01:before {
content: "\e936";
}
.icon-catalog:before {
content: "\e937";
}
.icon-agency:before {
content: "\e938";
}
.icon-delivery:before {
content: "\e939";
}
.icon-wand:before {
content: "\e93a";
}
.icon-buscaman:before {
content: "\e93b";
}
.icon-pbx:before {
content: "\e93c";
}
.icon-calendar:before {
content: "\e93d";
}
.icon-splitline:before {
content: "\e93e";
}
.icon-consignatarios:before {
content: "\e93f";
}
.icon-tax:before {
content: "\e940";
}
.icon-notes:before {
content: "\e941";
}
.icon-lines:before {
content: "\e942";
}
.icon-languaje:before {
content: "\e943";
}
.icon-greuge:before {
content: "\e944";
}
.icon-credit:before {
content: "\e945";
}
.icon-components:before {
content: "\e946";
}
.icon-pets:before {
content: "\e947";
}
.icon-linesprepaired:before {
content: "\e948";
}
.icon-control:before {
content: "\e949";
}
.icon-revision:before {
content: "\e94a";
}
.icon-newinvoices:before {
content: "\e94b";
}
.icon-services:before {
content: "\e94c";
}
.icon-newalbaran:before {
content: "\e94d";
}
.icon-solunion:before {
content: "\e94e";
}
.icon-stowaway:before {
content: "\e94f";
}
.icon-exit:before {
content: "\e950";
}
.icon-apps:before {
content: "\e951";
}
.icon-info:before {
content: "\e952";
}
.icon-columndelete:before {
content: "\e953";
}
.icon-columnadd:before {
content: "\e954";
}
.icon-deleteline:before {
content: "\e955";
}
.icon-item:before {
content: "\e956";
}
.icon-worker:before {
content: "\e957";
}
.icon-headercol:before {
content: "\e958";
}
.icon-reserva:before {
content: "\e959";
}
.icon-100:before {
content: "\e95a";
}
.icon-noweb1:before {
content: "\e95b";
}
.icon-settings1:before {
content: "\e95c";
}
.icon-sign:before {
content: "\e95d";
}
.icon-polizon:before {
content: "\e95e";
}
.icon-solclaim:before {
content: "\e95f";
}
.icon-actions:before {
content: "\e960";
}
.icon-details:before {
content: "\e961";
}
.icon-traceability:before {
content: "\e962";
}
.icon-claims:before {
content: "\e963";
}
.icon-regentry:before {
content: "\e964";
}
.icon-regentry-1:before {
content: "\e965";
}
.icon-transaction:before {
content: "\e966";
}
.icon-history:before {
content: "\e968";
}
.icon-entry:before {
content: "\e969";
}
.icon-mana:before {
content: "\e96a";
}
.icon-ticket:before {
content: "\e96b";
}
.icon-niche:before {
content: "\e96c";
}
.icon-tags:before {
content: "\e96d";
}
.icon-volume:before {
content: "\e96e";
}
.icon-bin:before {
content: "\e96f";
}
.icon-splur:before {
content: "\e970";
}
.icon-barcode:before {
content: "\e971";
}
.icon-botanical:before {
content: "\e972";
}
.icon-clone:before {
content: "\e973";
}
.icon-photo:before {
content: "\e974";
}
.icon-sms:before {
content: "\e975"; content: "\e975";
} }
.icon-eye:before {
content: "\e976";
}
.icon-doc:before {
content: "\e977";
}
.icon-package:before {
content: "\e978";
}
.icon-settings:before {
content: "\e979";
}
.icon-bucket:before {
content: "\e97a";
}
.icon-mandatory:before {
content: "\e97b";
}
.icon-recovery:before {
content: "\e97c";
}
.icon-payment:before {
content: "\e97e";
}
.icon-invoices:before {
content: "\e97f";
}
.icon-grid:before {
content: "\e980";
}
.icon-logout:before {
content: "\e981";
}
.icon-web:before {
content: "\e982";
}
.icon-albaran:before {
content: "\e983";
}
.icon-dfiscales:before {
content: "\e984";
}

Binary file not shown.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 145 KiB

After

Width:  |  Height:  |  Size: 162 KiB

View File

@ -51,7 +51,7 @@ h1, h2, h3, h4, h5, h6 {
color: $color-main; color: $color-main;
} }
.text-secondary { .text-secondary {
color: $color-font-secondary; color: $color-font-light;
} }
/* Helpers */ /* Helpers */

View File

@ -96,13 +96,13 @@
"This postcode already exists": "Este código postal ya existe", "This postcode already exists": "Este código postal ya existe",
"Concept cannot be blank": "El concepto no puede quedar en blanco", "Concept cannot be blank": "El concepto no puede quedar en blanco",
"File doesn't exists": "El archivo no existe", "File doesn't exists": "El archivo no existe",
"You don't have privileges to change the zone": "No tienes permisos para cambiar la zona", "You don't have privileges to change the zone or for these parameters there are more than one shipping options, talk to agencies": "No tienes permisos para cambiar la zona o para esos parámetros hay más de una opción de envío, hable con las agencias",
"This ticket is already on weekly tickets": "Este ticket ya está en tickets programados", "This ticket is already on weekly tickets": "Este ticket ya está en tickets programados",
"Ticket id cannot be blank": "El id de ticket no puede quedar en blanco", "Ticket id cannot be blank": "El id de ticket no puede quedar en blanco",
"Weekday cannot be blank": "El día de la semana no puede quedar en blanco", "Weekday cannot be blank": "El día de la semana no puede quedar en blanco",
"You can't delete a confirmed order": "No puedes borrar un pedido confirmado", "You can't delete a confirmed order": "No puedes borrar un pedido confirmado",
"Can't create stowaway for this ticket": "No se puede crear un polizon para este ticket", "Can't create stowaway for this ticket": "No se puede crear un polizon para este ticket",
"The socialName has an invalid format": "El nombre fiscal tiene un formato incorrecto", "The social name has an invalid format": "El nombre fiscal tiene un formato incorrecto",
"Invalid quantity": "Cantidad invalida", "Invalid quantity": "Cantidad invalida",
"This postal code is not valid": "This postal code is not valid", "This postal code is not valid": "This postal code is not valid",
"is invalid": "is invalid", "is invalid": "is invalid",
@ -215,5 +215,6 @@
"You can't create a claim from a ticket delivered more than seven days ago": "No puedes crear una reclamación de un ticket entregado hace más de siete días", "You can't create a claim from a ticket delivered more than seven days ago": "No puedes crear una reclamación de un ticket entregado hace más de siete días",
"The worker has hours recorded that day": "El trabajador tiene horas fichadas ese día", "The worker has hours recorded that day": "El trabajador tiene horas fichadas ese día",
"The worker has a marked absence that day": "El trabajador tiene marcada una ausencia ese día", "The worker has a marked absence that day": "El trabajador tiene marcada una ausencia ese día",
"You can not modify is pay method checked": "No se puede modificar el campo método de pago validado" "You can not modify is pay method checked": "No se puede modificar el campo método de pago validado",
} "Can't transfer claimed sales": "No puedes transferir lineas reclamadas"
}

View File

@ -1,5 +1,4 @@
const soap = require('soap'); const got = require('got');
const xmlParser = require('xml2js').parseString;
const UserError = require('vn-loopback/util/user-error'); const UserError = require('vn-loopback/util/user-error');
module.exports = Self => { module.exports = Self => {
@ -35,57 +34,49 @@ module.exports = Self => {
Self.send = async(ctx, destinationFk, destination, message) => { Self.send = async(ctx, destinationFk, destination, message) => {
const userId = ctx.req.accessToken.userId; const userId = ctx.req.accessToken.userId;
const smsConfig = await Self.app.models.SmsConfig.findOne(); const smsConfig = await Self.app.models.SmsConfig.findOne();
const soapClient = await soap.createClientAsync(smsConfig.uri);
if (destination.length == 9) {
const spainPrefix = '0034';
destination = spainPrefix + destination;
}
const params = { const params = {
user: smsConfig.user, api_key: smsConfig.apiKey,
pass: smsConfig.password, messages: [{
src: smsConfig.title, from: smsConfig.title,
dst: destination, to: destination,
msg: message text: message
}]
}; };
let xmlResponse; let response;
let xmlResult;
let xmlParsed;
let status;
try { try {
if (process.env.NODE_ENV !== 'production') { if (process.env.NODE_ENV !== 'production')
status = { response = {result: [{status: 'ok'}]};
codigo: [200], else {
descripcion: ['Fake response'] const jsonTest = {
json: params
}; };
} else { response = await got.post(smsConfig.uri, jsonTest).json();
[xmlResponse] = await soapClient.sendSMSAsync(params);
xmlResult = xmlResponse.result.$value;
xmlParsed = await new Promise((resolve, reject) => {
xmlParser(xmlResult, (err, result) => {
if (err)
reject(err);
resolve(result);
});
});
[status] = xmlParsed['xtratelecom-sms-response'].sms;
} }
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
const statusCode = status.codigo[0]; const [result] = response.result;
const statusDescription = status.descripcion[0]; const error = result.error_id;
const newSms = { const newSms = {
senderFk: userId, senderFk: userId,
destinationFk: destinationFk || null, destinationFk: destinationFk || null,
destination: destination, destination: destination,
message: message, message: message,
statusCode: statusCode, status: error
status: statusDescription
}; };
const sms = await Self.create(newSms); const sms = await Self.create(newSms);
if (statusCode != 200) if (error)
throw new UserError(`We weren't able to send this SMS`); throw new UserError(`We weren't able to send this SMS`);
return sms; return sms;

View File

@ -1,14 +1,10 @@
const app = require('vn-loopback/server/server'); const app = require('vn-loopback/server/server');
const soap = require('soap');
describe('sms send()', () => { describe('sms send()', () => {
it('should return the expected message and status code', async() => { it('should not return status error', async() => {
const code = 200; const ctx = {req: {accessToken: {userId: 1}}};
spyOn(soap, 'createClientAsync').and.returnValue('a so fake client'); const result = await app.models.Sms.send(ctx, 1105, '123456789', 'My SMS Body');
let ctx = {req: {accessToken: {userId: 1}}};
let result = await app.models.Sms.send(ctx, 1105, 'destination', 'My SMS Body');
expect(result.statusCode).toEqual(code); expect(result.status).toBeUndefined();
expect(result.status).toContain('Fake response');
}); });
}); });

View File

@ -55,15 +55,6 @@ module.exports = Self => {
with: /^[\w|.|-]+@[\w|-]+(\.[\w|-]+)*(,[\w|.|-]+@[\w|-]+(\.[\w|-]+)*)*$/ with: /^[\w|.|-]+@[\w|-]+(\.[\w|-]+)*(,[\w|.|-]+@[\w|-]+(\.[\w|-]+)*)*$/
}); });
Self.validate('businessTypeFk', hasBusinessType, {
message: `The type of business must be filled in basic data`
});
function hasBusinessType(err) {
if (!this.businessTypeFk)
err();
}
Self.validatesLengthOf('postcode', { Self.validatesLengthOf('postcode', {
allowNull: true, allowNull: true,
allowBlank: true, allowBlank: true,
@ -189,6 +180,32 @@ module.exports = Self => {
return regexp.test(value); return regexp.test(value);
} }
Self.observe('before save', async ctx => {
const changes = ctx.data || ctx.instance;
const orgData = ctx.currentInstance;
const businessTypeFk = changes && changes.businessTypeFk || orgData && orgData.businessTypeFk;
const isTaxDataChecked = changes && changes.isTaxDataChecked || orgData && orgData.isTaxDataChecked;
let invalidBusinessType = false;
if (!ctx.isNewInstance) {
const isWorker = await Self.app.models.UserAccount.findById(orgData.id);
const changedFields = Object.keys(changes);
const hasChangedOtherFields = changedFields.some(key => key !== 'businessTypeFk');
if (!businessTypeFk && !isTaxDataChecked && !isWorker && !hasChangedOtherFields)
invalidBusinessType = true;
}
if (ctx.isNewInstance) {
if (!businessTypeFk && !isTaxDataChecked)
invalidBusinessType = true;
}
if (invalidBusinessType)
throw new UserError(`The type of business must be filled in basic data`);
});
Self.observe('before save', async function(ctx) { Self.observe('before save', async function(ctx) {
const changes = ctx.data || ctx.instance; const changes = ctx.data || ctx.instance;
const orgData = ctx.currentInstance; const orgData = ctx.currentInstance;
@ -206,7 +223,7 @@ module.exports = Self => {
&& orgData.isTaxDataChecked != isTaxDataChecked; && orgData.isTaxDataChecked != isTaxDataChecked;
if ((socialNameChanged || dataCheckedChanged) && !isAlpha(socialName)) if ((socialNameChanged || dataCheckedChanged) && !isAlpha(socialName))
throw new UserError('The socialName has an invalid format'); throw new UserError(`The social name has an invalid format`);
if (changes.salesPerson === null) { if (changes.salesPerson === null) {
changes.credit = 0; changes.credit = 0;
@ -267,7 +284,7 @@ module.exports = Self => {
replyTo: worker.email replyTo: worker.email
}; };
await got.get(`${origin}/api/email/payment-update`, { await got.get(`${origin}/api/email/payment-update`, {
query: params searchParams: params
}); });
} }
@ -374,14 +391,11 @@ module.exports = Self => {
throw new UserError(`You don't have enough privileges to set this credit amount`); throw new UserError(`You don't have enough privileges to set this credit amount`);
} }
const client = await models.Client.findById(finalState.id, null, ctx.options);
if (client.businessTypeFk) {
await models.ClientCredit.create({ await models.ClientCredit.create({
amount: changes.credit, amount: changes.credit,
clientFk: finalState.id, clientFk: finalState.id,
workerFk: userId workerFk: userId
}, ctx.options); }, ctx.options);
}
}; };
const app = require('vn-loopback/server/server'); const app = require('vn-loopback/server/server');

View File

@ -16,10 +16,7 @@
"uri": { "uri": {
"type": "String" "type": "String"
}, },
"user": { "apiKey": {
"type": "String"
},
"password": {
"type": "String" "type": "String"
}, },
"title": { "title": {

View File

@ -26,8 +26,7 @@
"required": true "required": true
}, },
"statusCode": { "statusCode": {
"type": "Number", "type": "Number"
"required": true
}, },
"status": { "status": {
"type": "String" "type": "String"

View File

@ -179,7 +179,7 @@
ng-click="$ctrl.selectItem(item.id)"> ng-click="$ctrl.selectItem(item.id)">
<vn-td shrink> <vn-td shrink>
<span <span
ng-click="itemDescriptor.show($event, item.id)" vn-click-stop="itemDescriptor.show($event, item.id)"
class="link"> class="link">
{{::item.id}} {{::item.id}}
</span> </span>

View File

@ -58,7 +58,7 @@ module.exports = Self => {
}, myOptions); }, myOptions);
const response = got.stream(`${origin}/api/report/invoice`, { const response = got.stream(`${origin}/api/report/invoice`, {
query: { searchParams: {
authorization: auth.id, authorization: auth.id,
invoiceId: id invoiceId: id
} }

View File

@ -296,7 +296,7 @@
ng-click="$ctrl.selectItem(item.id)"> ng-click="$ctrl.selectItem(item.id)">
<vn-td shrink> <vn-td shrink>
<span <span
ng-click="itemDescriptor.show($event, item.id)" vn-click-stop="itemDescriptor.show($event, item.id)"
class="link"> class="link">
{{::item.id}} {{::item.id}}
</span> </span>

View File

@ -5,6 +5,7 @@ Search tickets: Buscar tickets
Delete selected elements: Eliminar los elementos seleccionados Delete selected elements: Eliminar los elementos seleccionados
All the selected elements will be deleted. Are you sure you want to continue?: Todos los elementos seleccionados serán eliminados. ¿Seguro que quieres continuar? All the selected elements will be deleted. Are you sure you want to continue?: Todos los elementos seleccionados serán eliminados. ¿Seguro que quieres continuar?
Component lack: Faltan componentes Component lack: Faltan componentes
Ticket too little: Ticket demasiado pequeño
Minimize/Maximize: Minimizar/Maximizar Minimize/Maximize: Minimizar/Maximizar
Problems: Problemas Problems: Problemas
Theoretical: Teórica Theoretical: Teórica

View File

@ -122,6 +122,12 @@
class="bright" class="bright"
icon="icon-components"> icon="icon-components">
</vn-icon> </vn-icon>
<vn-icon
ng-show="::ticket.isTooLittle"
translate-attr="{title: 'Ticket too little'}"
class="bright"
icon="icon-isTooLittle">
</vn-icon>
</td> </td>
<td> <td>
<span <span

View File

@ -10,7 +10,12 @@
], ],
"card": [] "card": []
}, },
"keybindings": [], "keybindings": [
{
"key": "m",
"state": "monitor.index"
}
],
"routes": [ "routes": [
{ {
"url": "/monitor", "url": "/monitor",

View File

@ -15,6 +15,12 @@
{"state": "order.card.line", "icon": "icon-lines"} {"state": "order.card.line", "icon": "icon-lines"}
] ]
}, },
"keybindings": [
{
"key": "o",
"state": "order.index"
}
],
"routes": [ "routes": [
{ {
"url": "/order", "url": "/order",

View File

@ -38,7 +38,6 @@ module.exports = Self => {
'payDemFk', 'payDemFk',
'payDay', 'payDay',
'account', 'account',
'isFarmer',
'sageTaxTypeFk', 'sageTaxTypeFk',
'sageTransactionTypeFk', 'sageTransactionTypeFk',
'sageWithholdingFk', 'sageWithholdingFk',
@ -102,6 +101,11 @@ module.exports = Self => {
] ]
}; };
let supplier = await Self.app.models.Supplier.findOne(filter); let supplier = await Self.app.models.Supplier.findOne(filter);
const farmerCode = 2;
if (supplier.sageWithholdingFk == farmerCode)
supplier.isFarmer = true;
return supplier; return supplier;
}; };
}; };

View File

@ -25,4 +25,12 @@ describe('Supplier getSummary()', () => {
expect(payMethod.name).toEqual('PayMethod one'); expect(payMethod.name).toEqual('PayMethod one');
}); });
it(`should get if supplier is farmer by sageWithholdingFk`, async() => {
const supplier = await app.models.Supplier.findById(2);
const supplierSummary = await app.models.Supplier.getSummary(2);
expect(supplier.isFarmer).toBeUndefined();
expect(supplierSummary.isFarmer).toEqual(true);
});
}); });

View File

@ -114,6 +114,6 @@ module.exports = Self => {
&& orgData.socialName != socialName; && orgData.socialName != socialName;
if ((socialNameChanged) && !isAlpha(socialName)) if ((socialNameChanged) && !isAlpha(socialName))
throw new UserError('The socialName has an invalid format'); throw new UserError('The social name has an invalid format');
}); });
}; };

View File

@ -27,9 +27,6 @@
"nif": { "nif": {
"type": "string" "type": "string"
}, },
"isFarmer": {
"type": "boolean"
},
"phone": { "phone": {
"type": "number" "type": "number"
}, },

View File

@ -112,10 +112,19 @@ module.exports = Self => {
const isProductionBoss = await models.Account.hasRole(userId, 'productionBoss', myOptions); const isProductionBoss = await models.Account.hasRole(userId, 'productionBoss', myOptions);
if (!isProductionBoss) { if (!isProductionBoss) {
const zoneShipped = await models.Agency.getShipped(args.landed, args.addressFk, args.agencyModeFk, args.warehouseFk, myOptions); const zoneShipped = await models.Agency.getShipped(
args.landed,
args.addressFk,
args.agencyModeFk,
args.warehouseFk,
myOptions);
if (!zoneShipped || zoneShipped.zoneFk != args.zoneFk) if (!zoneShipped || zoneShipped.zoneFk != args.zoneFk) {
throw new UserError(`You don't have privileges to change the zone`); const error = `You don't have privileges to change the zone or
for these parameters there are more than one shipping options, talk to agencies`;
throw new UserError(error);
}
} }
const originalTicket = await models.Ticket.findOne({ const originalTicket = await models.Ticket.findOne({

View File

@ -9,10 +9,14 @@ module.exports = Self => {
description: 'ticket id', description: 'ticket id',
http: {source: 'path'} http: {source: 'path'}
}], }],
returns: { returns: [{
type: ['Object'], arg: 'saleVolume',
root: true type: ['object']
}, },
{
arg: 'packingTypeVolume',
type: ['object']
}],
http: { http: {
path: `/:id/getVolume`, path: `/:id/getVolume`,
verb: 'GET' verb: 'GET'
@ -25,7 +29,21 @@ module.exports = Self => {
if (typeof options == 'object') if (typeof options == 'object')
Object.assign(myOptions, options); Object.assign(myOptions, options);
return Self.rawSql(`SELECT * FROM vn.saleVolume const saleVolume = await Self.rawSql(`
SELECT saleFk, volume
FROM vn.saleVolume
WHERE ticketFk = ?`, [ticketFk], myOptions); WHERE ticketFk = ?`, [ticketFk], myOptions);
const packingTypeVolume = await Self.rawSql(`
SELECT s.itemPackingTypeFk code,
i.description,
SUM(s.volume) volume
FROM vn.saleVolume s
LEFT JOIN vn.itemPackingType i
ON i.code = s.itemPackingTypeFk
WHERE s.ticketFk = ?
GROUP BY s.itemPackingTypeFk`, [ticketFk], myOptions);
return [saleVolume, packingTypeVolume];
}; };
}; };

View File

@ -81,8 +81,12 @@ module.exports = Self => {
args.warehouseId, args.warehouseId,
myOptions); myOptions);
if (!zoneShipped || zoneShipped.zoneFk != args.zoneId) if (!zoneShipped || zoneShipped.zoneFk != args.zoneId) {
throw new UserError(`You don't have privileges to change the zone`); const error = `You don't have privileges to change the zone or
for these parameters there are more than one shipping options, talk to agencies`;
throw new UserError(error);
}
} }
const items = await models.Sale.find({ const items = await models.Sale.find({

View File

@ -8,9 +8,15 @@ describe('ticket getVolume()', () => {
const options = {transaction: tx}; const options = {transaction: tx};
const ticketId = 1; const ticketId = 1;
const result = await models.Ticket.getVolume(ticketId, options); const expectedSaleVolume = 1.09;
const expectedPackingTypeVolume = 0.028;
expect(result[0].volume).toEqual(1.09); const result = await models.Ticket.getVolume(ticketId, options);
const [saleVolume] = result[0];
const [packingTypeVolume] = result[1];
expect(saleVolume.volume).toEqual(expectedSaleVolume);
expect(packingTypeVolume.volume).toEqual(expectedPackingTypeVolume);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {

View File

@ -58,13 +58,63 @@ describe('sale transferSales()', () => {
expect(error.message).toEqual(`The sales of the receiver ticket can't be modified`); expect(error.message).toEqual(`The sales of the receiver ticket can't be modified`);
}); });
it('should transfer the sales from one ticket to a new one then send them back and delete the created ticket', async() => { it('should throw an error if any of the sales has a claim', async() => {
const tx = await models.Ticket.beginTransaction({});
let error;
try {
const options = {transaction: tx};
const ticketId = 11;
const receiverTicketId = null;
const sales = await models.Ticket.getSales(ticketId, options);
await models.Ticket.transferSales(ctx, ticketId, receiverTicketId, sales, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
expect(error.message).toEqual(`Can't transfer claimed sales`);
});
it('should be able to transfer claimed sales if the role is claimManager', async() => {
const tx = await models.Ticket.beginTransaction({});
let error;
try {
const options = {transaction: tx};
const claimManagerId = 72;
const myActiveCtx = {
accessToken: {userId: claimManagerId},
};
const myCtx = {req: myActiveCtx};
const ticketId = 11;
const receiverTicketId = null;
const sales = await models.Ticket.getSales(ticketId, options);
await models.Ticket.transferSales(myCtx, ticketId, receiverTicketId, sales, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
expect(error).toBeUndefined();
});
it('should transfer the sales from a ticket to a new one', async() => {
const tx = await models.Ticket.beginTransaction({}); const tx = await models.Ticket.beginTransaction({});
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
const formerTicketId = 11; const formerTicketId = 22;
let createdTicketId = undefined; let createdTicketId = undefined;
let formerTicketSales = await models.Ticket.getSales(formerTicketId, options); let formerTicketSales = await models.Ticket.getSales(formerTicketId, options);
@ -77,23 +127,11 @@ describe('sale transferSales()', () => {
createdTicketId = createdTicket.id; createdTicketId = createdTicket.id;
formerTicketSales = await models.Ticket.getSales(formerTicketId, options); formerTicketSales = await models.Ticket.getSales(formerTicketId, options);
createdTicketSales = await models.Ticket.getSales(createdTicketId, options); let createdTicketSales = await models.Ticket.getSales(createdTicketId, options);
expect(formerTicketSales.length).toEqual(0); expect(formerTicketSales.length).toEqual(0);
expect(createdTicketSales.length).toEqual(2); expect(createdTicketSales.length).toEqual(2);
await models.Ticket.transferSales(
ctx, createdTicketId, formerTicketId, createdTicketSales, options);
formerTicketSales = await models.Ticket.getSales(formerTicketId, options);
createdTicketSales = await models.Ticket.getSales(createdTicketId, options);
createdTicket = await models.Ticket.findById(createdTicketId, null, options);
expect(createdTicket.isDeleted).toBeTruthy();
expect(formerTicketSales.length).toEqual(2);
expect(createdTicketSales.length).toEqual(0);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
await tx.rollback(); await tx.rollback();
@ -109,10 +147,9 @@ describe('sale transferSales()', () => {
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
const currentTicket = await models.Ticket.findById(11, null, options); const currentTicketId = 22;
const currentTicketSales = await models.Ticket.getSales(currentTicket.id, options); const currentTicketSales = await models.Ticket.getSales(currentTicketId, options);
const currentTicketId = currentTicket.id;
const receiverTicketId = undefined; const receiverTicketId = undefined;
currentTicketSales[0].quantity = 99; currentTicketSales[0].quantity = 99;
@ -135,7 +172,7 @@ describe('sale transferSales()', () => {
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
const formerTicketId = 11; const formerTicketId = 22;
let createdTicketId = undefined; let createdTicketId = undefined;
let formerTicketSales = await models.Ticket.getSales(formerTicketId, options); let formerTicketSales = await models.Ticket.getSales(formerTicketId, options);
@ -143,7 +180,7 @@ describe('sale transferSales()', () => {
const completeSaleId = formerTicketSales[1].id; const completeSaleId = formerTicketSales[1].id;
let partialSaleTotalQuantity = formerTicketSales[0].quantity; let partialSaleTotalQuantity = formerTicketSales[0].quantity;
expect(partialSaleTotalQuantity).toEqual(15); expect(partialSaleTotalQuantity).toEqual(30);
formerTicketSales[0].quantity = 1; formerTicketSales[0].quantity = 1;

View File

@ -75,6 +75,13 @@ module.exports = Self => {
for (const sale of originalSales) for (const sale of originalSales)
map.set(sale.id, sale); map.set(sale.id, sale);
const saleIds = sales.map(sale => sale.id);
const isClaimManager = await models.Account.hasRole(userId, 'claimManager');
const hasClaimedSales = await models.ClaimBeginning.findOne({where: {saleFk: {inq: saleIds}}});
if (hasClaimedSales && !isClaimManager)
throw new UserError(`Can't transfer claimed sales`);
for (const sale of sales) { for (const sale of sales) {
const originalSale = map.get(sale.id); const originalSale = map.get(sale.id);
const originalSaleData = { // <-- Loopback modifies original instance on save const originalSaleData = { // <-- Loopback modifies original instance on save

View File

@ -37,6 +37,7 @@ Observation type: Tipo de observación
Original: Original Original: Original
Package size: Bultos Package size: Bultos
Package type: Tipo de porte Package type: Tipo de porte
Packing type: Encajado
Phone: Teléfono Phone: Teléfono
PPU: Ud. PPU: Ud.
Price: Precio Price: Precio

View File

@ -6,20 +6,15 @@
data="$ctrl.sales" data="$ctrl.sales"
limit="20"> limit="20">
</vn-crud-model> </vn-crud-model>
<vn-crud-model auto-load="true"
url="tickets/{{$ctrl.$params.id}}/getVolume"
data="$ctrl.volumes">
</vn-crud-model>
<mg-ajax path="tickets/{{$ctrl.$params.id}}/getTotalVolume" options="mgEdit"></mg-ajax>
<vn-vertical> <vn-vertical>
<vn-card class="vn-pa-lg"> <vn-card class="vn-pa-lg">
<vn-horizontal> <vn-horizontal>
<div class="totalBox"> <div class="totalBox" ng-repeat="packingType in $ctrl.packingTypeVolume">
<vn-label-value label="Total" <vn-label-value label="Tipo"
value="{{::edit.model.totalVolume}}"> value="{{::packingType.description}}">
</vn-label-value> </vn-label-value>
<vn-label-value label="Cajas" <vn-label-value label="Volumen"
value="{{::edit.model.totalBoxes}}"> value="{{::packingType.volume}}">
</vn-label-value> </vn-label-value>
</div> </div>
</vn-horizontal> </vn-horizontal>
@ -29,6 +24,7 @@
<vn-tr> <vn-tr>
<vn-th field="itemFk" number>Item</vn-th> <vn-th field="itemFk" number>Item</vn-th>
<vn-th field="concept" default-order="ASC">Description</vn-th> <vn-th field="concept" default-order="ASC">Description</vn-th>
<vn-th field="itemPackingTypeFk" number>Packing type</vn-th>
<vn-th field="quantity" number>Quantity</vn-th> <vn-th field="quantity" number>Quantity</vn-th>
<vn-th number>m³ per quantity</vn-th> <vn-th number>m³ per quantity</vn-th>
</vn-tr> </vn-tr>
@ -55,6 +51,7 @@
tabindex="-1"> tabindex="-1">
</vn-fetched-tags> </vn-fetched-tags>
</vn-td> </vn-td>
<vn-td number>{{::sale.item.itemPackingTypeFk}}</vn-td>
<vn-td number>{{::sale.quantity}}</vn-td> <vn-td number>{{::sale.quantity}}</vn-td>
<vn-td number>{{::sale.saleVolume.volume | number:3}}</vn-td> <vn-td number>{{::sale.saleVolume.volume | number:3}}</vn-td>
</vn-tr> </vn-tr>

View File

@ -23,24 +23,19 @@ class Controller extends Section {
if (value) this.applyVolumes(); if (value) this.applyVolumes();
} }
get volumes() {
return this._volumes;
}
set volumes(value) {
this._volumes = value;
if (value) this.applyVolumes();
}
applyVolumes() { applyVolumes() {
if (!this.sales || !this.volumes) return; const ticket = this.sales[0].ticketFk;
this.$http.get(`Tickets/${ticket}/getVolume`).then(res => {
const saleVolume = res.data.saleVolume;
this.sales.forEach(sale => { const volumes = new Map();
this.volumes.forEach(volume => { for (const volume of saleVolume)
if (sale.id === volume.saleFk) volumes.set(volume.saleFk, volume);
sale.saleVolume = volume;
}); for (const sale of this.sales)
sale.saleVolume = volumes.get(sale.id);
this.packingTypeVolume = res.data.packingTypeVolume;
}); });
} }
} }

View File

@ -33,17 +33,20 @@ describe('ticket', () => {
}); });
}); });
describe('volumes() setter', () => {
it('should set volumes property on controller an then call applyVolumes() method', () => {
jest.spyOn(controller, 'applyVolumes');
controller.volumes = [{id: 1}];
expect(controller.applyVolumes).toHaveBeenCalledWith();
});
});
describe('applyVolumes()', () => { describe('applyVolumes()', () => {
const ticket = 1;
const response =
{
saleVolume: [
{saleFk: 1, volume: 0.012},
{saleFk: 2, volume: 0.015}
],
packingTypeVolume: [
{code: 'V', volume: 1},
{code: 'H', volume: 2}
]
};
it(`should not apply volumes to the sales if sales property is not defined on controller`, () => { it(`should not apply volumes to the sales if sales property is not defined on controller`, () => {
controller.sales = [{id: 1, name: 'Sale one'}, {id: 2, name: 'Sale two'}]; controller.sales = [{id: 1, name: 'Sale one'}, {id: 2, name: 'Sale two'}];
@ -58,29 +61,32 @@ describe('ticket', () => {
}); });
it(`should apply volumes to the sales if sales and volumes properties are defined on controller`, () => { it(`should apply volumes to the sales if sales and volumes properties are defined on controller`, () => {
controller.sales = [{id: 1, name: 'Sale one'}, {id: 2, name: 'Sale two'}]; const expectedResultOne = response.saleVolume[0].volume;
controller.volumes = [{saleFk: 1, volume: 0.012}, {saleFk: 2, volume: 0.015}]; const expectedResultTwo = response.saleVolume[1].volume;
$httpBackend.expectGET(`Tickets/${ticket}/getVolume`).respond(response);
expect(controller.sales[0].saleVolume.volume).toEqual(0.012); controller.sales = [
expect(controller.sales[1].saleVolume.volume).toEqual(0.015); {id: 1, name: 'Sale one', ticketFk: ticket},
}); {id: 2, name: 'Sale two'}
}); ];
/*
it('should join the sale volumes to its respective sale', () => {
controller.ticket = {id: 1};
let response = {volumes: [
{saleFk: 1, m3: 0.008},
{saleFk: 2, m3: 0.003}
]};
$httpBackend.expectGET(`tickets/1/getVolume`).respond(response);
controller.onDataChange();
$httpBackend.flush(); $httpBackend.flush();
expect($scope.model.data[0].volume.m3).toBe(0.008); expect(controller.sales[0].saleVolume.volume).toEqual(expectedResultOne);
expect($scope.model.data[1].volume.m3).toBe(0.003); expect(controller.sales[1].saleVolume.volume).toEqual(expectedResultTwo);
});
it(`should apply packing volumes to the sales if sales and volumes properties are defined on controller`, () => {
const expectedResultOne = response.packingTypeVolume[0].code;
const expectedResultTwo = response.packingTypeVolume[1].code;
$httpBackend.expectGET(`Tickets/${ticket}/getVolume`).respond(response);
controller.sales = [
{id: 1, name: 'Sale one', ticketFk: ticket},
{id: 2, name: 'Sale two'}
];
$httpBackend.flush();
expect(controller.packingTypeVolume[0].code).toEqual(expectedResultOne);
expect(controller.packingTypeVolume[1].code).toEqual(expectedResultTwo);
});
}); });
*/
}); });
}); });

View File

@ -112,6 +112,13 @@ module.exports = Self => {
const contracts = await models.WorkerLabour.find(filter, myOptions); const contracts = await models.WorkerLabour.find(filter, myOptions);
let [firstContract] = contracts;
let payedHolidays;
if (firstContract.payedHolidays)
payedHolidays = firstContract.payedHolidays;
else payedHolidays = 0;
let totalHolidays = 0; let totalHolidays = 0;
let holidaysEnjoyed = 0; let holidaysEnjoyed = 0;
@ -166,8 +173,7 @@ module.exports = Self => {
return isLeapYear(year) ? 366 : 365; return isLeapYear(year) ? 366 : 365;
} }
return {totalHolidays, holidaysEnjoyed, payedHolidays};
return {totalHolidays, holidaysEnjoyed};
}; };
function isLeapYear(year) { function isLeapYear(year) {

View File

@ -9,16 +9,19 @@
"properties": { "properties": {
"businessFk": { "businessFk": {
"id": true, "id": true,
"type": "Number" "type": "number"
}, },
"workerFk": { "workerFk": {
"type": "Number" "type": "number"
}, },
"started": { "started": {
"type": "date" "type": "date"
}, },
"ended": { "ended": {
"type": "date" "type": "date"
},
"payedHolidays": {
"type": "number"
} }
}, },
"relations": { "relations": {

View File

@ -28,6 +28,9 @@
{{'Used' | translate}} {{$ctrl.contractHolidays.holidaysEnjoyed}} {{'Used' | translate}} {{$ctrl.contractHolidays.holidaysEnjoyed}}
{{'of' | translate}} {{$ctrl.contractHolidays.totalHolidays || 0}} {{'days' | translate}} {{'of' | translate}} {{$ctrl.contractHolidays.totalHolidays || 0}} {{'days' | translate}}
</div> </div>
<div>
{{'Paid holidays' | translate}} {{$ctrl.contractHolidays.payedHolidays}} {{'days' | translate}}
</div>
</div> </div>
<div class="totalBox" style="text-align: center;"> <div class="totalBox" style="text-align: center;">

View File

@ -71,6 +71,10 @@ class Controller extends Section {
} }
} }
get payedHolidays() {
return this._businessId;
}
buildYearFilter() { buildYearFilter() {
const now = new Date(); const now = new Date();
now.setFullYear(now.getFullYear() + 1); now.setFullYear(now.getFullYear() + 1);

View File

@ -9,3 +9,4 @@ Choose an absence type from the right menu: Elige un tipo de ausencia desde el m
To start adding absences, click an absence type from the right menu and then on the day you want to add an absence: Para empezar a añadir ausencias, haz clic en un tipo de ausencia desde el menu de la derecha y después en el día que quieres añadir la ausencia To start adding absences, click an absence type from the right menu and then on the day you want to add an absence: Para empezar a añadir ausencias, haz clic en un tipo de ausencia desde el menu de la derecha y después en el día que quieres añadir la ausencia
You can just add absences within the current year: Solo puedes añadir ausencias dentro del año actual You can just add absences within the current year: Solo puedes añadir ausencias dentro del año actual
Current day: Día actual Current day: Día actual
Paid holidays: Vacaciones pagadas

View File

@ -24,6 +24,12 @@
{"state": "worker.card.workerLog", "icon": "history"} {"state": "worker.card.workerLog", "icon": "history"}
] ]
}, },
"keybindings": [
{
"key": "w",
"state": "worker.index"
}
],
"routes": [ "routes": [
{ {
"url": "/worker", "url": "/worker",

22472
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -9,13 +9,13 @@
"url": "https://gitea.verdnatura.es/verdnatura/salix" "url": "https://gitea.verdnatura.es/verdnatura/salix"
}, },
"engines": { "engines": {
"node": ">=12" "node": ">=14"
}, },
"dependencies": { "dependencies": {
"bmp-js": "^0.1.0", "bmp-js": "^0.1.0",
"compression": "^1.7.3", "compression": "^1.7.3",
"fs-extra": "^5.0.0", "fs-extra": "^5.0.0",
"got": "^6.7.1", "got": "^10.7.0",
"helmet": "^3.21.2", "helmet": "^3.21.2",
"i18n": "^0.8.4", "i18n": "^0.8.4",
"image-type": "^4.1.0", "image-type": "^4.1.0",