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

This commit is contained in:
Vicent Llopis 2022-03-23 12:37:34 +01:00
commit 1056060957
77 changed files with 20535 additions and 18926 deletions

View File

@ -1,3 +0,0 @@
UPDATE vn.absenceType
SET code='halfPaidLeave'
WHERE id=15 AND name='Permiso retribuido 1/2 día' AND rgb='#5151c0' AND code IS NULL AND permissionRate=NULL AND holidayEntitlementRate=0.50 AND discountRate=0.00;

View File

@ -1,27 +0,0 @@
INSERT INTO `salix`.`ACL`
(model, property, accessType, permission, principalType, principalId)
VALUES
('EntryObservation', '*', '*', 'ALLOW', 'ROLE', 'buyer'),
('LdapConfig', '*', '*', 'ALLOW', 'ROLE', 'sysadmin'),
('SambaConfig', '*', '*', 'ALLOW', 'ROLE', 'sysadmin'),
('ACL', '*', '*', 'ALLOW', 'ROLE', 'developer'),
('AccessToken', '*', '*', 'ALLOW', 'ROLE', 'developer'),
('MailAliasAccount', '*', '*', 'ALLOW', 'ROLE', 'marketing'),
('MailAliasAccount', '*', '*', 'ALLOW', 'ROLE', 'hr'),
('MailAlias', '*', '*', 'ALLOW', 'ROLE', 'hr'),
('MailForward', '*', '*', 'ALLOW', 'ROLE', 'marketing'),
('MailForward', '*', '*', 'ALLOW', 'ROLE', 'hr'),
('RoleInherit', '*', '*', 'ALLOW', 'ROLE', 'it'),
('RoleRole', '*', '*', 'ALLOW', 'ROLE', 'it'),
('AccountConfig', '*', '*', 'ALLOW', 'ROLE', 'sysadmin');
UPDATE `salix`.`ACL`
SET accessType='*', principalId='it'
WHERE model = 'Role';
DELETE FROM `salix`.`ACL`
WHERE id IN (280, 281);
UPDATE `salix`.`ACL`
SET accessType='*', principalId='marketing'
WHERE id=279;

View File

@ -1,5 +0,0 @@
UPDATE `salix`.`defaultViewConfig`
SET `columns` = '{"intrastat":false,"description":false,"density":false,"isActive":false,
"freightValue":false,"packageValue":false,"isIgnored":false,"price2":false,"ektFk":false,"weight":false,
"size":false,"comissionValue":false,"landing":false}'
WHERE tableCode = 'latestBuys'

View File

@ -1,33 +0,0 @@
UPDATE vn.department
SET notificationEmail='direccioncomercial@verdnatura.es'
WHERE id=96;
UPDATE vn.department
SET notificationEmail='direccioncomercial@verdnatura.es'
WHERE id=95;
UPDATE vn.department
SET notificationEmail='direccioncomercial@verdnatura.es'
WHERE id=115;
UPDATE vn.department
SET notificationEmail='direccioncomercial@verdnatura.es'
WHERE id=123;
UPDATE vn.department
SET notificationEmail='direccioncomercial@verdnatura.es'
WHERE id=94;
UPDATE vn.department
SET notificationEmail='direccioncomercial@verdnatura.es'
WHERE id=101;
UPDATE vn.department
SET notificationEmail='direccioncomercial@verdnatura.es'
WHERE id=80;
UPDATE vn.department
SET notificationEmail='direccioncomercial@verdnatura.es'
WHERE id=125;
UPDATE vn.department
SET notificationEmail='direccioncomercial@verdnatura.es'
WHERE id=98;
UPDATE vn.department
SET notificationEmail='direccioncomercial@verdnatura.es'
WHERE id=92;
UPDATE vn.department
SET notificationEmail=''
WHERE id=43;

View File

@ -1,142 +0,0 @@
DROP PROCEDURE IF EXISTS `vn`.`item_getBalance`;
DELIMITER $$
$$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`item_getBalance`(IN vItemId int, IN vWarehouse int)
BEGIN
DECLARE vDateInventory DATETIME;
DECLARE vCurdate DATE DEFAULT CURDATE();
DECLARE vDayEnd DATETIME DEFAULT util.dayEnd(vCurdate);
SELECT inventoried INTO vDateInventory FROM config;
SET @a = 0;
SET @currentLineFk = 0;
SET @shipped = '';
SELECT DATE(@shipped:= shipped) shipped,
alertLevel,
stateName,
origin,
reference,
clientFk,
name,
`in` AS invalue,
`out`,
@a := @a + IFNULL(`in`,0) - IFNULL(`out`,0) as balance,
@currentLineFk := IF (@shipped < CURDATE()
OR (@shipped = CURDATE() AND (isPicked OR alertLevel >= 2)),
lineFk,@currentLineFk) lastPreparedLineFk,
isTicket,
lineFk,
isPicked,
clientType,
claimFk
FROM
( SELECT tr.landed AS shipped,
b.quantity AS `in`,
NULL AS `out`,
al.id AS alertLevel,
st.name AS stateName,
s.name AS name,
e.ref AS reference,
e.id AS origin,
s.id AS clientFk,
IF(al.id = 3, TRUE, FALSE) isPicked,
FALSE AS isTicket,
b.id lineFk,
NULL `order`,
NULL AS clientType,
NULL AS claimFk
FROM buy b
JOIN entry e ON e.id = b.entryFk
JOIN travel tr ON tr.id = e.travelFk
JOIN supplier s ON s.id = e.supplierFk
JOIN alertLevel al ON al.id =
CASE
WHEN tr.shipped < CURDATE() THEN 3
WHEN tr.shipped = CURDATE() AND tr.isReceived = TRUE THEN 3
ELSE 0
END
JOIN state st ON st.code = al.code
WHERE tr.landed >= vDateInventory
AND vWarehouse = tr.warehouseInFk
AND b.itemFk = vItemId
AND e.isInventory = FALSE
AND e.isRaid = FALSE
UNION ALL
SELECT tr.shipped,
NULL,
b.quantity,
al.id,
st.name,
s.name,
e.ref,
e.id,
s.id,
IF(al.id = 3, TRUE, FALSE),
FALSE,
b.id,
NULL,
NULL,
NULL
FROM buy b
JOIN entry e ON e.id = b.entryFk
JOIN travel tr ON tr.id = e.travelFk
JOIN warehouse w ON w.id = tr.warehouseOutFk
JOIN supplier s ON s.id = e.supplierFk
JOIN alertLevel al ON al.id =
CASE
WHEN tr.shipped < CURDATE() THEN 3
WHEN tr.shipped = CURDATE() AND tr.isReceived = TRUE THEN 3
ELSE 0
END
JOIN state st ON st.code = al.code
WHERE tr.shipped >= vDateInventory
AND vWarehouse =tr.warehouseOutFk
AND s.id <> 4
AND b.itemFk = vItemId
AND e.isInventory = FALSE
AND w.isFeedStock = FALSE
AND e.isRaid = FALSE
UNION ALL
SELECT DATE(t.shipped),
NULL,
s.quantity,
al.id,
st.name,
t.nickname,
t.refFk,
t.id,
t.clientFk,
stk.id,
TRUE,
s.id,
st.`order`,
ct.code,
cb.claimFk
FROM sale s
JOIN ticket t ON t.id = s.ticketFk
LEFT JOIN ticketState ts ON ts.ticket = t.id
LEFT JOIN state st ON st.code = ts.code
JOIN client c ON c.id = t.clientFk
JOIN clientType ct ON ct.id = c.clientTypeFk
JOIN alertLevel al ON al.id =
CASE
WHEN t.shipped < curdate() THEN 3
WHEN t.shipped > util.dayEnd(curdate()) THEN 0
ELSE IFNULL(ts.alertLevel, 0)
END
LEFT JOIN state stPrep ON stPrep.`code` = 'PREPARED'
LEFT JOIN saleTracking stk ON stk.saleFk = s.id AND stk.stateFk = stPrep.id
LEFT JOIN claimBeginning cb ON s.id = cb.saleFk
WHERE t.shipped >= vDateInventory
AND s.itemFk = vItemId
AND vWarehouse =t.warehouseFk
ORDER BY shipped, alertLevel DESC, isTicket, `order` DESC, isPicked DESC, `in` DESC, `out` DESC
) AS itemDiary;
END;
$$
DELIMITER ;

View File

@ -1,2 +0,0 @@
ALTER TABLE vn.payMethod CHANGE ibanRequiredForClients isIbanRequiredForClients tinyint(3) DEFAULT 0 NULL;
ALTER TABLE vn.payMethod CHANGE ibanRequiredForSuppliers isIbanRequiredForSuppliers tinyint(3) DEFAULT 0 NULL;

View File

@ -1,120 +0,0 @@
DROP PROCEDURE IF EXISTS `vn`.`sale_recalcComponent`;
DELIMITER $$
$$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`sale_recalcComponent`(vOption INT)
proc: BEGIN
/**
* Actualiza los componentes
*
* @table tmp.recalculateSales
*/
DECLARE vShipped DATE;
DECLARE vWarehouseFk SMALLINT;
DECLARE vAgencyModeFk INT;
DECLARE vAddressFk INT;
DECLARE vTicketFk BIGINT;
DECLARE vItemFk BIGINT;
DECLARE vLanded DATE;
DECLARE vIsEditable BOOLEAN;
DECLARE vZoneFk INTEGER;
DECLARE vOption INTEGER;
DECLARE vSale INTEGER;
DECLARE vDone BOOL DEFAULT FALSE;
DECLARE vCur CURSOR FOR
SELECT id from tmp.recalculateSales;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
OPEN vCur;
l: LOOP
SET vDone = FALSE;
FETCH vCur INTO vSale;
IF vDone THEN
LEAVE l;
END IF;
SELECT t.refFk IS NULL AND (IFNULL(ts.alertLevel, 0) = 0 OR s.price = 0),
s.ticketFk,
s.itemFk ,
t.zoneFk,
t.warehouseFk,
t.shipped,
t.addressFk,
t.agencyModeFk,
t.landed
INTO vIsEditable,
vTicketFk,
vItemFk,
vZoneFk,
vWarehouseFk,
vShipped,
vAddressFk,
vAgencyModeFk,
vLanded
FROM ticket t
JOIN sale s ON s.ticketFk = t.id
LEFT JOIN ticketState ts ON ts.ticketFk = t.id
WHERE s.id = vSale;
CALL zone_getLanded(vShipped, vAddressFk, vAgencyModeFk, vWarehouseFk, TRUE);
IF (SELECT COUNT(*) FROM tmp.zoneGetLanded LIMIT 1) = 0 THEN
CALL util.throw('There is no zone for these parameters');
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);
DELETE FROM tmp.buyUltimate WHERE itemFk != vItemFk;
DROP TEMPORARY TABLE IF EXISTS tmp.ticketLot;
CREATE TEMPORARY TABLE tmp.ticketLot
SELECT vWarehouseFk warehouseFk, NULL available, vItemFk itemFk, buyFk, vZoneFk zoneFk
FROM tmp.buyUltimate
WHERE itemFk = vItemFk;
CALL catalog_componentPrepare();
CALL catalog_componentCalculate(vZoneFk, vAddressFk, vShipped, vWarehouseFk);
DROP TEMPORARY TABLE IF EXISTS tmp.sale;
CREATE TEMPORARY TABLE tmp.sale
(PRIMARY KEY (saleFk)) ENGINE = MEMORY
SELECT vSale saleFk,vWarehouseFk warehouseFk;
IF vOption IS NULL THEN
SET vOption = IF(vIsEditable, 1, 6);
END IF;
CALL ticketComponentUpdateSale(vOption);
CALL catalog_componentPurge();
DROP TEMPORARY TABLE tmp.buyUltimate;
DROP TEMPORARY TABLE tmp.sale;
END LOOP;
CLOSE vCur;
END$$
DELIMITER ;

View File

@ -1,23 +0,0 @@
DROP PROCEDURE IF EXISTS `vn`.`sale_calculateComponent`;
DELIMITER $$
$$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`sale_calculateComponent`(vSale INT, vOption INT)
proc: BEGIN
/**
* Crea tabla temporal para vn.sale_recalcComponent() para recalcular los componentes
*
* @param vSale Id de la venta
* @param vOption indica en que componente pone el descuadre, NULL en casos habituales
*/
DROP TEMPORARY TABLE IF EXISTS tmp.recalculateSales;
CREATE TEMPORARY TABLE tmp.recalculateSales
SELECT s.id
FROM sale s
WHERE s.id = vSale;
CALL vn.sale_recalcComponent(vOption);
DROP TEMPORARY TABLE tmp.recalculateSales;
END$$
DELIMITER ;

View File

@ -1,2 +0,0 @@
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
VALUES ('Sale','payBack','WRITE','ALLOW','ROLE','employee');

View File

@ -1 +0,0 @@
ALTER TABLE `vn`.`payMethod` ADD hasVerified TINYINT(1) DEFAULT 0 NULL;

View File

@ -1,90 +0,0 @@
DROP PROCEDURE IF EXISTS `vn`.`ticket_doRefund`;
DELIMITER $$
$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_doRefund`(IN vOriginTicket INT, OUT vNewTicket INT)
BEGIN
DECLARE vDone BIT DEFAULT 0;
DECLARE vCustomer MEDIUMINT;
DECLARE vWarehouse TINYINT;
DECLARE vCompany MEDIUMINT;
DECLARE vAddress MEDIUMINT;
DECLARE vRefundAgencyMode INT;
DECLARE vItemFk INT;
DECLARE vQuantity DECIMAL (10,2);
DECLARE vConcept VARCHAR(50);
DECLARE vPrice DECIMAL (10,2);
DECLARE vDiscount TINYINT;
DECLARE vSaleNew INT;
DECLARE vSaleMain INT;
DECLARE vZoneFk INT;
DECLARE vRsMainTicket CURSOR FOR
SELECT *
FROM tmp.sale;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = 1;
SELECT id INTO vRefundAgencyMode
FROM agencyMode WHERE `name` = 'ABONO';
SELECT clientFk, warehouseFk, companyFk, addressFk
INTO vCustomer, vWarehouse, vCompany, vAddress
FROM ticket
WHERE id = vOriginTicket;
SELECT id INTO vZoneFk
FROM zone WHERE agencyModeFk = vRefundAgencyMode
LIMIT 1;
INSERT INTO vn.ticket (
clientFk,
shipped,
addressFk,
agencyModeFk,
nickname,
warehouseFk,
companyFk,
landed,
zoneFk
)
SELECT
vCustomer,
CURDATE(),
vAddress,
vRefundAgencyMode,
a.nickname,
vWarehouse,
vCompany,
CURDATE(),
vZoneFk
FROM address a
WHERE a.id = vAddress;
SET vNewTicket = LAST_INSERT_ID();
SET vDone := 0;
OPEN vRsMainTicket ;
FETCH vRsMainTicket INTO vSaleMain, vItemFk, vQuantity, vConcept, vPrice, vDiscount;
WHILE NOT vDone DO
INSERT INTO vn.sale(ticketFk, itemFk, quantity, concept, price, discount)
VALUES( vNewTicket, vItemFk, vQuantity, vConcept, vPrice, vDiscount );
SET vSaleNew = LAST_INSERT_ID();
INSERT INTO vn.saleComponent(saleFk,componentFk,`value`)
SELECT vSaleNew,componentFk,`value`
FROM vn.saleComponent
WHERE saleFk = vSaleMain;
FETCH vRsMainTicket INTO vSaleMain, vItemFk, vQuantity, vConcept, vPrice, vDiscount;
END WHILE;
CLOSE vRsMainTicket;
END;
$$
DELIMITER ;

View File

@ -1,3 +0,0 @@
UPDATE `vn`.`department`
SET `notificationEmail` = 'finanzas@verdnatura.es'
WHERE `name` = 'FINANZAS';

View File

@ -1,2 +0,0 @@
UPDATE `vn`.`supplier`
SET isPayMethodChecked = TRUE;

View File

@ -1,33 +0,0 @@
DELIMITER $$
$$
CREATE DEFINER=`root`@`%` TRIGGER `vn`.`payment_afterInsert` AFTER INSERT ON `payment` FOR EACH ROW
BEGIN
DECLARE vIsPayMethodChecked BOOLEAN;
DECLARE vEmail VARCHAR(150);
SELECT isPayMethodChecked INTO vIsPayMethodChecked
FROM supplier
WHERE id = NEW.supplierFk;
IF vIsPayMethodChecked = FALSE THEN
SELECT notificationEmail INTO vEmail
FROM department
WHERE name = 'FINANZAS';
CALL mail_insert(
vEmail,
NULL,
'Pago con método sin verificar',
CONCAT(
'Se ha realizado el pago ',
NEW.id,
' al proveedor ',
NEW.supplierFk,
' con el método de pago sin verificar.'
)
);
END IF;
END$$
DELIMITER ;

View File

@ -1,26 +0,0 @@
DROP TRIGGER IF EXISTS `vn`.`supplier_beforeUpdate`;
DELIMITER $$
$$
CREATE DEFINER=`root`@`%` TRIGGER `vn`.`supplier_beforeUpdate`
BEFORE UPDATE ON `vn`.`supplier` FOR EACH ROW
BEGIN
DECLARE vHasChange BOOL DEFAULT FALSE;
DECLARE vPayMethodHasVerified BOOL;
SELECT hasVerified INTO vPayMethodHasVerified
FROM payMethod
WHERE id = NEW.payMethodFk;
SET vHasChange = (NEW.payDemFk <> OLD.payDemFk) OR (NEW.payDay <> OLD.payDay);
IF vPayMethodHasVerified AND !vHasChange THEN
SET vHasChange = (NEW.payMethodFk <> OLD.payMethodFk);
END IF;
IF vHasChange THEN
SET NEW.isPayMethodChecked = FALSE;
END IF;
END$$
DELIMITER ;

View File

@ -0,0 +1,8 @@
CREATE TABLE `vn`.`claimConfig` (
`id` int(11) NOT NULL,
`pickupContact` varchar(250),
PRIMARY KEY (`id`)
);
INSERT INTO vn.claimConfig (id, pickupContact)
VALUES(1, 'Email: cmorenoa@logista.com Telf: 961594250 Extensión: 206');

View File

@ -0,0 +1 @@
ALTER TABLE vn.claim ADD packages smallint(10) unsigned DEFAULT 0 NULL COMMENT 'packages received by the client';

File diff suppressed because one or more lines are too long

View File

@ -32,6 +32,11 @@ INSERT INTO `vn`.`packagingConfig`(`upperGap`)
('10');
UPDATE `account`.`role` SET id = 100 WHERE id = 0;
INSERT INTO `account`.`roleConfig`(`id`, `mysqlPassword`, `rolePrefix`, `userPrefix`, `userHost`, `tplUser`)
VALUES
(1, 'mysqlPassword', '$', '!', '%', 'any');
CALL `account`.`role_sync`;
INSERT INTO `account`.`user`(`id`,`name`, `nickname`, `password`,`role`,`active`,`email`, `lang`, `image`)
@ -807,25 +812,25 @@ INSERT INTO `vn`.`itemFamily`(`code`, `description`)
('VT', 'Sales');
INSERT INTO `vn`.`item`(`id`, `typeFk`, `size`, `inkFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `expenceFk`,
`comment`, `relevancy`, `image`, `subName`, `minPrice`, `stars`, `family`, `isFloramondo`, `genericFk`, `itemPackingTypeFk`)
`comment`, `relevancy`, `image`, `subName`, `minPrice`, `stars`, `family`, `isFloramondo`, `genericFk`, `itemPackingTypeFk`, `hasMinPrice`)
VALUES
(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, 'H'),
(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, 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, 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, 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, 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, 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, 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, NULL),
(71, 6, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'VT', 0, NULL, NULL);
(1, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '1', NULL, 0, 1, 'VT', 0, NULL, 'V', 0),
(2, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '2', NULL, 0, 2, 'VT', 0, NULL, 'H', 0),
(3, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '3', NULL, 0, 5, 'VT', 0, NULL, NULL, 0),
(4, 1, 60, 'YEL', 1, 1, 'Increases block', 1, 05080000, 4751000000, NULL, 0, '4', NULL, 0, 3, 'VT', 0, NULL, NULL, 0),
(5, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '5', NULL, 0, 3, 'VT', 0, NULL, NULL, 0),
(6, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '6', NULL, 0, 4, 'VT', 0, NULL, NULL, 0),
(7, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '7', NULL, 0, 4, 'VT', 0, NULL, NULL, 0),
(8, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '8', NULL, 0, 5, 'VT', 0, NULL, NULL, 0),
(9, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '9', NULL, 0, 4, 'VT', 1, NULL, NULL, 0),
(10, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '10', NULL, 0, 4, 'VT', 0, NULL, NULL, 0),
(11, 1, 60, 'YEL', 1, 1, NULL, 1, 05080000, 4751000000, NULL, 0, '11', NULL, 0, 4, 'VT', 0, NULL, NULL, 0),
(12, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '12', NULL, 0, 3, 'VT', 0, NULL, NULL, 0),
(13, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '13', NULL, 1, 2, 'VT', 1, NULL, NULL, 1),
(14, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 4, 'VT', 1, NULL, NULL, 0),
(15, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'EMB', 0, NULL, NULL, 0),
(16, 6, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'EMB', 0, NULL, NULL, 0),
(71, 6, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'VT', 0, NULL, NULL, 0);
-- Update the taxClass after insert of the items
UPDATE `vn`.`itemTaxCountry` SET `taxClassFk` = 2
@ -835,7 +840,7 @@ INSERT INTO `vn`.`priceFixed`(`id`, `itemFk`, `rate0`, `rate1`, `rate2`, `rate3`
VALUES
(1, 1, 0, 0, 2.5, 2, CURDATE(), DATE_ADD(CURDATE(), INTERVAL +1 MONTH), 0, 1, CURDATE()),
(2, 3, 10, 10, 10, 10, CURDATE(), DATE_ADD(CURDATE(), INTERVAL +1 MONTH), 0, 1, CURDATE()),
(3, 5, 8.5, 10, 7.5, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL +1 MONTH), 1, 2, CURDATE());
(3, 13, 8.5, 10, 7.5, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL +1 MONTH), 1, 2, CURDATE());
INSERT INTO `vn`.`expeditionBoxVol`(`boxFk`, `m3`, `ratio`)
VALUES
@ -1705,12 +1710,12 @@ INSERT INTO `vn`.`claimState`(`id`, `code`, `description`, `roleFk`, `priority`,
( 6, 'mana', 'Mana', 1, 4, 0),
( 7, 'lack', 'Faltas', 1, 2, 0);
INSERT INTO `vn`.`claim`(`id`, `ticketCreated`, `claimStateFk`, `observation`, `clientFk`, `workerFk`, `responsibility`, `isChargedToMana`, `created` )
INSERT INTO `vn`.`claim`(`id`, `ticketCreated`, `claimStateFk`, `observation`, `clientFk`, `workerFk`, `responsibility`, `isChargedToMana`, `created`, `packages`)
VALUES
(1, CURDATE(), 1, 'Cu nam labores lobortis definiebas, ei aliquyam salutatus persequeris quo, cum eu nemore fierent dissentiunt. Per vero dolor id, vide democritum scribentur eu vim, pri erroribus temporibus ex.', 1101, 18, 3, 0, CURDATE()),
(2, CURDATE(), 2, 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.', 1101, 18, 3, 0, CURDATE()),
(3, CURDATE(), 3, 'An vim commodo dolorem volutpat, cu expetendis voluptatum usu, et mutat consul adversarium his. His natum numquam legimus an, diam fabulas mei ut. Melius fabellas sadipscing vel id. Partem diceret mandamus mea ne, has te tempor nostrud. Aeque nostro eum no.', 1101, 18, 1, 1, CURDATE()),
(4, CURDATE(), 3, 'Wisi forensibus mnesarchum in cum. Per id impetus abhorreant, his no magna definiebas, inani rationibus in quo. Ut vidisse dolores est, ut quis nominavi mel. Ad pri quod apeirian concludaturque.', 1104, 18, 5, 0, CURDATE());
(1, CURDATE(), 1, 'Cu nam labores lobortis definiebas, ei aliquyam salutatus persequeris quo, cum eu nemore fierent dissentiunt. Per vero dolor id, vide democritum scribentur eu vim, pri erroribus temporibus ex.', 1101, 18, 3, 0, CURDATE(), 0),
(2, CURDATE(), 2, 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.', 1101, 18, 3, 0, CURDATE(), 1),
(3, CURDATE(), 3, 'An vim commodo dolorem volutpat, cu expetendis voluptatum usu, et mutat consul adversarium his. His natum numquam legimus an, diam fabulas mei ut. Melius fabellas sadipscing vel id. Partem diceret mandamus mea ne, has te tempor nostrud. Aeque nostro eum no.', 1101, 18, 1, 1, CURDATE(), 5),
(4, CURDATE(), 3, 'Wisi forensibus mnesarchum in cum. Per id impetus abhorreant, his no magna definiebas, inani rationibus in quo. Ut vidisse dolores est, ut quis nominavi mel. Ad pri quod apeirian concludaturque.', 1104, 18, 5, 0, CURDATE(), 10);
INSERT INTO `vn`.`claimBeginning`(`id`, `claimFk`, `saleFk`, `quantity`)
VALUES

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,6 @@ IGNORETABLES=(
--ignore-table=bs.productionIndicators
--ignore-table=bs.VentasPorCliente
--ignore-table=bs.v_ventas
--ignore-table=edi.supplyOffer
--ignore-table=postgresql.currentWorkersStats
--ignore-table=vn.accounting__
--ignore-table=vn.agencyModeZone

View File

@ -346,16 +346,17 @@ export default {
saveFieldsButton: '.vn-popover.shown vn-button[label="Save"] > button'
},
itemFixedPrice: {
add: 'vn-fixed-price vn-icon[icon="add_circle"]',
fourthFixedPrice: 'vn-fixed-price vn-tr:nth-child(4)',
fourthItemID: 'vn-fixed-price vn-tr:nth-child(4) vn-autocomplete[ng-model="price.itemFk"]',
fourthWarehouse: 'vn-fixed-price vn-tr:nth-child(4) vn-autocomplete[ng-model="price.warehouseFk"]',
fourthPPU: 'vn-fixed-price vn-tr:nth-child(4) > vn-td-editable:nth-child(4)',
fourthPPP: 'vn-fixed-price vn-tr:nth-child(4) > vn-td-editable:nth-child(5)',
fourthMinPrice: 'vn-fixed-price vn-tr:nth-child(4) > vn-td-editable:nth-child(6)',
fourthStarted: 'vn-fixed-price vn-tr:nth-child(4) vn-date-picker[ng-model="price.started"]',
fourthEnded: 'vn-fixed-price vn-tr:nth-child(4) vn-date-picker[ng-model="price.ended"]',
fourthDeleteIcon: 'vn-fixed-price vn-tr:nth-child(4) > vn-td:nth-child(9) > vn-icon-button[icon="delete"]'
add: 'vn-fixed-price vn-icon-button[icon="add_circle"]',
fourthFixedPrice: 'vn-fixed-price tr:nth-child(5)',
fourthItemID: 'vn-fixed-price tr:nth-child(5) vn-autocomplete[ng-model="price.itemFk"]',
fourthWarehouse: 'vn-fixed-price tr:nth-child(5) vn-autocomplete[ng-model="price.warehouseFk"]',
fourthPPU: 'vn-fixed-price tr:nth-child(5) > td:nth-child(4)',
fourthPPP: 'vn-fixed-price tr:nth-child(5) > td:nth-child(5)',
fourthHasMinPrice: 'vn-fixed-price tr:nth-child(5) > td:nth-child(6) > vn-check[ng-model="price.hasMinPrice"]',
fourthMinPrice: 'vn-fixed-price tr:nth-child(5) > td:nth-child(6) > vn-input-number[ng-model="price.minPrice"]',
fourthStarted: 'vn-fixed-price tr:nth-child(5) vn-date-picker[ng-model="price.started"]',
fourthEnded: 'vn-fixed-price tr:nth-child(5) vn-date-picker[ng-model="price.ended"]',
fourthDeleteIcon: 'vn-fixed-price tr:nth-child(5) > td:nth-child(9) > vn-icon-button[icon="delete"]'
},
itemCreateView: {
temporalName: 'vn-item-create vn-textfield[ng-model="$ctrl.item.provisionalName"]',
@ -692,6 +693,7 @@ export default {
claimBasicData: {
claimState: 'vn-claim-basic-data vn-autocomplete[ng-model="$ctrl.claim.claimStateFk"]',
observation: 'vn-textarea[ng-model="$ctrl.claim.observation"]',
packages: 'vn-input-number[ng-model="$ctrl.claim.packages"]',
hasToPickUpCheckbox: 'vn-claim-basic-data vn-check[ng-model="$ctrl.claim.hasToPickUp"]',
saveButton: `button[type=submit]`
},
@ -898,6 +900,7 @@ export default {
sundayWorkedHours: 'vn-worker-time-control vn-table > div > vn-tfoot > vn-tr:nth-child(1) > vn-td:nth-child(7)',
weekWorkedHours: 'vn-worker-time-control vn-side-menu vn-label-value > section > span',
nextMonthButton: 'vn-worker-time-control vn-side-menu vn-calendar vn-button[icon=keyboard_arrow_right]',
previousMonthButton: 'vn-worker-time-control vn-side-menu vn-calendar vn-button[icon=keyboard_arrow_left]',
secondWeekDay: 'vn-worker-time-control vn-side-menu vn-calendar .day:nth-child(8) > .day-number',
navigateBackToIndex: 'vn-worker-descriptor [name="goToModuleIndex"]'
},

View File

@ -10,6 +10,8 @@ describe('Worker time control path', () => {
await page.loginAndModule('salesBoss', 'worker');
await page.accessToSearchResult('HankPym');
await page.accessToSection('worker.card.timeControl');
await page.waitToClick(selectors.workerTimeControl.previousMonthButton);
await page.waitToClick(selectors.workerTimeControl.secondWeekDay);
});
afterAll(async() => {
@ -97,9 +99,9 @@ describe('Worker time control path', () => {
expect(result).toEqual(scanTime);
});
it(`should check Hank Pym worked 7 hours`, async() => {
await page.waitForTextInElement(selectors.workerTimeControl.mondayWorkedHours, '07:00 h.');
// 3736 check proc vn.timeControl_calculate
xit(`should check Hank Pym worked 6:40 hours`, async() => {
await page.waitForTextInElement(selectors.workerTimeControl.mondayWorkedHours, '06:40 h.');
});
});
@ -152,8 +154,8 @@ describe('Worker time control path', () => {
expect(result).toEqual(scanTime);
});
it(`should check Hank Pym worked 8 happy hours`, async() => {
await page.waitForTextInElement(selectors.workerTimeControl.tuesdayWorkedHours, '08:00 h.');
it(`should check Hank Pym worked 7:40 hours`, async() => {
await page.waitForTextInElement(selectors.workerTimeControl.tuesdayWorkedHours, '07:40 h.');
});
});
@ -206,8 +208,8 @@ describe('Worker time control path', () => {
expect(result).toEqual(scanTime);
});
it(`should check Hank Pym worked 8 cheerfull hours`, async() => {
await page.waitForTextInElement(selectors.workerTimeControl.wednesdayWorkedHours, '08:00 h.');
it(`should check Hank Pym worked 7:40 cheerfull hours`, async() => {
await page.waitForTextInElement(selectors.workerTimeControl.wednesdayWorkedHours, '07:40 h.');
});
});
@ -257,8 +259,8 @@ describe('Worker time control path', () => {
expect(result).toEqual(scanTime);
});
it(`should check Hank Pym worked 8 joyfull hours`, async() => {
await page.waitForTextInElement(selectors.workerTimeControl.thursdayWorkedHours, '08:00 h.');
it(`should check Hank Pym worked 7:40 joyfull hours`, async() => {
await page.waitForTextInElement(selectors.workerTimeControl.thursdayWorkedHours, '07:40 h.');
});
});
@ -307,8 +309,8 @@ describe('Worker time control path', () => {
expect(result).toEqual(scanTime);
});
it(`should check Hank Pym worked 8 hours with a smile on his face`, async() => {
await page.waitForTextInElement(selectors.workerTimeControl.fridayWorkedHours, '08:00 h.');
it(`should check Hank Pym worked 7:40 hours with a smile on his face`, async() => {
await page.waitForTextInElement(selectors.workerTimeControl.fridayWorkedHours, '07:40 h.');
});
});
});
@ -327,6 +329,8 @@ describe('Worker time control path', () => {
it('should access to the time control section', async() => {
await page.accessToSection('worker.card.timeControl');
await page.waitForState('worker.card.timeControl');
await page.waitToClick(selectors.workerTimeControl.previousMonthButton);
await page.waitToClick(selectors.workerTimeControl.secondWeekDay);
});
it('should lovingly scan in Hank Pym', async() => {
@ -352,8 +356,8 @@ describe('Worker time control path', () => {
expect(result).toEqual(scanTime);
});
it(`should check Hank Pym worked 8 hours with all his will`, async() => {
await page.waitForTextInElement(selectors.workerTimeControl.saturdayWorkedHours, '08:00 h.');
it(`should check Hank Pym worked 7:40 hours with all his will`, async() => {
await page.waitForTextInElement(selectors.workerTimeControl.saturdayWorkedHours, '07:40 h.');
});
});
@ -380,11 +384,11 @@ describe('Worker time control path', () => {
expect(result).toEqual(scanTime);
});
it(`should check Hank Pym worked 8 glad hours`, async() => {
await page.waitForTextInElement(selectors.workerTimeControl.sundayWorkedHours, '08:00 h.');
it(`should check Hank Pym worked 7:40 glad hours`, async() => {
await page.waitForTextInElement(selectors.workerTimeControl.sundayWorkedHours, '07:40 h.');
});
it(`should check Hank Pym doesn't have hours set on the next months first week`, async() => {
it(`should check Hank Pym doesn't have hours set on the next months second week`, async() => {
await page.waitToClick(selectors.workerTimeControl.nextMonthButton);
await page.waitToClick(selectors.workerTimeControl.secondWeekDay);
await page.waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '00:00 h.');
@ -408,10 +412,12 @@ describe('Worker time control path', () => {
await page.loginAndModule('HankPym', 'worker');
await page.accessToSearchResult('HankPym');
await page.accessToSection('worker.card.timeControl');
await page.waitToClick(selectors.workerTimeControl.previousMonthButton);
await page.waitToClick(selectors.workerTimeControl.secondWeekDay);
});
it('should check his weekly hours are alright', async() => {
await page.waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '55:00 h.');
await page.waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '52:40 h.');
});
});
});

View File

@ -16,33 +16,17 @@ describe('Item fixed prices path', () => {
});
it('should click on the add new foxed price button', async() => {
await page.doSearch();
await page.waitToClick(selectors.itemFixedPrice.add);
await page.waitForSelector(selectors.itemFixedPrice.fourthFixedPrice);
});
it('should fill the fixed price data', async() => {
const now = new Date();
const searchValue = 'Chest ammo box';
await page.waitToClick(selectors.itemFixedPrice.fourthItemID);
await page.write('body > div > div > div.content > div.filter.ng-scope > vn-textfield', searchValue);
try {
await page.waitForFunction(searchValue => {
const element = document.querySelector('li.active');
if (element)
return element.innerText.toLowerCase().includes(searchValue.toLowerCase());
}, {}, searchValue);
} catch (error) {
const builtSelector = await page.selectorFormater(selectors.ticketSales.moreMenuState);
const inputValue = await page.evaluate(() => {
return document.querySelector('.vn-drop-down.shown vn-textfield input').value;
});
throw new Error(`${builtSelector} value is ${inputValue}! ${error}`);
}
await page.keyboard.press('Enter');
await page.autocompleteSearch(selectors.itemFixedPrice.fourthWarehouse, 'Warehouse one');
await page.writeOnEditableTD(selectors.itemFixedPrice.fourthPPU, '20');
await page.writeOnEditableTD(selectors.itemFixedPrice.fourthPPP, '10');
await page.writeOnEditableTD(selectors.itemFixedPrice.fourthMinPrice, '5');
await page.write(selectors.itemFixedPrice.fourthPPU, '1');
await page.write(selectors.itemFixedPrice.fourthPPP, '1');
await page.write(selectors.itemFixedPrice.fourthMinPrice, '1');
await page.pickDate(selectors.itemFixedPrice.fourthStarted, now);
await page.pickDate(selectors.itemFixedPrice.fourthEnded, now);
const message = await page.waitForSnackbar();
@ -53,7 +37,9 @@ describe('Item fixed prices path', () => {
it('should reload the section and check the created price has the expected ID', async() => {
await page.accessToSection('item.index');
await page.accessToSection('item.fixedPrice');
const result = await page.getProperty('vn-fixed-price > div > vn-card > vn-table > div > vn-tbody > vn-tr:nth-child(4) > vn-td:nth-child(1) > span', 'innerText');
await page.doSearch();
const result = await page.waitToGetProperty(selectors.itemFixedPrice.fourthItemID, 'value');
expect(result).toContain('13');
});

View File

@ -25,7 +25,7 @@ describe('Ticket Create new tracking state path', () => {
});
it(`should create a new state`, async() => {
await page.autocompleteSearch(selectors.createStateView.state, '¿Fecha?');
await page.autocompleteSearch(selectors.createStateView.state, 'OK');
await page.waitToClick(selectors.createStateView.saveStateButton);
const message = await page.waitForSnackbar();

View File

@ -24,6 +24,8 @@ describe('Claim edit basic data path', () => {
await page.autocompleteSearch(selectors.claimBasicData.claimState, 'Gestionado');
await page.clearTextarea(selectors.claimBasicData.observation);
await page.write(selectors.claimBasicData.observation, 'edited observation');
await page.clearInput(selectors.claimBasicData.packages);
await page.write(selectors.claimBasicData.packages, '2');
await page.waitToClick(selectors.claimBasicData.saveButton);
const message = await page.waitForSnackbar();
@ -64,10 +66,19 @@ describe('Claim edit basic data path', () => {
expect(result).toEqual('edited observation');
});
it('should confirm the claim packages was edited', async() => {
const result = await page
.waitToGetProperty(selectors.claimBasicData.packages, 'value');
expect(result).toEqual('2');
});
it(`should edit the claim to leave it untainted`, async() => {
await page.autocompleteSearch(selectors.claimBasicData.claimState, 'Pendiente');
await page.clearTextarea(selectors.claimBasicData.observation);
await page.write(selectors.claimBasicData.observation, 'Observation one');
await page.clearInput(selectors.claimBasicData.packages);
await page.write(selectors.claimBasicData.packages, '0');
await page.waitToClick(selectors.claimBasicData.saveButton);
const message = await page.waitForSnackbar();

View File

@ -80,7 +80,7 @@ describe('Account create and basic data path', () => {
await page.reloadSection('account.card.roles');
const rolesCount = await page.countElement(selectors.accountRoles.anyResult);
expect(rolesCount).toEqual(35);
expect(rolesCount).toEqual(61);
});
});

View File

@ -32,6 +32,9 @@ export default class SmartTable extends Component {
this._options = options;
if (!options) return;
if (options.defaultSearch)
this.displaySearch();
const activeButtons = options.activeButtons;
const missingId = activeButtons && activeButtons.shownColumns && !this.viewConfigId;
if (missingId)

View File

@ -221,5 +221,6 @@
"Can't transfer claimed sales": "No puedes transferir lineas reclamadas",
"You don't have privileges to create pay back": "No tienes permisos para crear un abono",
"The item is required": "El artículo es requerido",
"date in the future": "Fecha en el futuro",
"reference duplicated": "Referencia duplicada"
}

View File

@ -26,7 +26,6 @@ module.exports = Self => {
Self.sync = async function(userName, password, force) {
let $ = Self.app.models;
let user = await $.Account.findOne({
fields: ['id'],
where: {name: userName}

View File

@ -28,6 +28,10 @@ module.exports = Self => {
{
arg: 'hasToPickUp',
type: 'boolean'
},
{
arg: 'packages',
type: 'number'
}],
returns: {
type: 'object',

View File

@ -43,6 +43,9 @@
},
"workerFk": {
"type": "number"
},
"packages": {
"type": "number"
}
},
"relations": {

View File

@ -43,7 +43,14 @@
order="priority ASC"
vn-focus>
</vn-autocomplete>
</vn-horizontal>
</vn-horizontal>
<vn-horizontal>
<vn-input-number vn-one
min="0"
type="number"
label="Packages received"
ng-model="$ctrl.claim.packages">
</vn-input-number>
</vn-horizontal>
<vn-horizontal>
<vn-textarea

View File

@ -5,4 +5,5 @@ Responsability: Responsabilidad
Company: Empresa
Sales/Client: Comercial/Cliente
Pick up: Recoger
When checked will notify a pickup to the salesPerson: Cuando se marque enviará una notificación de recogida al comercial
When checked will notify a pickup to the salesPerson: Cuando se marque enviará una notificación de recogida al comercial
Packages received: Bultos recibidos

View File

@ -78,6 +78,11 @@
</vn-table>
</vn-card>
</vn-data-viewer>
<vn-button
label="Next"
class="next"
ui-sref="claim.card.photos">
</vn-button>
<vn-float-button
icon="add"
ng-if="$ctrl.isRewritable"

View File

@ -25,3 +25,6 @@
}
}
.next{
float: right;
}

View File

@ -1,8 +1,7 @@
const models = require('vn-loopback/server/server').models;
const soap = require('soap');
// #3673 sendSms tests excluded
xdescribe('client sendSms()', () => {
describe('client sendSms()', () => {
it('should now send a message and log it', async() => {
spyOn(soap, 'createClientAsync').and.returnValue('a so fake client');
const tx = await models.Client.beginTransaction({});

View File

@ -1,9 +1,10 @@
const models = require('vn-loopback/server/server').models;
xdescribe('Client updatePortfolio', () => {
const salesPersonId = 18;
describe('Client updatePortfolio', () => {
const clientId = 1108;
it('should update the portfolioWeight', async() => {
it('should update the portfolioWeight when the salesPerson of a client changes', async() => {
const salesPersonId = 18;
const tx = await models.Client.beginTransaction({});
try {
@ -15,9 +16,34 @@ xdescribe('Client updatePortfolio', () => {
await models.Client.updatePortfolio();
let [vendedores] = await models.Client.rawSql(`SELECT portfolioWeight FROM bs.vendedores WHERE Id_Trabajador = ${salesPersonId}; `, null, options);
let [salesPerson] = await models.Client.rawSql(`SELECT portfolioWeight FROM bs.salesPerson WHERE workerFk = ${salesPersonId}; `, null, options);
expect(vendedores.portfolioWeight).toEqual(expectedResult);
expect(salesPerson.portfolioWeight).toEqual(expectedResult);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
// 3742 first have to migrate vn2008.Clientes_cedidos to vn
xit('should keep the same portfolioWeight when a salesperson is unassigned of a client', async() => {
const salesPersonId = 19;
const tx = await models.Client.beginTransaction({});
try {
const options = {transaction: tx};
const expectedResult = 34.40;
await models.Client.rawSql(`UPDATE vn.client SET salesPersonFk = NULL WHERE id = ${clientId}; `);
await models.Client.updatePortfolio();
let [salesPerson] = await models.Client.rawSql(`SELECT portfolioWeight FROM bs.salesPerson WHERE workerFk = ${salesPersonId}; `, null, options);
expect(salesPerson.portfolioWeight).toEqual(expectedResult);
await tx.rollback();
} catch (e) {

View File

@ -1,7 +1,6 @@
const app = require('vn-loopback/server/server');
// #3673 sendSms tests excluded
xdescribe('sms send()', () => {
describe('sms send()', () => {
it('should not return status error', async() => {
const ctx = {req: {accessToken: {userId: 1}}};
const result = await app.models.Sms.send(ctx, 1105, '123456789', 'My SMS Body');

View File

@ -39,17 +39,25 @@ class Controller extends Descriptor {
loadData() {
const filter = {
include: [
{
relation: 'company',
{relation: 'supplier'},
{relation: 'invoiceInDueDay'},
{relation: 'company',
scope: {
fields: ['id', 'code']
}
}
]
};
return this.getData(`InvoiceIns/${this.id}`, {filter})
.then(res => this.entity = res.data);
.then(res => {
this.entity = res.data;
this.invoiceIn.amount = res.data.invoiceInDueDay.reduce(
(accumulator, currentValue) => {
return accumulator + (currentValue['amount'] || 0);
}, 0);
});
}
checkToBook() {

View File

@ -12,12 +12,25 @@ describe('vnInvoiceInDescriptor', () => {
controller = $componentController('vnInvoiceInDescriptor', {$element});
controller.invoiceIn = {id: 1};
$httpBackend.when('GET', `InvoiceIns/${controller.invoiceIn.id}`).respond({id: 1});
}));
describe('loadData()', () => {
it(`should perform a get query to store the invoice in data into the controller`, () => {
expect(controller.invoiceIn).toEqual({id: 1});
const invoiceIn = {
id: 1,
invoiceInDueDay: [
{amount: 1},
{amount: 2}
]
};
const expectedAmount = invoiceIn.invoiceInDueDay[0].amount + invoiceIn.invoiceInDueDay[1].amount;
$httpBackend.when('GET', `InvoiceIns/${controller.invoiceIn.id}`).respond(invoiceIn);
controller.loadData();
$httpBackend.flush();
expect(controller.invoiceIn.id).toEqual(invoiceIn.id);
expect(controller.invoiceIn.amount).toEqual(expectedAmount);
});
});

View File

@ -90,7 +90,7 @@ describe('fixed price filter()', () => {
}
});
it('should return no results filtering by hasMinPrice', async() => {
it('should return 1 result filtering by hasMinPrice', async() => {
const tx = await models.FixedPrice.beginTransaction({});
try {
@ -103,7 +103,7 @@ describe('fixed price filter()', () => {
};
const result = await models.FixedPrice.filter(ctx, null, options);
expect(result.length).toEqual(0);
expect(result.length).toEqual(1);
await tx.rollback();
} catch (e) {

View File

@ -3,8 +3,8 @@
url="FixedPrices/filter"
limit="20"
data="prices"
auto-load="true"
order="itemFk">
order="itemFk"
auto-load="false">
</vn-crud-model>
<vn-crud-model
auto-load="true"
@ -18,147 +18,166 @@
panel="vn-fixed-price-search-panel"
info="Search prices by item ID or code"
placeholder="Search fixed prices"
filter="{}"
model="model">
</vn-searchbar>
</vn-portal>
<div class="vn-w-lg">
<div class="vn-w-xl">
<vn-card>
<vn-table model="model">
<vn-thead>
<vn-tr>
<vn-th field="itemFk" shrink>Item ID</vn-th>
<vn-th field="itemFk">Description</vn-th>
<vn-th field="warehouseFk">Warehouse</vn-th>
<vn-th field="rate2">P.P.U.</vn-th>
<vn-th field="rate3">P.P.P.</vn-th>
<vn-th field="minPrice">Min price</vn-th>
<vn-th field="started" style="width: 90px">Started</vn-th>
<vn-th field="ended" style="width: 90px">Ended</vn-th>
<vn-th shrink></vn-th>
</vn-tr>
</vn-thead>
<vn-tbody>
<vn-tr ng-repeat="price in prices">
<vn-td shrink>
<span
ng-if="price.itemFk"
ng-click="itemDescriptor.show($event, price.itemFk)"
class="link">
{{price.itemFk}}
</span>
<vn-autocomplete
class="dense"
ng-if="!price.itemFk"
vn-focus
url="Items/withName"
ng-model="price.itemFk"
show-field="name"
value-field="id"
search-function="$ctrl.itemSearchFunc($search)"
on-change="$ctrl.upsertPrice(price)"
order="id DESC"
tabindex="1">
<tpl-item>
{{::id}} - {{::name}}
</tpl-item>
</vn-autocomplete>
</vn-td>
<vn-td vn-fetched-tags>
<div>
<vn-one title="{{price.name}}">{{price.name}}</vn-one>
<vn-one ng-if="price.subName">
<h3 title="{{price.subName}}">{{price.subName}}</h3>
</vn-one>
</div>
<vn-fetched-tags
max-length="6"
item="price"
tabindex="-1">
</vn-fetched-tags>
</vn-td>
<vn-td>
<vn-autocomplete
vn-one
label="Warehouse"
ng-model="price.warehouseFk"
url="Warehouses"
on-change="$ctrl.upsertPrice(price)"
tabindex="2">
</vn-autocomplete>
</vn-td>
<vn-td-editable number>
<text>{{price.rate2 | currency: 'EUR':2}}</text>
<field>
<vn-input-number
class="dense"
vn-focus
ng-model="price.rate2"
on-change="$ctrl.upsertPrice(price)">
</vn-input-number>
</field>
</vn-td-editable>
<vn-td-editable number>
<text>{{price.rate3 | currency: 'EUR':2}}</text>
<field>
<vn-input-number
class="dense"
vn-focus
ng-model="price.rate3"
on-change="$ctrl.upsertPrice(price)">
</vn-input-number>
</field>
</vn-td-editable>
<vn-td-editable number>
<text>{{(price.hasMinPrice ? (price.minPrice | currency: 'EUR':2) : "-")}}</text>
<field>
<vn-input-number
class="dense"
vn-focus
ng-model="price.minPrice"
on-change="$ctrl.upsertPrice(price)"
step="0.01">
</vn-input-number>
</field>
</vn-td-editable>
<vn-td>
<vn-date-picker
vn-one
label="Started"
ng-model="price.started"
on-change="$ctrl.upsertPrice(price)">
</vn-date-picker>
</vn-td>
<vn-td>
<vn-date-picker
vn-one
label="Ended"
ng-model="price.ended"
on-change="$ctrl.upsertPrice(price)">
</vn-date-picker>
</vn-td>
<vn-td shrink>
<vn-icon-button
icon="delete"
vn-tooltip="Delete"
ng-click="deleteFixedPrice.show({$index})">
</vn-icon-button>
</vn-td>
</vn-tr>
</vn-tbody>
</vn-table>
<div class="vn-pa-md">
<vn-icon-button
vn-tooltip="Add fixed price"
icon="add_circle"
vn-bind="+"
ng-click="model.insert()">
</vn-icon-button>
</div>
<vn-pagination
<smart-table
model="model"
class="vn-pt-md">
</vn-pagination>
options="$ctrl.smartTableOptions"
expr-builder="$ctrl.exprBuilder(param, value)">
<slot-table>
<table>
<thead>
<tr>
<th field="itemFk">
<span translate>Item ID</span>
</th>
<th field="itemName">
<span translate>Description</span>
</th>
<th field="warehouseFk">
<span translate>Warehouse</span>
</th>
<th
field="rate2"
vn-tooltip="Price By Unit">
<span translate>P.P.U.</span>
</th>
<th
field="rate3"
vn-tooltip="Price By Package">
<span translate>P.P.P.</span>
</th>
<th field="minPrice">
<span translate>Min price</span>
</th>
<th field="started">
<span translate>Started</span>
</th>
<th field="ended">
<span translate>Ended</span>
</th>
<th shrink></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="price in prices">
<td shrink-field>
<vn-autocomplete
vn-focus
class="dense"
url="Items/withName"
ng-model="price.itemFk"
show-field="name"
value-field="id"
search-function="$ctrl.itemSearchFunc($search)"
on-change="$ctrl.upsertPrice(price)"
order="id DESC"
tabindex="1">
<tpl-item>
<div>{{id}}</div>
<div class="text-caption text-secondary">
{{name}}
</div>
</tpl-item>
</vn-autocomplete>
</td>
<td vn-fetched-tags>
<div>
<span
vn-one
ng-if="price.itemFk"
ng-click="itemDescriptor.show($event, price.itemFk)"
class="link">
{{price.name}}
</span>
<vn-one ng-if="price.subName">
<h3 title="{{price.subName}}">{{price.subName}}</h3>
</vn-one>
</div>
<vn-fetched-tags
max-length="6"
item="price"
tabindex="-1">
</vn-fetched-tags>
</td>
<td shrink-field-expand>
<vn-autocomplete
vn-one
ng-model="price.warehouseFk"
data="warehouses"
on-change="$ctrl.upsertPrice(price)"
tabindex="2">
</vn-autocomplete>
</td>
<td shrink-field>
<vn-input-number
ng-model="price.rate2"
on-change="$ctrl.upsertPrice(price)"
step="0.01">
</vn-input-number>
</td>
<td shrink-field>
<vn-input-number
ng-model="price.rate3"
on-change="$ctrl.upsertPrice(price)"
step="0.01">
</vn-input-number>
</td>
<td shrink-field-expand class="minPrice">
<vn-check
vn-one
ng-model="price.hasMinPrice">
</vn-check>
<vn-input-number
disabled="!price.hasMinPrice"
ng-model="price.minPrice"
on-change="$ctrl.upsertPrice(price)"
step="0.01">
</vn-input-number>
</td>
<td shrink-date>
<vn-date-picker
vn-one
ng-model="price.started"
on-change="$ctrl.upsertPrice(price)">
</vn-date-picker>
</td>
<td shrink-date>
<vn-date-picker
vn-one
ng-model="price.ended"
on-change="$ctrl.upsertPrice(price)">
</vn-date-picker>
</td>
<td shrink>
<vn-icon-button
icon="delete"
vn-tooltip="Delete"
ng-click="deleteFixedPrice.show({$index})">
</vn-icon-button>
</td>
</tr>
</tbody>
</table>
<div class="vn-pa-md">
<vn-icon-button
vn-tooltip="Add fixed price"
icon="add_circle"
vn-bind="+"
ng-click="$ctrl.add()">
</vn-icon-button>
</div>
<vn-pagination
model="model"
class="vn-pt-md"
scroll-selector="vn-item-price-fixed vn-table"
scroll-offset="100">
</vn-pagination>
</slot-table>
</smart-table>
</vn-card>
</div>
<vn-item-descriptor-popover

View File

@ -5,13 +5,69 @@ import './style.scss';
export default class Controller extends Section {
constructor($element, $) {
super($element, $);
this.smartTableOptions = {
activeButtons: {
search: true
},
defaultSearch: true,
columns: [
{
field: 'itemName',
autocomplete: {
url: 'Items',
showField: 'name',
valueField: 'id'
}
},
{
field: 'warehouseFk',
autocomplete: {
url: 'Warehouses',
showField: 'name',
valueField: 'id',
}
},
{
field: 'started',
searchable: false
},
{
field: 'ended',
searchable: false
}
]
};
}
/**
* Inserts a new instance
*/
add() {
this.$.model.insert({});
if (!this.$.model.data || this.$.model.data.length == 0) {
this.$.model.data = [];
this.$.model.proxiedData = [];
this.$.model.insert({});
return;
}
const lastIndex = this.$.model.data.length - 1;
const lastItem = this.$.model.data[lastIndex];
this.$.model.insert({
itemFk: lastItem.itemFk,
name: lastItem.name,
subName: lastItem.subName,
value5: lastItem.value5,
value6: lastItem.value6,
value7: lastItem.value7,
value8: lastItem.value8,
value9: lastItem.value9,
value10: lastItem.value10,
warehouseFk: lastItem.warehouseFk,
rate2: lastItem.rate2,
rate3: lastItem.rate3,
hasMinPrice: lastItem.hasMinPrice,
minPrice: lastItem.minPrice,
started: lastItem.started,
ended: lastItem.ended,
});
}
upsertPrice(price) {
@ -46,6 +102,22 @@ export default class Controller extends Section {
? {id: $search}
: {name: {like: '%' + $search + '%'}};
}
exprBuilder(param, value) {
switch (param) {
case 'itemName':
return {'i.id': value};
case 'itemFk':
case 'warehouseFk':
case 'rate2':
case 'rate3':
param = `fp.${param}`;
return {[param]: value};
case 'minPrice':
param = `i.${param}`;
return {[param]: value};
}
}
}
ngModule.vnComponent('vnFixedPrice', {

View File

@ -55,6 +55,8 @@ describe('fixed price', () => {
jest.spyOn(controller.vnApp, 'showSuccess');
jest.spyOn(controller.$.model, 'remove');
$httpBackend.expectGET('Warehouses').respond();
controller.removePrice($index);
expect(controller.vnApp.showSuccess).not.toHaveBeenCalled();

View File

@ -2,4 +2,6 @@ Fixed prices: Precios fijados
Search prices by item ID or code: Buscar por ID de artículo o código
Search fixed prices: Buscar precios fijados
Add fixed price: Añadir precio fijado
This row will be removed: Esta linea se eliminará
This row will be removed: Esta linea se eliminará
Price By Unit: Precio Por Unidad
Price By Package: Precio Por Paquete

View File

@ -1,5 +1,20 @@
@import "variables";
smart-table table{
[shrink-field]{
width: 80px;
max-width: 80px;
}
[shrink-field-expand]{
width: 150px;
max-width: 150px;
}
}
vn-table vn-date-picker {
max-width: 90px;
.minPrice {
align-items: center;
text-align: center;
vn-input-number {
width: 90px;
max-width: 90px;
}
}

View File

@ -40,7 +40,8 @@ module.exports = Self => {
IFNULL(sc.workerSubstitute, c.salesPersonFk) AS salesPersonFk,
c.id AS clientFk,
c.name AS clientName,
s.lastUpdate AS dated,
TIME(v.stamp) AS hour,
DATE(v.stamp) AS dated,
wtc.workerFk
FROM hedera.userSession s
JOIN hedera.visitUser v ON v.id = s.userVisitFk

View File

@ -2,7 +2,8 @@
vn-id="model"
url="SalesMonitors/clientsFilter"
limit="6"
order="dated DESC"
filter="$ctrl.filter"
order="dated DESC, hour DESC"
auto-load="true">
</vn-crud-model>
<vn-horizontal class="header">
@ -15,87 +16,85 @@
vn-tooltip="Minimize/Maximize"
ng-click="$ctrl.main.toggle()">
</vn-icon>
<vn-icon
icon="refresh"
vn-tooltip="Refresh"
ng-click="model.refresh()">
</vn-icon>
</vn-none>
</vn-horizontal>
<vn-card vn-id="card">
<vn-table model="model" class="scrollable sm">
<vn-thead>
<vn-tr>
<vn-th field="dated">Hour</vn-th>
<vn-th field="salesPersonFk" class="expendable">Salesperson</vn-th>
<vn-th field="clientFk">Client</vn-th>
</vn-tr>
</vn-thead>
<vn-tbody>
<vn-tr ng-repeat="visit in model.data">
<vn-td shrink-date>
<span class="chip">
{{::visit.dated | date: 'HH:mm'}}
</span>
</vn-td>
<vn-td class="shrink expendable">
<span
title="{{::visit.salesPerson}}"
vn-click-stop="workerDescriptor.show($event, visit.salesPersonFk)"
class="link">
{{::visit.salesPerson | dashIfEmpty}}
</span>
</vn-td>
<vn-td>
<span
title="{{::visit.clientName}}"
vn-click-stop="clientDescriptor.show($event, visit.clientFk)"
class="link">
{{::visit.clientName}}
</span>
</vn-td>
</vn-tr>
</vn-tbody>
</vn-table>
<vn-pagination
model="model"
class="vn-pt-xs"
scroll-selector="vn-monitor-sales-clients vn-table"
scroll-offset="100">
</vn-pagination>
<smart-table
model="model"
options="$ctrl.smartTableOptions"
expr-builder="$ctrl.exprBuilder(param, value)"
class="scrollable sm">
<slot-actions>
<vn-horizontal>
<vn-date-picker
class="vn-pa-xs"
label="From"
ng-model="$ctrl.dateFrom"
on-change="$ctrl.addFilterDate()">
</vn-date-picker>
<vn-date-picker
class="vn-pa-xs"
label="To"
ng-model="$ctrl.dateTo"
on-change="$ctrl.addFilterDate()">
</vn-date-picker>
</vn-horizontal>
</slot-actions>
<slot-table>
<table>
<thead>
<tr>
<th field="dated">
<span translate>Date</span>
</th>
<th field="hour">
<span translate>Hour</span>
</th>
<th field="salesPersonFk" class="expendable">
<span translate>Salesperson</span>
</th>
<th field="clientFk">
<span translate>Client</span>
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="visit in model.data">
<td shrink-date>
<span class="chip">
{{::visit.dated | date:'dd/MM/yy'}}
</span>
</td>
<td shrink-date>
<span class="chip">
{{::visit.hour | date: 'HH:mm'}}
</span>
</td>
<td class="shrink expendable">
<span
title="{{::visit.salesPerson}}"
vn-click-stop="workerDescriptor.show($event, visit.salesPersonFk)"
class="link">
{{::visit.salesPerson | dashIfEmpty}}
</span>
</td>
<td>
<span
title="{{::visit.clientName}}"
vn-click-stop="clientDescriptor.show($event, visit.clientFk)"
class="link">
{{::visit.clientName}}
</span>
</td>
</tr>
</tbody>
<table>
<slot-table>
</smart-table>
</vn-card>
<vn-worker-descriptor-popover
vn-id="workerDescriptor">
</vn-worker-descriptor-popover>
<vn-client-descriptor-popover
vn-id="clientDescriptor">
</vn-client-descriptor-popover>
<vn-contextmenu vn-id="contextmenu" targets="['vn-monitor-sales-clients vn-table']" model="model"
expr-builder="$ctrl.exprBuilder(param, value)">
<slot-menu>
<vn-item translate
ng-if="contextmenu.isFilterAllowed()"
ng-click="contextmenu.filterBySelection()">
Filter by selection
</vn-item>
<vn-item translate
ng-if="contextmenu.isFilterAllowed()"
ng-click="contextmenu.excludeSelection()">
Exclude selection
</vn-item>
<vn-item translate
ng-if="contextmenu.isFilterAllowed()"
ng-click="contextmenu.removeFilter()">
Remove filter
</vn-item>
<vn-item translate
ng-click="contextmenu.removeAllFilters()">
Remove all filters
</vn-item>
<vn-item translate
ng-if="contextmenu.isActionAllowed()"
ng-click="contextmenu.copyValue()">
Copy value
</vn-item>
</slot-menu>
</vn-contextmenu>
</vn-client-descriptor-popover>

View File

@ -2,26 +2,89 @@ import ngModule from '../../module';
import Section from 'salix/components/section';
export default class Controller extends Section {
constructor($element, $) {
super($element, $);
const date = new Date();
this.dateFrom = date;
this.dateTo = date;
this.filter = {
where: {
'v.stamp': {
between: this.dateRange()
}
}
};
this.smartTableOptions = {
activeButtons: {
search: true
},
columns: [
{
field: 'clientFk',
autocomplete: {
url: 'Clients',
showField: 'name',
valueField: 'id'
}
},
{
field: 'salesPersonFk',
autocomplete: {
url: 'Workers/activeWithInheritedRole',
where: `{role: 'salesPerson'}`,
searchFunction: '{firstName: $search}',
showField: 'nickname',
valueField: 'id',
}
},
{
field: 'dated',
searchable: false
},
{
field: 'hour',
searchable: false
}
]
};
}
exprBuilder(param, value) {
switch (param) {
case 'dated':
return {'s.lastUpdate': {
between: this.dateRange(value)}
};
case 'clientFk':
return {[`c.id`]: value};
case 'salesPersonFk':
return {[`c.${param}`]: value};
}
}
dateRange(value) {
const minHour = new Date(value);
dateRange() {
let from = this.dateFrom;
let to = this.dateTo;
if (!from)
from = new Date();
if (!to)
to = new Date();
const minHour = new Date(from);
minHour.setHours(0, 0, 0, 0);
const maxHour = new Date(value);
const maxHour = new Date(to);
maxHour.setHours(23, 59, 59, 59);
return [minHour, maxHour];
}
addFilterDate() {
this.$.model.filter = {
where: {
'v.stamp': {
between: this.dateRange()
}
}
};
this.$.model.refresh();
}
}
ngModule.vnComponent('vnMonitorSalesClients', {

View File

@ -1,4 +1,6 @@
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
const buildFilter = require('vn-loopback/util/filter').buildFilter;
const mergeFilters = require('vn-loopback/util/filter').mergeFilters;
module.exports = Self => {
Self.remoteMethodCtx('filter', {
@ -9,7 +11,31 @@ module.exports = Self => {
arg: 'filter',
type: 'object',
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
http: {source: 'query'}
},
{
arg: 'search',
type: 'string',
description: `If it's and integer searchs by invoiceInFk, otherwise it searchs by the supplierName`,
},
{
arg: 'agencyModeFk',
type: 'integer',
description: 'The agency agencyModeFk id',
},
{
arg: 'agencyFk',
type: 'integer',
description: 'The agencyFk id',
},
{
arg: 'from',
type: 'date',
description: 'The from date filter',
},
{
arg: 'to',
type: 'date',
description: 'The to date filter',
}
],
returns: {
@ -29,6 +55,25 @@ module.exports = Self => {
if (typeof options == 'object')
Object.assign(myOptions, options);
const where = buildFilter(ctx.args, (param, value) => {
switch (param) {
case 'search':
return /^\d+$/.test(value)
? {'invoiceInFk': {inq: value}}
: {'supplierName': {like: `%${value}%`}};
case 'agencyModeFk':
return {'agencyModeFk': value};
case 'agencyFk':
return {'agencyFk': value};
case 'from':
return {'created': {gte: value}};
case 'to':
return {'created': {lte: value}};
}
});
filter = mergeFilters(filter, {where});
const stmts = [];
const stmt = new ParameterizedSQL(
`SELECT *
@ -61,7 +106,8 @@ module.exports = Self => {
) a`
);
stmt.merge(conn.makeSuffix(filter));
stmt.merge(conn.makeWhere(filter.where));
stmt.merge(conn.makePagination(filter));
const agencyTerm = stmts.push(stmt) - 1;
const sql = ParameterizedSQL.join(stmts, ';');

View File

@ -1,9 +1,12 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('AgencyTerm filter()', () => {
const authUserId = 9;
const today = new Date();
today.setHours(2, 0, 0, 0);
it('should return all the tickets matching the filter', async() => {
it('should return all results matching the filter', async() => {
const tx = await models.AgencyTerm.beginTransaction({});
try {
@ -23,4 +26,84 @@ describe('AgencyTerm filter()', () => {
throw e;
}
});
it('should return results matching "search" searching by integer', async() => {
let ctx = {
args: {
search: 1,
}
};
let result = await app.models.AgencyTerm.filter(ctx);
expect(result.length).toEqual(1);
expect(result[0].routeFk).toEqual(1);
});
it('should return results matching "search" searching by string', async() => {
let ctx = {
args: {
search: 'Plants SL',
}
};
let result = await app.models.AgencyTerm.filter(ctx);
expect(result.length).toEqual(2);
});
it('should return results matching "from" and "to"', async() => {
const tx = await models.Buy.beginTransaction({});
const options = {transaction: tx};
try {
const from = new Date();
from.setHours(0, 0, 0, 0);
const to = new Date();
to.setHours(23, 59, 59, 999);
const ctx = {
args: {
from: from,
to: to
}
};
const results = await models.AgencyTerm.filter(ctx, options);
expect(results.length).toBe(3);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return results matching "agencyModeFk"', async() => {
let ctx = {
args: {
agencyModeFk: 1,
}
};
let result = await app.models.AgencyTerm.filter(ctx);
expect(result.length).toEqual(1);
expect(result[0].routeFk).toEqual(1);
});
it('should return results matching "agencyFk"', async() => {
let ctx = {
args: {
agencyFk: 2,
}
};
let result = await app.models.AgencyTerm.filter(ctx);
expect(result.length).toEqual(1);
expect(result[0].routeFk).toEqual(2);
});
});

View File

@ -1,4 +1,5 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('Route filter()', () => {
let today = new Date();
@ -17,29 +18,33 @@ describe('Route filter()', () => {
expect(result[0].id).toEqual(1);
});
// #1428 cuadrar formato de horas
xit('should return the routes matching "from"', async() => {
let ctx = {
args: {
from: today,
}
};
it('should return results matching "from" and "to"', async() => {
const tx = await models.Buy.beginTransaction({});
const options = {transaction: tx};
let result = await app.models.Route.filter(ctx);
try {
const from = new Date();
from.setHours(0, 0, 0, 0);
expect(result.length).toEqual(7);
});
const to = new Date();
to.setHours(23, 59, 59, 999);
it('should return the routes matching "to"', async() => {
let ctx = {
args: {
to: today,
}
};
const ctx = {
args: {
from: from,
to: to
}
};
let result = await app.models.Route.filter(ctx);
const results = await models.Route.filter(ctx, options);
expect(result.length).toEqual(7);
expect(results.length).toBe(7);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should return the routes matching "m3"', async() => {

View File

@ -0,0 +1,47 @@
<div class="search-panel">
<form id="manifold-form" ng-submit="$ctrl.onSearch()">
<vn-horizontal class="vn-px-lg vn-pt-lg">
<vn-textfield
vn-one
label="General search"
ng-model="filter.search"
vn-focus>
</vn-textfield>
</vn-horizontal>
<vn-horizontal class="vn-px-lg">
<vn-autocomplete vn-one
url="AgencyModes"
label="Agency route"
show-field="name"
value-field="id"
ng-model="filter.agencyModeFk">
</vn-autocomplete>
<vn-autocomplete vn-one
url="Agencies"
label="Agency Agreement"
show-field="name"
value-field="id"
ng-model="filter.agencyFk">
</vn-autocomplete>
</vn-horizontal>
<section class="vn-px-md">
<vn-horizontal class="manifold-panel vn-pa-md">
<vn-date-picker
vn-one
label="From"
ng-model="filter.from"
on-change="$ctrl.from = value">
</vn-date-picker>
<vn-date-picker
vn-one
label="To"
ng-model="filter.to"
on-change="$ctrl.to = value">
</vn-date-picker>
</vn-horizontal>
</section>
<vn-horizontal class="vn-px-lg vn-pb-lg vn-mt-lg">
<vn-submit label="Search"></vn-submit>
</vn-horizontal>
</form>
</div>

View File

@ -0,0 +1,17 @@
import ngModule from '../module';
import SearchPanel from 'core/components/searchbar/search-panel';
class Controller extends SearchPanel {
get filter() {
return this.$.filter;
}
set filter(value = {}) {
this.$.filter = value;
}
}
ngModule.vnComponent('vnAgencyTermSearchPanel', {
template: require('./index.html'),
controller: Controller
});

View File

@ -0,0 +1,2 @@
Search by invoiceIn id or autonomous name: Buscar por id de recibida o por nombre de autónomo
Search autonomous: Buscar autónomos

View File

@ -1,10 +1,19 @@
<vn-crud-model
vn-id="model"
url="AgencyTerms/filter"
filter="::$ctrl.filter"
data="agencyTerms"
auto-load="true">
</vn-crud-model>
<vn-portal slot="topbar">
<vn-searchbar
auto-state="false"
panel="vn-agency-term-search-panel"
info="Search by invoiceIn id or autonomous name"
placeholder="Search autonomous"
filter="{}"
model="model">
</vn-searchbar>
</vn-portal>
<vn-card>
<smart-table
model="model"
@ -36,10 +45,10 @@
<th field="created">
<span translate>Date</span>
</th>
<th field="agencyFk">
<th field="agencyModeFk">
<span translate>Agency route</span>
</th>
<th field="agencyAgreement">
<th field="agencyFk">
<span translate>Agency Agreement</span>
</th>
<th field="packages">

View File

@ -12,19 +12,19 @@ class Controller extends Section {
},
columns: [
{
field: 'agencyFk',
field: 'agencyModeFk',
autocomplete: {
url: 'AgencyModes',
showField: 'name',
valueField: 'name'
valueField: 'id'
}
},
{
field: 'agencyAgreement',
field: 'agencyFk',
autocomplete: {
url: 'Agencies',
showField: 'name',
valueField: 'name'
valueField: 'id'
}
},
{
@ -41,14 +41,14 @@ class Controller extends Section {
exprBuilder(param, value) {
switch (param) {
case 'agencyFk':
return {'a.agencyModeName': value};
case 'agencyModeFk':
return {'a.agencyModeFk': value};
case 'supplierFk':
return {'a.supplierName': value};
case 'routeFk':
return {'a.routeFk': value};
case 'created':
case 'agencyAgreement':
case 'agencyFk':
case 'packages':
case 'm3':
case 'kmTotal':

View File

@ -13,4 +13,5 @@ import './log';
import './tickets';
import './agency-term/index';
import './agency-term/createInvoiceIn';
import './agency-term-search-panel';
import './ticket-popup';

View File

@ -1,8 +1,7 @@
const models = require('vn-loopback/server/server').models;
const soap = require('soap');
// #3673 sendSms tests excluded
xdescribe('ticket sendSms()', () => {
describe('ticket sendSms()', () => {
it('should send a message and log it', async() => {
const tx = await models.Ticket.beginTransaction({});

View File

@ -28,8 +28,8 @@ describe('ticket setDeleted()', () => {
expect(error.message).toEqual('You must delete the claim id %d first');
});
it('should delete the ticket, remove the stowaway link and change the stowaway ticket state to "FIXING" and get rid of the itemshelving', async() => {
// test excluded by task #3693
xit('should delete the ticket, remove the stowaway link and change the stowaway ticket state to "FIXING" and get rid of the itemshelving', async() => {
const tx = await models.Ticket.beginTransaction({});
try {

View File

@ -21,7 +21,7 @@
<vn-list>
<vn-item
ng-if="!$ctrl.hasDocuwareFile"
ng-click="$ctrl.showPdfDeliveryNote()"
ng-click="$ctrl.showPdfDeliveryNote('deliveryNote')"
translate>
as PDF
</vn-item>
@ -44,7 +44,6 @@
vn-click-stop="sendDeliveryNoteMenu.show($event, 'left')"
translate>
Send Delivery Note...
<vn-menu vn-id="sendDeliveryNoteMenu">
<vn-list>
<vn-item
@ -60,6 +59,11 @@
</vn-list>
</vn-menu>
</vn-item>
<vn-item
ng-click="$ctrl.showPdfDeliveryNote('proforma')"
translate>
Show Proforma
</vn-item>
<vn-item
ng-click="deleteConfirmation.show()"
ng-show="$ctrl.isEditable"

View File

@ -116,10 +116,11 @@ class Controller extends Section {
});
}
showPdfDeliveryNote() {
showPdfDeliveryNote(type) {
this.vnReport.show('delivery-note', {
recipientId: this.ticket.client.id,
ticketId: this.id,
type: type
});
}

View File

@ -122,14 +122,15 @@ describe('Ticket Component vnTicketDescriptorMenu', () => {
describe('showPdfDeliveryNote()', () => {
it('should open a new window showing a delivery note PDF document', () => {
jest.spyOn(window, 'open').mockReturnThis();
const type = 'deliveryNote';
const expectedParams = {
ticketId: ticket.id,
recipientId: ticket.client.id
recipientId: ticket.client.id,
type: type
};
const serializedParams = $httpParamSerializer(expectedParams);
const expectedPath = `api/report/delivery-note?${serializedParams}`;
controller.showPdfDeliveryNote();
controller.showPdfDeliveryNote(type);
expect(window.open).toHaveBeenCalledWith(expectedPath);
});

View File

@ -5,4 +5,5 @@ as CSV: como CSV
Send PDF: Enviar PDF
Send CSV: Enviar CSV
Send CSV Delivery Note: Enviar albarán en CSV
Send PDF Delivery Note: Enviar albarán en PDF
Send PDF Delivery Note: Enviar albarán en PDF
Show Proforma: Ver proforma

View File

@ -10,13 +10,13 @@ describe('department moveChild()', () => {
it('should move a child department to a new parent', async() => {
const childId = 22;
const parentId = 1;
const parentId = 37;
const child = await app.models.Department.findById(childId);
expect(child.parentFk).toBeNull();
expect(child.parentFk).toEqual(1);
updatedChild = await app.models.Department.moveChild(childId, parentId);
expect(updatedChild.parentFk).toEqual(1);
expect(updatedChild.parentFk).toEqual(37);
});
});

View File

@ -12,6 +12,6 @@ describe('Worker getWorkedHours()', () => {
const [result] = await models.Worker.getWorkedHours(workerID, started, ended);
expect(result.expectedHours).toEqual(28800); // 8:00 hours in seconds
expect(result.workedHours).toEqual(29400); // 8:10 hours in seconds
expect(result.workedHours).toEqual(28200); // 7:50 hours in seconds
});
});

View File

@ -78,8 +78,9 @@
<h3>{{client.name}}</h3>
</div>
</div>
<p v-html="$t('sections.agency.description')"></p>
<p>{{claimConfig.pickupContact}}</p>
</div>
</div>
<!-- Footer block -->

View File

@ -7,6 +7,7 @@ module.exports = {
async serverPrefetch() {
this.client = await this.fetchClient(this.claimId);
this.sales = await this.fetchSales(this.claimId);
this.claimConfig = await this.fetchClaimConfig();
if (!this.client)
throw new Error('Something went wrong');
@ -25,6 +26,9 @@ module.exports = {
fetchSales(claimId) {
return this.rawSqlFromDef('sales', [claimId]);
},
fetchClaimConfig() {
return this.findOneFromDef('claimConfig');
},
},
components: {
'report-header': reportHeader.build(),

View File

@ -14,4 +14,4 @@ phone: Teléfono
sections:
agency:
description: 'Para agilizar su recogida, por favor, póngase en contacto con la oficina
de Logista Parcel. <br/> Tlf: 96 166 77 88 - Ana Gómez (Ext. 2113) <em>(atcsalidas.i2valencia@integra2.es)</em>'
de Logista Parcel.'

View File

@ -0,0 +1,2 @@
SELECT pickupContact
FROM claimConfig;

View File

@ -15,7 +15,7 @@
<div class="columns">
<div class="size50">
<div class="size75 vn-mt-ml">
<h1 class="title uppercase">{{$t('title')}}</h1>
<h1 class="title uppercase">{{$t(type)}}</h1>
<table class="row-oriented ticket-info">
<tbody>
<tr>
@ -23,7 +23,7 @@
<th>{{client.id}}</th>
</tr>
<tr>
<td class="font gray uppercase">{{$t('ticketId')}}</td>
<td class="font gray uppercase">{{$t(type)}}</td>
<th>{{ticket.id}}</th>
</tr>
<tr>
@ -281,7 +281,7 @@
<!-- Footer block -->
<report-footer id="pageFooter"
v-bind:company-code="ticket.companyCode"
v-bind:left-text="$t('ticket', [ticket.id])"
v-bind:left-text="footerType"
v-bind:center-text="client.socialName"
v-bind="$props">
</report-footer>

View File

@ -44,6 +44,10 @@ module.exports = {
});
return total;
},
footerType() {
const translatedType = this.$t(this.type);
return `${translatedType} ${this.ticketId}`;
}
},
methods: {
@ -119,6 +123,10 @@ module.exports = {
ticketId: {
type: [Number, String],
required: true
},
type: {
type: String,
required: true
}
}
};

View File

@ -1,6 +1,6 @@
reportName: delivery-note
title: Delivery note
ticketId: Delivery note
deliveryNote: Delivery note
proforma: Proforma
clientId: Client
deliveryAddress: Delivery address
fiscalData: Fiscal data
@ -17,7 +17,6 @@ total: Total
subtotal: Subtotal
vatType: VAT Type
digitalSignature: Digital signature
ticket: Delivery note {0}
plantPassport: Plant passport
packages: Packages
services:

View File

@ -1,6 +1,6 @@
reportName: albaran
title: Albarán
ticketId: Albarán
deliveryNote: Albarán
proforma: Proforma
clientId: Cliente
deliveryAddress: Dirección de entrega
fiscalData: Datos fiscales

View File

@ -1,6 +1,6 @@
reportName: bon-de-livraison
title: Bon de livraison
ticketId: BL
deliveryNote: Bon de livraison
proforma: Proforma
clientId: Client
deliveryAddress: Adresse de livraison
fiscalData: Coordonnées

View File

@ -1,6 +1,6 @@
reportName: nota-de-entrega
title: Nota de Entrega
ticketId: Nota de Entrega
deliveryNote: Nota de Entrega
proforma: Proforma
clientId: Cliente
deliveryAddress: Morada de Entrega
fiscalData: Dados Fiscais