Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 2245-ticket_component
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
This commit is contained in:
commit
174cea7bc3
|
@ -2,6 +2,9 @@
|
|||
"Account": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"AccountingType": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"Bank": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"name": "AccountingType",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "accountingType"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
"description": {
|
||||
"type": "String",
|
||||
"required": true
|
||||
},
|
||||
"receiptDescription": {
|
||||
"type": "String",
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
"acls": [{
|
||||
"accessType": "READ",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$everyone",
|
||||
"permission": "ALLOW"
|
||||
}]
|
||||
}
|
|
@ -2,39 +2,49 @@
|
|||
"name": "Bank",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "bank"
|
||||
}
|
||||
"mysql": {
|
||||
"table": "bank"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
"bank": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"account": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"cash": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"entityFk": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"isActive": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"currencyFk": {
|
||||
"type": "string",
|
||||
"required": true
|
||||
}
|
||||
"id": {
|
||||
"type": "Number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
"bank": {
|
||||
"type": "String",
|
||||
"required": true
|
||||
},
|
||||
"account": {
|
||||
"type": "String",
|
||||
"required": true
|
||||
},
|
||||
"accountingTypeFk": {
|
||||
"type": "Number",
|
||||
"required": true,
|
||||
"mysql": {
|
||||
"columnName": "cash"
|
||||
}
|
||||
},
|
||||
"entityFk": {
|
||||
"type": "Number",
|
||||
"required": true
|
||||
},
|
||||
"isActive": {
|
||||
"type": "Boolean",
|
||||
"required": true
|
||||
},
|
||||
"currencyFk": {
|
||||
"type": "Number",
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
"accountingType": {
|
||||
"type": "belongsTo",
|
||||
"model": "AccountingType",
|
||||
"foreignKey": "accountingTypeFk"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -55,8 +55,9 @@ module.exports = Self => {
|
|||
};
|
||||
|
||||
await fs.mkdir(dstDir, {recursive: true});
|
||||
await sharp(srcFilePath)
|
||||
await sharp(srcFilePath, {failOnError: false})
|
||||
.resize(collection.maxWidth, collection.maxHeight, resizeOpts)
|
||||
.png()
|
||||
.toFile(dstFile);
|
||||
|
||||
const sizes = collection.sizes();
|
||||
|
@ -69,8 +70,9 @@ module.exports = Self => {
|
|||
};
|
||||
|
||||
await fs.mkdir(dstDir, {recursive: true});
|
||||
await sharp(srcFilePath)
|
||||
await sharp(srcFilePath, {failOnError: false})
|
||||
.resize(size.width, size.height, resizeOpts)
|
||||
.png()
|
||||
.toFile(dstFile);
|
||||
}
|
||||
|
||||
|
@ -88,7 +90,9 @@ module.exports = Self => {
|
|||
);
|
||||
}
|
||||
|
||||
await fs.unlink(srcFilePath);
|
||||
if (fs.existsSync(srcFilePath))
|
||||
await fs.unlink(srcFilePath);
|
||||
|
||||
await tx.commit();
|
||||
return newImage;
|
||||
} catch (e) {
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
|
||||
USE `vn`;
|
||||
DROP procedure IF EXISTS `vn`.`itemLastEntries`;
|
||||
|
||||
DELIMITER $$
|
||||
USE `vn`$$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `itemLastEntries__`(IN `vItem` INT, IN `vDays` DATE)
|
||||
BEGIN
|
||||
SELECT
|
||||
w.id AS warehouseFk,
|
||||
w.name AS warehouse,
|
||||
tr.landed,
|
||||
b.entryFk,
|
||||
b.isIgnored,
|
||||
b.price2,
|
||||
b.price3,
|
||||
b.stickers,
|
||||
b.packing,
|
||||
b.`grouping`,
|
||||
b.groupingMode,
|
||||
b.weight,
|
||||
i.stems,
|
||||
b.quantity,
|
||||
b.buyingValue,
|
||||
b.packageFk ,
|
||||
s.id AS supplierFk,
|
||||
s.name AS supplier
|
||||
FROM itemType it
|
||||
RIGHT JOIN (entry e
|
||||
LEFT JOIN supplier s ON s.id = e.supplierFk
|
||||
RIGHT JOIN buy b ON b.entryFk = e.id
|
||||
LEFT JOIN item i ON i.id = b.itemFk
|
||||
LEFT JOIN ink ON ink.id = i.inkFk
|
||||
LEFT JOIN travel tr ON tr.id = e.travelFk
|
||||
LEFT JOIN warehouse w ON w.id = tr.warehouseInFk
|
||||
LEFT JOIN origin o ON o.id = i.originFk
|
||||
) ON it.id = i.typeFk
|
||||
LEFT JOIN edi.ekt ek ON b.ektFk = ek.id
|
||||
WHERE b.itemFk = vItem And tr.shipped BETWEEN vDays AND DATE_ADD(CURDATE(), INTERVAl + 10 DAY)
|
||||
ORDER BY tr.landed DESC , b.id DESC;
|
||||
END$$
|
||||
|
||||
DELIMITER ;
|
||||
;
|
|
@ -0,0 +1,2 @@
|
|||
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
|
||||
VALUES ('Buy', '*', '*', 'ALLOW', 'ROLE', 'buyer');
|
|
@ -0,0 +1,2 @@
|
|||
ALTER TABLE `vn`.`accountingType`
|
||||
ADD COLUMN `receiptDescription` VARCHAR(50) NULL COMMENT 'Descripción por defecto al crear nuevo recibo' AFTER `description`;
|
|
@ -0,0 +1,119 @@
|
|||
USE `vn`;
|
||||
DROP procedure IF EXISTS `ticket_close`;
|
||||
|
||||
DELIMITER $$
|
||||
USE `vn`$$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `ticket_close`(vTicketFk INT)
|
||||
BEGIN
|
||||
/**
|
||||
* Realiza el cierre de todos los
|
||||
* tickets de la tabla ticketClosure.
|
||||
*
|
||||
* @param vTicketFk Id del ticket
|
||||
*/
|
||||
DECLARE vDone BOOL;
|
||||
DECLARE vClientFk INT;
|
||||
DECLARE vCurTicketFk INT;
|
||||
DECLARE vIsTaxDataChecked BOOL;
|
||||
DECLARE vCompanyFk INT;
|
||||
DECLARE vShipped DATE;
|
||||
DECLARE vNewInvoiceId INT;
|
||||
DECLARE vHasDailyInvoice BOOL;
|
||||
DECLARE vWithPackage BOOL;
|
||||
DECLARE vHasToInvoice BOOL;
|
||||
|
||||
DECLARE cur CURSOR FOR
|
||||
SELECT ticketFk FROM tmp.ticketClosure;
|
||||
|
||||
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
||||
DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN
|
||||
RESIGNAL;
|
||||
END;
|
||||
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.ticketClosure;
|
||||
CREATE TEMPORARY TABLE tmp.ticketClosure
|
||||
SELECT vTicketFk AS ticketFk;
|
||||
|
||||
INSERT INTO tmp.ticketClosure
|
||||
SELECT id FROM stowaway s
|
||||
WHERE s.shipFk = vTicketFk;
|
||||
OPEN cur;
|
||||
|
||||
proc: LOOP
|
||||
SET vDone = FALSE;
|
||||
|
||||
FETCH cur INTO vCurTicketFk;
|
||||
|
||||
IF vDone THEN
|
||||
LEAVE proc;
|
||||
END IF;
|
||||
|
||||
-- ticketClosure start
|
||||
SELECT
|
||||
c.id,
|
||||
c.isTaxDataChecked,
|
||||
t.companyFk,
|
||||
t.shipped,
|
||||
co.hasDailyInvoice,
|
||||
w.isManaged,
|
||||
c.hasToInvoice
|
||||
INTO vClientFk,
|
||||
vIsTaxDataChecked,
|
||||
vCompanyFk,
|
||||
vShipped,
|
||||
vHasDailyInvoice,
|
||||
vWithPackage,
|
||||
vHasToInvoice
|
||||
FROM ticket t
|
||||
JOIN `client` c ON c.id = t.clientFk
|
||||
JOIN province p ON p.id = c.provinceFk
|
||||
JOIN country co ON co.id = p.countryFk
|
||||
JOIN warehouse w ON w.id = t.warehouseFk
|
||||
WHERE t.id = vCurTicketFk;
|
||||
|
||||
INSERT INTO ticketPackaging (ticketFk, packagingFk, quantity)
|
||||
(SELECT vCurTicketFk, p.id, COUNT(*)
|
||||
FROM expedition e
|
||||
JOIN packaging p ON p.itemFk = e.itemFk
|
||||
WHERE e.ticketFk = vCurTicketFk AND p.isPackageReturnable
|
||||
AND vWithPackage
|
||||
GROUP BY p.itemFk);
|
||||
|
||||
-- No retornables o no catalogados
|
||||
INSERT INTO sale (itemFk, ticketFk, concept, quantity, price, isPriceFixed)
|
||||
(SELECT e.itemFk, vCurTicketFk, i.name, COUNT(*) AS amount, getSpecialPrice(e.itemFk, vClientFk), 1
|
||||
FROM expedition e
|
||||
JOIN item i ON i.id = e.itemFk
|
||||
LEFT JOIN packaging p ON p.itemFk = i.id
|
||||
WHERE e.ticketFk = vCurTicketFk AND IFNULL(p.isPackageReturnable, 0) = 0
|
||||
AND getSpecialPrice(e.itemFk, vClientFk) > 0
|
||||
GROUP BY e.itemFk);
|
||||
|
||||
CALL vn.zonePromo_Make();
|
||||
|
||||
IF(vHasDailyInvoice) AND vHasToInvoice THEN
|
||||
|
||||
-- Facturacion rapida
|
||||
CALL ticketTrackingAdd(vCurTicketFk, 'DELIVERED', NULL);
|
||||
-- Facturar si está contabilizado
|
||||
IF vIsTaxDataChecked THEN
|
||||
CALL invoiceOut_newFromClient(
|
||||
vClientFk,
|
||||
(SELECT invoiceSerial(vClientFk, vCompanyFk, 'M')),
|
||||
vShipped,
|
||||
vCompanyFk,
|
||||
NULL,
|
||||
vNewInvoiceId);
|
||||
END IF;
|
||||
ELSE
|
||||
CALL ticketTrackingAdd(vCurTicketFk, (SELECT vn.getAlert3State(vCurTicketFk)), NULL);
|
||||
END IF;
|
||||
END LOOP;
|
||||
|
||||
CLOSE cur;
|
||||
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.ticketClosure;
|
||||
END$$
|
||||
|
||||
DELIMITER ;
|
||||
|
|
@ -116,13 +116,13 @@ INSERT INTO `vn`.`shelving` (`code`, `parkingFk`, `isPrinted`, `priority`, `park
|
|||
('GVC', '1', '0', '1', '0', '106'),
|
||||
('HEJ', '2', '0', '1', '0', '106');
|
||||
|
||||
INSERT INTO `vn`.`accountingType`(`id`, `description`)
|
||||
INSERT INTO `vn`.`accountingType`(`id`, `description`, `receiptDescription`)
|
||||
VALUES
|
||||
(1, 'Digital money'),
|
||||
(2, 'Cash'),
|
||||
(3, 'Card'),
|
||||
(4, 'Stolen Money'),
|
||||
(5, 'Miscellaneous');
|
||||
(1, 'Digital money', ''),
|
||||
(2, 'Cash', 'Cash'),
|
||||
(3, 'Card', 'Pay on receipt'),
|
||||
(4, 'Stolen Money', ''),
|
||||
(5, 'Miscellaneous', '');
|
||||
|
||||
INSERT INTO `vn`.`currency`(`id`, `code`, `name`, `ratio`)
|
||||
VALUES
|
||||
|
@ -133,8 +133,8 @@ INSERT INTO `vn`.`currency`(`id`, `code`, `name`, `ratio`)
|
|||
|
||||
INSERT INTO `vn`.`bank`(`id`, `bank`, `account`, `cash`, `entityFk`, `isActive`, `currencyFk`)
|
||||
VALUES
|
||||
(1, 'Pay on receipt', '0000000000', 4, 0, 1, 1),
|
||||
(2, 'Cash', '1111111111', 1, 0, 1, 1);
|
||||
(1, 'Pay on receipt', '0000000000', 3, 0, 1, 1),
|
||||
(2, 'Cash', '1111111111', 2, 0, 1, 1);
|
||||
|
||||
INSERT INTO `vn`.`deliveryMethod`(`id`, `code`, `description`)
|
||||
VALUES
|
||||
|
@ -586,7 +586,7 @@ INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeF
|
|||
(16, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, CURDATE()),
|
||||
(17, 1, 7, 2, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, CURDATE()),
|
||||
(18, 1, 4, 4, 4, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 108, 'Cerebro', 128, NULL, 0, 12, CURDATE()),
|
||||
(19, 1, 5, 5, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 109, 'Somewhere in Thailand', 129, NULL, 1, 13, CURDATE()),
|
||||
(19, 1, 5, 5, NULL, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 109, 'Somewhere in Thailand', 129, NULL, 1, 13, CURDATE()),
|
||||
(20, 1, 5, 5, 3, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Thailand', 129, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
|
||||
(21, NULL, 5, 5, 5, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Holland', 102, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
|
||||
(22, NULL, 5, 5, 5, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Japan', 103, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
|
||||
|
@ -627,11 +627,11 @@ INSERT INTO `vn`.`ticketTracking`(`ticketFk`, `stateFk`, `workerFk`, `created`)
|
|||
(12, 3, 19, NOW()),
|
||||
(13, 3, 19, NOW()),
|
||||
(14, 3, 19, NOW()),
|
||||
(15, 3, 19, NOW()),
|
||||
(15, 2, 19, NOW()),
|
||||
(16, 3, 19, NOW()),
|
||||
(17, 3, 19, NOW()),
|
||||
(18, 3, 19, NOW()),
|
||||
(19, 3, 19, NOW()),
|
||||
(17, 2, 19, NOW()),
|
||||
(18, 2, 19, NOW()),
|
||||
(19, 2, 19, NOW()),
|
||||
(20, 1, 19, DATE_ADD(NOW(), INTERVAL +1 MONTH)),
|
||||
(21, 1, 19, DATE_ADD(NOW(), INTERVAL +1 MONTH)),
|
||||
(22, 1, 19, DATE_ADD(NOW(), INTERVAL +1 MONTH)),
|
||||
|
@ -759,25 +759,25 @@ INSERT INTO `vn`.`intrastat`(`id`, `description`, `taxClassFk`, `taxCodeFk`)
|
|||
(05080000, 'Coral y materiales similares', 2, 2),
|
||||
(06021010, 'Plantas vivas: Esqueje/injerto, Vid', 1, 1);
|
||||
|
||||
INSERT INTO `vn`.`item`(`id`, `typeFk`, `size`, `inkFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `isOnOffer`, `expenceFk`, `isBargain`, `comment`, `relevancy`, `image`, `taxClassFk`, `subName`)
|
||||
INSERT INTO `vn`.`item`(`id`, `typeFk`, `size`, `inkFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `isOnOffer`, `expenceFk`, `isBargain`, `comment`, `relevancy`, `image`, `taxClassFk`, `subName`, `minPrice`)
|
||||
VALUES
|
||||
(1, 2, 70, 'AMA', 1, 1, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 66540, 1, NULL),
|
||||
(2, 2, 70, 'AZL', 1, 2, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 65540, 1, NULL),
|
||||
(3, 1, 60, 'AMR', 1, 3, NULL, 1, 05080000, 0, 4751000000, 0, NULL, 0, 61692, 1, NULL),
|
||||
(4, 1, 60, 'AMR', 1, 1, NULL, 1, 05080000, 1, 4751000000, 0, NULL, 0, 66090, 2, NULL),
|
||||
(5, 3, 30, 'GRE', 1, 2, NULL, 2, 06021010, 1, 4751000000, 0, NULL, 0, 67350, 2, NULL),
|
||||
(6, 5, 30, 'GRE', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 67350, 2, NULL),
|
||||
(7, 5, 90, 'AZL', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 67350, 2, NULL),
|
||||
(8, 2, 70, 'AMA', 1, 1, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 66540, 1, NULL),
|
||||
(9, 2, 70, 'AZL', 1, 2, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 65540, 1, NULL),
|
||||
(10, 1, 60, 'AMR', 1, 3, NULL, 1, 05080000, 0, 4751000000, 0, NULL, 0, 61692, 1, NULL),
|
||||
(11, 1, 60, 'AMR', 1, 1, NULL, 1, 05080000, 1, 4751000000, 0, NULL, 0, 66090, 2, NULL),
|
||||
(12, 3, 30, 'GRE', 1, 2, NULL, 2, 06021010, 1, 4751000000, 0, NULL, 0, 67350, 2, NULL),
|
||||
(13, 5, 30, 'GRE', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 67350, 2, NULL),
|
||||
(14, 5, 90, 'AZL', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 67350, 2, NULL),
|
||||
(15, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 67350, 2, NULL),
|
||||
(16, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 67350, 2, NULL),
|
||||
(71, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 1, 4751000000, 0, NULL, 0, 67350, 2, NULL);
|
||||
(1, 2, 70, 'AMA', 1, 1, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 67, 1, NULL, 0),
|
||||
(2, 2, 70, 'AZL', 1, 2, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 66, 1, NULL, 0),
|
||||
(3, 1, 60, 'AMR', 1, 3, NULL, 1, 05080000, 0, 4751000000, 0, NULL, 0, 65, 1, NULL, 0),
|
||||
(4, 1, 60, 'AMR', 1, 1, 'Increases block', 1, 05080000, 1, 4751000000, 0, NULL, 0, 69, 2, NULL, 0),
|
||||
(5, 3, 30, 'GRE', 1, 2, NULL, 2, 06021010, 1, 4751000000, 0, NULL, 0, 74, 2, NULL, 0),
|
||||
(6, 5, 30, 'GRE', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 62, 2, NULL, 0),
|
||||
(7, 5, 90, 'AZL', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 64, 2, NULL, 0),
|
||||
(8, 2, 70, 'AMA', 1, 1, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 75, 1, NULL, 0),
|
||||
(9, 2, 70, 'AZL', 1, 2, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 76, 1, NULL, 0),
|
||||
(10, 1, 60, 'AMR', 1, 3, NULL, 1, 05080000, 0, 4751000000, 0, NULL, 0, 77, 1, NULL, 0),
|
||||
(11, 1, 60, 'AMR', 1, 1, NULL, 1, 05080000, 1, 4751000000, 0, NULL, 0, 78, 2, NULL, 0),
|
||||
(12, 3, 30, 'GRE', 1, 2, NULL, 2, 06021010, 1, 4751000000, 0, NULL, 0, 82, 2, NULL, 0),
|
||||
(13, 5, 30, 'GRE', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 83, 2, NULL, 0),
|
||||
(14, 5, 90, 'AZL', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 84, 2, NULL, 0),
|
||||
(15, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 67350, 2, NULL, 0),
|
||||
(16, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 67350, 2, NULL, 0),
|
||||
(71, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 1, 4751000000, 0, NULL, 0, 88, 2, NULL, 0);
|
||||
|
||||
INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `isBox`, `created`, `itemFk`, `counter`, `checked`, `workerFk`)
|
||||
VALUES
|
||||
|
@ -791,6 +791,26 @@ INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `isBox`, `create
|
|||
(8, 3, 5, 71, DATE_ADD(CURDATE(), INTERVAL -4 MONTH), 1, 1, 1, 18),
|
||||
(9, 3, 6, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 1, 1, 18),
|
||||
(10, 7, 7, 71, CURDATE(), 1, 1, 1, 18);
|
||||
|
||||
INSERT INTO `vn`.`item`(`id`, `typeFk`, `size`, `inkFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `isOnOffer`, `expenceFk`, `isBargain`, `comment`, `relevancy`, `image`, `taxClassFk`, `subName`)
|
||||
VALUES
|
||||
(1, 2, 70, 'AMA', 1, 1, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 67, 1, NULL),
|
||||
(2, 2, 70, 'AZL', 1, 2, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 66, 1, NULL),
|
||||
(3, 1, 60, 'AMR', 1, 3, NULL, 1, 05080000, 0, 4751000000, 0, NULL, 0, 65, 1, NULL),
|
||||
(4, 1, 60, 'AMR', 1, 1, NULL, 1, 05080000, 1, 4751000000, 0, NULL, 0, 69, 2, NULL),
|
||||
(5, 3, 30, 'GRE', 1, 2, NULL, 2, 06021010, 1, 4751000000, 0, NULL, 0, 74, 2, NULL),
|
||||
(6, 5, 30, 'GRE', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 62, 2, NULL),
|
||||
(7, 5, 90, 'AZL', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 64, 2, NULL),
|
||||
(8, 2, 70, 'AMA', 1, 1, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 75, 1, NULL),
|
||||
(9, 2, 70, 'AZL', 1, 2, NULL, 1, 06021010, 0, 2000000000, 0, NULL, 0, 76, 1, NULL),
|
||||
(10, 1, 60, 'AMR', 1, 3, NULL, 1, 05080000, 0, 4751000000, 0, NULL, 0, 77, 1, NULL),
|
||||
(11, 1, 60, 'AMR', 1, 1, NULL, 1, 05080000, 1, 4751000000, 0, NULL, 0, 78, 2, NULL),
|
||||
(12, 3, 30, 'GRE', 1, 2, NULL, 2, 06021010, 1, 4751000000, 0, NULL, 0, 82, 2, NULL),
|
||||
(13, 5, 30, 'GRE', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 83, 2, NULL),
|
||||
(14, 5, 90, 'AZL', 1, 2, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 84, 2, NULL),
|
||||
(15, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 67350, 2, NULL),
|
||||
(16, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 0, 4751000000, 0, NULL, 0, 67350, 2, NULL),
|
||||
(71, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 1, 4751000000, 0, NULL, 0, 88, 2, NULL);
|
||||
|
||||
INSERT INTO `vn`.`expeditionBoxVol`(`boxFk`, `m3`, `ratio`)
|
||||
VALUES
|
||||
|
@ -807,6 +827,19 @@ INSERT INTO `vn`.`packaging`(`id`, `volume`, `width`, `height`, `depth`, `isPack
|
|||
('cc', 1640038.00, 56.00, 220.00, 128.00, 1, CURDATE(), 15, 90.00),
|
||||
('pallet 100', 2745600.00, 100.00, 220.00, 120.00, 1, CURDATE(), 16, 0.00);
|
||||
|
||||
INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `isBox`, `created`, `itemFk`, `counter`, `workerFk`, `packagingFk`)
|
||||
VALUES
|
||||
(1, 1, 1, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 1, 1, 1),
|
||||
(2, 1, 1, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 2, 1, 1),
|
||||
(3, 1, 1, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 2, 3, 1, 1),
|
||||
(4, 1, 1, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 4, 4, 1, 1),
|
||||
(5, 1, 2, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 1, 1, 1),
|
||||
(6, 7, 3, 71, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), 1, 1, 1, 1),
|
||||
(7, 2, 4, 71, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), 1, 1, 1, 1),
|
||||
(8, 3, 5, 71, DATE_ADD(CURDATE(), INTERVAL -4 MONTH), 1, 1, 1, 1),
|
||||
(9, 3, 6, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 1, 1, 1),
|
||||
(10, 7, 7, 71, CURDATE(), 1, 1, 1, 1);
|
||||
|
||||
INSERT INTO `vn`.`ticketPackaging`(`id`, `ticketFk`, `packagingFk`, `quantity`, `created`, `pvp`)
|
||||
VALUES
|
||||
(1, 1, 2, 2, CURDATE(), NULL),
|
||||
|
@ -1263,23 +1296,23 @@ INSERT INTO `bs`.`waste`(`buyer`, `year`, `week`, `family`, `saleTotal`, `saleWa
|
|||
('HankPym', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Miscellaneous Accessories', '186', '0', '0.0'),
|
||||
('HankPym', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(CURDATE(), INTERVAL -1 WEEK), 1), 'Adhesives', '277', '0', '0.0');
|
||||
|
||||
INSERT INTO `vn`.`buy`(`id`,`entryFk`,`itemFk`,`buyingValue`,`quantity`,`packageFk`,`stickers`,`freightValue`,`packageValue`,`comissionValue`,`packing`,`grouping`,`groupingMode`,`location`,`price1`,`price2`,`price3`,`minPrice`,`producer`,`printedStickers`,`isChecked`,`isIgnored`,`weight`, `created`)
|
||||
INSERT INTO `vn`.`buy`(`id`,`entryFk`,`itemFk`,`buyingValue`,`quantity`,`packageFk`,`stickers`,`freightValue`,`packageValue`,`comissionValue`,`packing`,`grouping`,`groupingMode`,`location`,`price1`,`price2`,`price3`,`producer`,`printedStickers`,`isChecked`,`isIgnored`,`weight`, `created`)
|
||||
VALUES
|
||||
(1, 1, 1, 50, 5000, 4, 1, 1.500, 1.500, 0.000, 1, 1, 1, NULL, 0.00, 99.6, 99.4, 0.00, NULL, 0, 1, 0, 1, DATE_ADD(CURDATE(), INTERVAL -2 MONTH)),
|
||||
(2, 2, 1, 50, 100, 4, 1, 1.500, 1.500, 0.000, 1, 1, 1, NULL, 0.00, 99.6, 99.4, 0.00, NULL, 0, 1, 0, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
|
||||
(3, 3, 1, 50, 100, 4, 1, 1.500, 1.500, 0.000, 1, 1, 0, NULL, 0.00, 99.6, 99.4, 0.00, NULL, 0, 1, 0, 1, CURDATE()),
|
||||
(4, 2, 2, 5, 450, 3, 1, 1.000, 1.000, 0.000, 10, 10, 0, NULL, 0.00, 7.30, 7.00, 0.00, NULL, 0, 1, 0, 2.5, CURDATE()),
|
||||
(5, 3, 3, 55, 500, 5, 1, 1.000, 1.000, 0.000, 1, 1, 0, NULL, 0.00, 78.3, 75.6, 0.00, NULL, 0, 1, 0, 2.5, CURDATE()),
|
||||
(6, 4, 8, 50, 1000, 4, 1, 1.000, 1.000, 0.000, 1, 1, 1, NULL, 0.00, 99.6, 99.4, 0.00, NULL, 0, 1, 0, 2.5, CURDATE()),
|
||||
(7, 4, 9, 20, 1000, 3, 1, 0.500, 0.500, 0.000, 10, 10, 1, NULL, 0.00, 30.50, 29.00, 0.00, NULL, 0, 1, 0, 2.5, CURDATE()),
|
||||
(8, 4, 4, 1.25, 1000, 3, 1, 0.500, 0.500, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, 0.00, NULL, 0, 1, 0, 2.5, CURDATE()),
|
||||
(9, 4, 4, 1.25, 1000, 3, 1, 0.500, 0.500, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, 0.00, NULL, 0, 1, 0, 4, CURDATE()),
|
||||
(10, 5, 1, 50, 10, 4, 1, 2.500, 2.500, 0.000, 1, 1, 1, NULL, 0.00, 99.6, 99.4, 0.00, NULL, 0, 1, 0, 4, CURDATE()),
|
||||
(11, 5, 4, 1.25, 10, 3, 1, 2.500, 2.500, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, 0.00, NULL, 0, 1, 0, 4, CURDATE()),
|
||||
(12, 6, 4, 1.25, 0, 3, 1, 2.500, 2.500, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, 0.00, NULL, 0, 1, 0, 4, CURDATE()),
|
||||
(13, 7, 1, 50, 0, 3, 1, 2.000, 2.000, 0.000, 1, 1, 1, NULL, 0.00, 99.6, 99.4, 0.00, NULL, 0, 1, 0, 4, CURDATE()),
|
||||
(14, 7, 2, 5, 0, 3, 1, 2.000, 2.000, 0.000, 10, 10, 1, NULL, 0.00, 7.30, 7.00, 0.00, NULL, 0, 1, 0, 4, CURDATE()),
|
||||
(15, 7, 4, 1.25, 0, 3, 1, 2.000, 2.000, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, 0.00, NULL, 0, 1, 0, 4, CURDATE());
|
||||
(1, 1, 1, 50, 5000, 4, 1, 1.500, 1.500, 0.000, 1, 1, 1, NULL, 0.00, 99.6, 99.4, NULL, 0, 1, 0, 1, DATE_ADD(CURDATE(), INTERVAL -2 MONTH)),
|
||||
(2, 2, 1, 50, 100, 4, 1, 1.500, 1.500, 0.000, 1, 1, 1, NULL, 0.00, 99.6, 99.4, NULL, 0, 1, 0, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
|
||||
(3, 3, 1, 50, 100, 4, 1, 1.500, 1.500, 0.000, 1, 1, 0, NULL, 0.00, 99.6, 99.4, NULL, 0, 1, 0, 1, CURDATE()),
|
||||
(4, 2, 2, 5, 450, 3, 1, 1.000, 1.000, 0.000, 10, 10, 0, NULL, 0.00, 7.30, 7.00, NULL, 0, 1, 0, 2.5, CURDATE()),
|
||||
(5, 3, 3, 55, 500, 5, 1, 1.000, 1.000, 0.000, 1, 1, 0, NULL, 0.00, 78.3, 75.6, NULL, 0, 1, 0, 2.5, CURDATE()),
|
||||
(6, 4, 8, 50, 1000, 4, 1, 1.000, 1.000, 0.000, 1, 1, 1, NULL, 0.00, 99.6, 99.4, NULL, 0, 1, 0, 2.5, CURDATE()),
|
||||
(7, 4, 9, 20, 1000, 3, 1, 0.500, 0.500, 0.000, 10, 10, 1, NULL, 0.00, 30.50, 29.00, NULL, 0, 1, 0, 2.5, CURDATE()),
|
||||
(8, 4, 4, 1.25, 1000, 3, 1, 0.500, 0.500, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, NULL, 0, 1, 0, 2.5, CURDATE()),
|
||||
(9, 4, 4, 1.25, 1000, 3, 1, 0.500, 0.500, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, NULL, 0, 1, 0, 4, CURDATE()),
|
||||
(10, 5, 1, 50, 10, 4, 1, 2.500, 2.500, 0.000, 1, 1, 1, NULL, 0.00, 99.6, 99.4, NULL, 0, 1, 0, 4, CURDATE()),
|
||||
(11, 5, 4, 1.25, 10, 3, 1, 2.500, 2.500, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, NULL, 0, 1, 0, 4, CURDATE()),
|
||||
(12, 6, 4, 1.25, 0, 3, 1, 2.500, 2.500, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, NULL, 0, 1, 0, 4, CURDATE()),
|
||||
(13, 7, 1, 50, 0, 3, 1, 2.000, 2.000, 0.000, 1, 1, 1, NULL, 0.00, 99.6, 99.4, NULL, 0, 1, 0, 4, CURDATE()),
|
||||
(14, 7, 2, 5, 0, 3, 1, 2.000, 2.000, 0.000, 10, 10, 1, NULL, 0.00, 7.30, 7.00, NULL, 0, 1, 0, 4, CURDATE()),
|
||||
(15, 7, 4, 1.25, 0, 3, 1, 2.000, 2.000, 0.000, 10, 10, 1, NULL, 0.00, 1.75, 1.67, NULL, 0, 1, 0, 4, CURDATE());
|
||||
|
||||
INSERT INTO `hedera`.`order`(`id`, `date_send`, `customer_id`, `delivery_method_id`, `agency_id`, `address_id`, `company_id`, `note`, `source_app`, `confirmed`,`total`, `date_make`, `first_row_stamp`, `confirm_date`)
|
||||
VALUES
|
||||
|
|
|
@ -189,8 +189,9 @@ export default {
|
|||
newPaymentBank: '.vn-dialog.shown vn-autocomplete[ng-model="$ctrl.receipt.bankFk"]',
|
||||
newPaymentAmount: '.vn-dialog.shown vn-input-number[ng-model="$ctrl.receipt.amountPaid"]',
|
||||
saveButton: '.vn-dialog.shown [response="accept"]',
|
||||
firstBalanceLine: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(8)'
|
||||
|
||||
firstLineBalance: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(8)',
|
||||
firstLineReference: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable',
|
||||
firstLineReferenceInput: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable > div > field > vn-textfield'
|
||||
},
|
||||
webPayment: {
|
||||
confirmFirstPaymentButton: 'vn-client-web-payment vn-tr:nth-child(1) vn-icon-button[icon="done_all"]',
|
||||
|
@ -219,23 +220,23 @@ export default {
|
|||
topbarSearch: 'vn-topbar',
|
||||
searchButton: 'vn-searchbar vn-icon[icon="search"]',
|
||||
closeItemSummaryPreview: '.vn-popup.shown',
|
||||
fieldsToShowButton: 'vn-item-index vn-table > div > div > vn-icon-button[icon="menu"]',
|
||||
fieldsToShowForm: '.vn-dialog.shown form',
|
||||
fieldsToShowButton: 'vn-item-index vn-table > div > div > vn-icon-button[icon="more_vert"]',
|
||||
fieldsToShowForm: '.vn-popover.shown .content',
|
||||
firstItemImage: 'vn-item-index vn-tbody > a:nth-child(1) > vn-td:nth-child(1) > img',
|
||||
firstItemImageTd: 'vn-item-index vn-table a:nth-child(1) vn-td:nth-child(1)',
|
||||
firstItemId: 'vn-item-index vn-tbody > a:nth-child(1) > vn-td:nth-child(2)',
|
||||
idCheckbox: '.vn-dialog.shown form vn-horizontal:nth-child(2) > vn-check',
|
||||
stemsCheckbox: '.vn-dialog.shown form vn-horizontal:nth-child(3) > vn-check',
|
||||
sizeCheckbox: '.vn-dialog.shown form vn-horizontal:nth-child(4) > vn-check',
|
||||
nicheCheckbox: '.vn-dialog.shown form vn-horizontal:nth-child(5) > vn-check',
|
||||
typeCheckbox: '.vn-dialog.shown form vn-horizontal:nth-child(6) > vn-check',
|
||||
categoryCheckbox: '.vn-dialog.shown form vn-horizontal:nth-child(7) > vn-check',
|
||||
intrastadCheckbox: '.vn-dialog.shown form vn-horizontal:nth-child(8) > vn-check',
|
||||
originCheckbox: '.vn-dialog.shown form vn-horizontal:nth-child(9) > vn-check',
|
||||
buyerCheckbox: '.vn-dialog.shown form vn-horizontal:nth-child(10) > vn-check',
|
||||
destinyCheckbox: '.vn-dialog.shown form vn-horizontal:nth-child(11) > vn-check',
|
||||
taxClassCheckbox: '.vn-dialog.shown form vn-horizontal:nth-child(12) > vn-check',
|
||||
saveFieldsButton: '.vn-dialog.shown vn-horizontal:nth-child(16) > vn-button > button'
|
||||
idCheckbox: '.vn-popover.shown vn-horizontal:nth-child(1) > vn-check',
|
||||
stemsCheckbox: '.vn-popover.shown vn-horizontal:nth-child(2) > vn-check',
|
||||
sizeCheckbox: '.vn-popover.shown vn-horizontal:nth-child(3) > vn-check',
|
||||
nicheCheckbox: '.vn-popover.shown vn-horizontal:nth-child(4) > vn-check',
|
||||
typeCheckbox: '.vn-popover.shown vn-horizontal:nth-child(5) > vn-check',
|
||||
categoryCheckbox: '.vn-popover.shown vn-horizontal:nth-child(6) > vn-check',
|
||||
intrastadCheckbox: '.vn-popover.shown vn-horizontal:nth-child(7) > vn-check',
|
||||
originCheckbox: '.vn-popover.shown vn-horizontal:nth-child(8) > vn-check',
|
||||
buyerCheckbox: '.vn-popover.shown vn-horizontal:nth-child(9) > vn-check',
|
||||
destinyCheckbox: '.vn-popover.shown vn-horizontal:nth-child(10) > vn-check',
|
||||
taxClassCheckbox: '.vn-popover.shown vn-horizontal:nth-child(11) > vn-check',
|
||||
saveFieldsButton: '.vn-popover.shown vn-button[label="Save"] > button'
|
||||
},
|
||||
itemCreateView: {
|
||||
temporalName: 'vn-item-create vn-textfield[ng-model="$ctrl.item.provisionalName"]',
|
||||
|
@ -371,7 +372,9 @@ export default {
|
|||
ticketsIndex: {
|
||||
openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]',
|
||||
advancedSearchInvoiceOut: 'vn-ticket-search-panel vn-textfield[ng-model="filter.refFk"]',
|
||||
newTicketButton: 'vn-ticket-index a',
|
||||
advancedSearchDaysOnward: 'vn-ticket-search-panel vn-input-number[ng-model="filter.scopeDays"]',
|
||||
advancedSearchButton: 'vn-ticket-search-panel button[type=submit]',
|
||||
newTicketButton: 'vn-ticket-index a[ui-sref="ticket.create"]',
|
||||
searchResult: 'vn-ticket-index vn-card > vn-table > div > vn-tbody > a.vn-tr',
|
||||
secondTicketCheckbox: 'vn-ticket-index vn-tbody > a:nth-child(2) > vn-td:nth-child(1) > vn-check',
|
||||
thirdTicketCheckbox: 'vn-ticket-index vn-tbody > a:nth-child(3) > vn-td:nth-child(1) > vn-check',
|
||||
|
@ -383,7 +386,6 @@ export default {
|
|||
searchWeeklyResult: 'vn-ticket-weekly-index vn-table vn-tbody > vn-tr',
|
||||
searchResultDate: 'vn-ticket-summary [label=Landed] span',
|
||||
topbarSearch: 'vn-searchbar',
|
||||
advancedSearchButton: 'vn-ticket-search-panel button[type=submit]',
|
||||
searchButton: 'vn-searchbar vn-icon[icon="search"]',
|
||||
moreMenu: 'vn-ticket-index vn-icon-button[icon=more_vert]',
|
||||
sixthWeeklyTicket: 'vn-ticket-weekly-index vn-table vn-tr:nth-child(6)',
|
||||
|
@ -544,6 +546,7 @@ export default {
|
|||
logButton: 'vn-left-menu a[ui-sref="ticket.card.log"]',
|
||||
changedBy: 'vn-ticket-log > vn-log vn-tr:nth-child(1) > vn-td:nth-child(2) > span',
|
||||
actionTaken: 'vn-ticket-log > vn-log vn-td:nth-child(1) > div > div:nth-child(3) > span.value',
|
||||
changes: 'vn-ticket-log vn-data-viewer vn-tbody > vn-tr > vn-td:nth-child(7)',
|
||||
id: 'vn-ticket-log > vn-log vn-td.before > vn-one:nth-child(1) > div > span.value'
|
||||
},
|
||||
ticketService: {
|
||||
|
@ -688,7 +691,7 @@ export default {
|
|||
confirmButton: '.vn-confirm.shown button[response="accept"]',
|
||||
},
|
||||
routeIndex: {
|
||||
addNewRouteButton: 'vn-route-index > a[ui-sref="route.create"]'
|
||||
addNewRouteButton: 'vn-route-index a[ui-sref="route.create"]'
|
||||
},
|
||||
createRouteView: {
|
||||
worker: 'vn-route-create vn-autocomplete[ng-model="$ctrl.route.workerFk"]',
|
||||
|
@ -803,6 +806,22 @@ export default {
|
|||
navigateBackToIndex: 'vn-worker-descriptor [name="goToModuleIndex"]',
|
||||
acceptDeleteDialog: '.vn-confirm.shown button[response="accept"]'
|
||||
},
|
||||
workerCalendar: {
|
||||
year: 'vn-worker-calendar vn-autocomplete[ng-model="$ctrl.year"]',
|
||||
totalHolidaysUsed: 'vn-worker-calendar div.totalBox > div',
|
||||
januaryThirtyFirst: 'vn-worker-calendar vn-calendar:nth-child(2) section:nth-child(33) > div',
|
||||
marchTwentyThird: 'vn-worker-calendar vn-calendar:nth-child(4) section:nth-child(29) > div',
|
||||
mayFourth: 'vn-worker-calendar vn-calendar:nth-child(6) section:nth-child(8) > div',
|
||||
mayEighth: 'vn-worker-calendar vn-calendar:nth-child(6) section:nth-child(12) > div',
|
||||
mayTwelfth: 'vn-worker-calendar vn-calendar:nth-child(6) section:nth-child(16) > div',
|
||||
mayThirteenth: 'vn-worker-calendar vn-calendar:nth-child(6) section:nth-child(17) > div',
|
||||
mayFourteenth: 'vn-worker-calendar vn-calendar:nth-child(6) section:nth-child(18) > div',
|
||||
holidays: 'vn-worker-calendar > vn-side-menu div:nth-child(3) > vn-chip:nth-child(1)',
|
||||
absence: 'vn-worker-calendar > vn-side-menu div:nth-child(3) > vn-chip:nth-child(2)',
|
||||
halfHoliday: 'vn-worker-calendar > vn-side-menu div:nth-child(3) > vn-chip:nth-child(3)',
|
||||
furlough: 'vn-worker-calendar > vn-side-menu div:nth-child(3) > vn-chip:nth-child(4)',
|
||||
halfFurlough: 'vn-worker-calendar > vn-side-menu div:nth-child(3) > vn-chip:nth-child(5)',
|
||||
},
|
||||
invoiceOutIndex: {
|
||||
topbarSearch: 'vn-searchbar',
|
||||
searchButton: 'vn-searchbar vn-icon[icon="search"]',
|
||||
|
@ -852,6 +871,13 @@ export default {
|
|||
createdThermograph: 'vn-travel-thermograph-index vn-tbody > vn-tr',
|
||||
upload: 'vn-travel-thermograph-create button[type=submit]'
|
||||
},
|
||||
zoneIndex: {
|
||||
searchResult: 'vn-zone-index a.vn-tr',
|
||||
},
|
||||
zoneDescriptor: {
|
||||
menu: 'vn-zone-descriptor vn-icon-button[vn-popover="menu"]',
|
||||
deleteZone: 'slot-menu vn-item[ng-click="$ctrl.onDelete()"]'
|
||||
},
|
||||
zoneBasicData: {
|
||||
name: 'vn-zone-basic-data vn-textfield[ng-model="$ctrl.zone.name"]',
|
||||
agency: 'vn-zone-basic-data vn-autocomplete[ng-model="$ctrl.zone.agencyModeFk"]',
|
||||
|
@ -873,5 +899,22 @@ export default {
|
|||
agency: 'vn-entry-descriptor div.body vn-label-value:nth-child(1) span',
|
||||
travelsQuicklink: 'vn-entry-descriptor vn-quick-link[icon="local_airport"] > a',
|
||||
entriesQuicklink: 'vn-entry-descriptor vn-quick-link[icon="icon-entry"] > a'
|
||||
},
|
||||
entryLatestBuys: {
|
||||
firstBuy: 'vn-entry-latest-buys vn-tbody > a:nth-child(1)',
|
||||
allBuysCheckBox: 'vn-entry-latest-buys vn-thead vn-check',
|
||||
secondBuyCheckBox: 'vn-entry-latest-buys a:nth-child(2) vn-check[ng-model="buy.checked"]',
|
||||
editBuysButton: 'vn-entry-latest-buys vn-button[icon="edit"]',
|
||||
fieldAutocomplete: 'vn-autocomplete[ng-model="$ctrl.editedColumn.field"]',
|
||||
newValueInput: 'vn-textfield[ng-model="$ctrl.editedColumn.newValue"]',
|
||||
latestBuysSectionButton: 'a[ui-sref="entry.latestBuys"]',
|
||||
acceptEditBuysDialog: 'button[response="accept"]'
|
||||
},
|
||||
entryIndex: {
|
||||
createEntryButton: 'vn-entry-index vn-button[icon="add"]',
|
||||
newEntrySupplier: 'vn-entry-create vn-autocomplete[ng-model="$ctrl.entry.supplierFk"]',
|
||||
newEntryTravel: 'vn-entry-create vn-autocomplete[ng-model="$ctrl.entry.travelFk"]',
|
||||
newEntryCompany: 'vn-entry-create vn-autocomplete[ng-model="$ctrl.entry.companyFk"]',
|
||||
saveNewEntry: 'vn-entry-create button[type="submit"]'
|
||||
}
|
||||
};
|
||||
|
|
|
@ -17,6 +17,7 @@ describe('Client Add address path', () => {
|
|||
});
|
||||
|
||||
it(`should click on the add new address button to access to the new address form`, async() => {
|
||||
await page.waitFor(500);
|
||||
await page.waitToClick(selectors.clientAddresses.createAddress);
|
||||
await page.waitForState('client.card.address.create');
|
||||
});
|
||||
|
|
|
@ -53,15 +53,28 @@ describe('Client balance path', () => {
|
|||
expect(message.type).toBe('success');
|
||||
});
|
||||
|
||||
it('should check balance is now 0 and the company is now VNL becouse the user local settings were removed', async() => {
|
||||
it('should edit the 1st line reference', async() => {
|
||||
await page.waitToClick(selectors.clientBalance.firstLineReference);
|
||||
await page.write(selectors.clientBalance.firstLineReferenceInput, 'Miscellaneous payment');
|
||||
await page.keyboard.press('Enter');
|
||||
const message = await page.waitForSnackbar();
|
||||
|
||||
expect(message.type).toBe('success');
|
||||
});
|
||||
|
||||
it('should check balance is now 0, the reference was saved and the company is now VNL becouse the user local settings were removed', async() => {
|
||||
await page.waitForSpinnerLoad();
|
||||
let company = await page
|
||||
.waitToGetProperty(selectors.clientBalance.company, 'value');
|
||||
|
||||
let reference = await page
|
||||
.waitToGetProperty(selectors.clientBalance.firstLineReference, 'innerText');
|
||||
|
||||
let firstBalanceLine = await page
|
||||
.waitToGetProperty(selectors.clientBalance.firstBalanceLine, 'innerText');
|
||||
.waitToGetProperty(selectors.clientBalance.firstLineBalance, 'innerText');
|
||||
|
||||
expect(company).toEqual('VNL');
|
||||
expect(reference).toEqual('Miscellaneous payment');
|
||||
expect(firstBalanceLine).toContain('0.00');
|
||||
});
|
||||
|
||||
|
@ -76,7 +89,7 @@ describe('Client balance path', () => {
|
|||
|
||||
it('should check balance is now -100', async() => {
|
||||
let result = await page
|
||||
.waitToGetProperty(selectors.clientBalance.firstBalanceLine, 'innerText');
|
||||
.waitToGetProperty(selectors.clientBalance.firstLineBalance, 'innerText');
|
||||
|
||||
expect(result).toContain('-€100.00');
|
||||
});
|
||||
|
@ -92,7 +105,7 @@ describe('Client balance path', () => {
|
|||
|
||||
it('should check balance is now 50', async() => {
|
||||
let result = await page
|
||||
.waitToGetProperty(selectors.clientBalance.firstBalanceLine, 'innerText');
|
||||
.waitToGetProperty(selectors.clientBalance.firstLineBalance, 'innerText');
|
||||
|
||||
expect(result).toEqual('€50.00');
|
||||
});
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
import selectors from '../../helpers/selectors.js';
|
||||
import getBrowser from '../../helpers/puppeteer';
|
||||
|
||||
describe('Worker calendar path', () => {
|
||||
let reasonableTimeBetweenClicks = 400;
|
||||
let browser;
|
||||
let page;
|
||||
beforeAll(async() => {
|
||||
browser = await getBrowser();
|
||||
page = browser.page;
|
||||
await page.loginAndModule('hr', 'worker');
|
||||
await page.accessToSearchResult('Hank Pym');
|
||||
await page.accessToSection('worker.card.calendar');
|
||||
});
|
||||
|
||||
afterAll(async() => {
|
||||
await browser.close();
|
||||
});
|
||||
|
||||
describe('as hr', () => {
|
||||
it('should check 5 total holidays have been used so far before testing anything', async() => {
|
||||
const result = await page.waitToGetProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText');
|
||||
|
||||
expect(result).toContain(' 5 ');
|
||||
});
|
||||
|
||||
it('should set two days as holidays on the calendar', async() => {
|
||||
await page.waitToClick(selectors.workerCalendar.holidays);
|
||||
await page.waitFor(reasonableTimeBetweenClicks);
|
||||
await page.waitToClick(selectors.workerCalendar.januaryThirtyFirst);
|
||||
|
||||
await page.waitFor(reasonableTimeBetweenClicks);
|
||||
await page.waitToClick(selectors.workerCalendar.absence);
|
||||
await page.waitFor(reasonableTimeBetweenClicks);
|
||||
await page.waitToClick(selectors.workerCalendar.marchTwentyThird);
|
||||
|
||||
await page.waitFor(reasonableTimeBetweenClicks);
|
||||
await page.waitToClick(selectors.workerCalendar.halfHoliday);
|
||||
await page.waitFor(reasonableTimeBetweenClicks);
|
||||
await page.waitToClick(selectors.workerCalendar.mayFourth);
|
||||
|
||||
await page.waitFor(reasonableTimeBetweenClicks);
|
||||
await page.waitToClick(selectors.workerCalendar.furlough);
|
||||
await page.waitFor(reasonableTimeBetweenClicks);
|
||||
await page.waitToClick(selectors.workerCalendar.mayTwelfth);
|
||||
await page.waitToClick(selectors.workerCalendar.mayThirteenth);
|
||||
await page.waitToClick(selectors.workerCalendar.mayFourteenth);
|
||||
|
||||
await page.waitFor(reasonableTimeBetweenClicks);
|
||||
await page.waitToClick(selectors.workerCalendar.halfFurlough);
|
||||
await page.waitFor(reasonableTimeBetweenClicks);
|
||||
await page.waitToClick(selectors.workerCalendar.mayEighth);
|
||||
});
|
||||
|
||||
it('should check the total holidays increased by 1.5', async() => {
|
||||
const result = await page.waitToGetProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText');
|
||||
|
||||
expect(result).toContain(' 6.5 ');
|
||||
});
|
||||
});
|
||||
|
||||
describe(`as salesBoss`, () => {
|
||||
it(`should log in and get to Hank's calendar`, async() => {
|
||||
await page.loginAndModule('salesBoss', 'worker');
|
||||
await page.accessToSearchResult('Hank Pym');
|
||||
await page.accessToSection('worker.card.calendar');
|
||||
});
|
||||
|
||||
it('should undo what was done here', async() => {
|
||||
await page.waitFor(reasonableTimeBetweenClicks);
|
||||
await page.waitToClick(selectors.workerCalendar.holidays);
|
||||
await page.waitFor(reasonableTimeBetweenClicks);
|
||||
await page.waitToClick(selectors.workerCalendar.januaryThirtyFirst);
|
||||
|
||||
await page.waitFor(reasonableTimeBetweenClicks);
|
||||
await page.waitToClick(selectors.workerCalendar.absence);
|
||||
await page.waitFor(reasonableTimeBetweenClicks);
|
||||
await page.waitToClick(selectors.workerCalendar.marchTwentyThird);
|
||||
|
||||
await page.waitFor(reasonableTimeBetweenClicks);
|
||||
await page.waitToClick(selectors.workerCalendar.halfHoliday);
|
||||
await page.waitFor(reasonableTimeBetweenClicks);
|
||||
await page.waitToClick(selectors.workerCalendar.mayFourth);
|
||||
|
||||
await page.waitFor(reasonableTimeBetweenClicks);
|
||||
await page.waitToClick(selectors.workerCalendar.furlough);
|
||||
await page.waitFor(reasonableTimeBetweenClicks);
|
||||
await page.waitToClick(selectors.workerCalendar.mayTwelfth);
|
||||
await page.waitToClick(selectors.workerCalendar.mayThirteenth);
|
||||
await page.waitToClick(selectors.workerCalendar.mayFourteenth);
|
||||
|
||||
await page.waitFor(reasonableTimeBetweenClicks);
|
||||
await page.waitToClick(selectors.workerCalendar.halfFurlough);
|
||||
await page.waitFor(reasonableTimeBetweenClicks);
|
||||
await page.waitToClick(selectors.workerCalendar.mayEighth);
|
||||
});
|
||||
|
||||
it('should check the total holidays used are back to what it was', async() => {
|
||||
const result = await page.waitToGetProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText');
|
||||
|
||||
expect(result).toContain(' 5 ');
|
||||
});
|
||||
});
|
||||
|
||||
describe(`as Hank`, () => {
|
||||
it(`should log in and get to his calendar`, async() => {
|
||||
await page.loginAndModule('HankPym', 'worker');
|
||||
await page.accessToSearchResult('Hank Pym');
|
||||
await page.accessToSection('worker.card.calendar');
|
||||
});
|
||||
|
||||
it('should make a futile attempt to add holidays', async() => {
|
||||
await page.waitFor(reasonableTimeBetweenClicks);
|
||||
await page.waitToClick(selectors.workerCalendar.holidays);
|
||||
await page.waitFor(reasonableTimeBetweenClicks);
|
||||
await page.waitToClick(selectors.workerCalendar.januaryThirtyFirst);
|
||||
});
|
||||
|
||||
it('should check the total holidays used are now the initial ones', async() => {
|
||||
const result = await page.waitToGetProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText');
|
||||
|
||||
expect(result).toContain(' 5 ');
|
||||
});
|
||||
|
||||
it('should use the year selector to go to the previous year', async() => {
|
||||
const date = new Date();
|
||||
const lastYear = (date.getFullYear() - 1).toString();
|
||||
|
||||
await page.autocompleteSearch(selectors.workerCalendar.year, lastYear);
|
||||
|
||||
await page.waitFor(reasonableTimeBetweenClicks);
|
||||
const result = await page.waitToGetProperty(selectors.workerCalendar.totalHolidaysUsed, 'innerText');
|
||||
|
||||
expect(result).toContain(' 0 ');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -55,7 +55,7 @@ describe('Item index path', () => {
|
|||
});
|
||||
|
||||
it('should mark all unchecked boxes to leave the index as it was', async() => {
|
||||
await page.waitFor(3000); // otherwise the snackbar doesnt appear some times.
|
||||
await page.waitFor(500); // otherwise the snackbar doesnt appear some times.
|
||||
await page.waitToClick(selectors.itemsIndex.fieldsToShowButton);
|
||||
await page.waitToClick(selectors.itemsIndex.idCheckbox);
|
||||
await page.waitToClick(selectors.itemsIndex.stemsCheckbox);
|
||||
|
|
|
@ -31,7 +31,7 @@ describe('Item request path', () => {
|
|||
it('should the status of the request should now be accepted', async() => {
|
||||
let status = await page.waitToGetProperty(selectors.itemRequest.firstRequestStatus, 'innerText');
|
||||
|
||||
expect(status).toContain('Aceptada');
|
||||
expect(status).toContain('Accepted');
|
||||
});
|
||||
|
||||
it('should now click on the second declain request icon then type the reason', async() => {
|
||||
|
@ -40,6 +40,6 @@ describe('Item request path', () => {
|
|||
await page.respondToDialog('accept');
|
||||
let status = await page.waitToGetProperty(selectors.itemRequest.firstRequestStatus, 'innerText');
|
||||
|
||||
expect(status).toContain('Denegada');
|
||||
expect(status).toContain('Denied');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -18,7 +18,7 @@ describe('Ticket purchase request path', () => {
|
|||
});
|
||||
|
||||
it('should add a new request', async() => {
|
||||
await page.waitFor('.vn-popup', {hidden: true}),
|
||||
await page.waitFor(500);
|
||||
await page.waitToClick(selectors.ticketRequests.addRequestButton);
|
||||
await page.write(selectors.ticketRequests.descriptionInput, 'New stuff');
|
||||
await page.write(selectors.ticketRequests.quantity, '9');
|
||||
|
|
|
@ -19,7 +19,7 @@ describe('Ticket index payout path', () => {
|
|||
await page.waitForState('ticket.index');
|
||||
});
|
||||
|
||||
it('should check three tickets 2 of a clinet and 1 of another', async() => {
|
||||
it('should check the second ticket from a client and 1 of another', async() => {
|
||||
await page.keyboard.press('Enter');
|
||||
await page.waitToClick(selectors.ticketsIndex.secondTicketCheckbox);
|
||||
await page.waitToClick(selectors.ticketsIndex.sixthTicketCheckbox);
|
||||
|
|
|
@ -17,6 +17,7 @@ describe('Route create path', () => {
|
|||
|
||||
describe('as employee', () => {
|
||||
it('should click on the add new route button and open the creation form', async() => {
|
||||
await page.waitFor(500);
|
||||
await page.waitToClick(selectors.routeIndex.addNewRouteButton);
|
||||
await page.waitForState('route.create');
|
||||
});
|
||||
|
|
|
@ -18,6 +18,7 @@ describe('InvoiceOut descriptor path', () => {
|
|||
describe('as Administrative', () => {
|
||||
it('should search for tickets with an specific invoiceOut', async() => {
|
||||
await page.waitToClick(selectors.ticketsIndex.openAdvancedSearchButton);
|
||||
await page.clearInput(selectors.ticketsIndex.advancedSearchDaysOnward);
|
||||
await page.write(selectors.ticketsIndex.advancedSearchInvoiceOut, 'T2222222');
|
||||
await page.waitToClick(selectors.ticketsIndex.advancedSearchButton);
|
||||
await page.waitForState('ticket.card.summary');
|
||||
|
@ -63,7 +64,7 @@ describe('InvoiceOut descriptor path', () => {
|
|||
await page.waitForState('ticket.index');
|
||||
});
|
||||
|
||||
it('should search for tickets with an specific invoiceOut to find no results', async() => {
|
||||
it('should search now for tickets with an specific invoiceOut to find no results', async() => {
|
||||
await page.doSearch('T2222222');
|
||||
const nResults = await page.countElement(selectors.ticketsIndex.searchResult);
|
||||
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
import selectors from '../../helpers/selectors.js';
|
||||
import getBrowser from '../../helpers/puppeteer';
|
||||
|
||||
describe('Zone descriptor path', () => {
|
||||
let browser;
|
||||
let page;
|
||||
|
||||
beforeAll(async() => {
|
||||
browser = await getBrowser();
|
||||
page = browser.page;
|
||||
await page.loginAndModule('deliveryBoss', 'zone');
|
||||
await page.accessToSearchResult('13');
|
||||
});
|
||||
|
||||
afterAll(async() => {
|
||||
await browser.close();
|
||||
});
|
||||
|
||||
it('should eliminate the zone using the descriptor option', async() => {
|
||||
await page.waitToClick(selectors.zoneDescriptor.menu);
|
||||
await page.waitToClick(selectors.zoneDescriptor.deleteZone);
|
||||
await page.respondToDialog('accept');
|
||||
await page.waitForState('zone.index');
|
||||
});
|
||||
|
||||
it('should search for the deleted zone to find no results', async() => {
|
||||
await page.doSearch('13');
|
||||
const count = await page.countElement(selectors.zoneIndex.searchResult);
|
||||
|
||||
expect(count).toEqual(0);
|
||||
});
|
||||
|
||||
it('should check the ticket whom lost the zone and see evidence on the logs', async() => {
|
||||
await page.waitToClick(selectors.globalItems.homeButton);
|
||||
await page.selectModule('ticket');
|
||||
await page.accessToSearchResult('20');
|
||||
await page.accessToSection('ticket.card.log');
|
||||
const lastChanges = await page.waitToGetProperty(selectors.ticketLog.changes, 'innerText');
|
||||
|
||||
expect(lastChanges).toContain('Arreglar');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,46 @@
|
|||
import selectors from '../../helpers/selectors.js';
|
||||
import getBrowser from '../../helpers/puppeteer';
|
||||
|
||||
describe('Entry lastest buys path', () => {
|
||||
let browser;
|
||||
let page;
|
||||
|
||||
beforeAll(async() => {
|
||||
browser = await getBrowser();
|
||||
page = browser.page;
|
||||
await page.loginAndModule('buyer', 'entry');
|
||||
});
|
||||
|
||||
afterAll(async() => {
|
||||
await browser.close();
|
||||
});
|
||||
|
||||
it('should access the latest buys seccion and search not seeing the edit buys button yet', async() => {
|
||||
await page.waitToClick(selectors.entryLatestBuys.latestBuysSectionButton);
|
||||
await page.waitFor(250);
|
||||
await page.keyboard.press('Enter');
|
||||
await page.waitForSelector(selectors.entryLatestBuys.editBuysButton, {visible: false});
|
||||
});
|
||||
|
||||
it('should select all lines but one and then check the edit buys button appears', async() => {
|
||||
await page.waitToClick(selectors.entryLatestBuys.allBuysCheckBox);
|
||||
await page.waitToClick(selectors.entryLatestBuys.secondBuyCheckBox);
|
||||
await page.waitForSelector(selectors.entryLatestBuys.editBuysButton, {visible: true});
|
||||
});
|
||||
|
||||
it('should open the edit dialog', async() => {
|
||||
await page.waitToClick(selectors.entryLatestBuys.editBuysButton);
|
||||
await page.waitForSelector(selectors.entryLatestBuys.fieldAutocomplete, {visible: true});
|
||||
});
|
||||
|
||||
it('should search for the "Description" field and type a new description for the items in each selected buy', async() => {
|
||||
await page.autocompleteSearch(selectors.entryLatestBuys.fieldAutocomplete, 'Description');
|
||||
await page.write(selectors.entryLatestBuys.newValueInput, 'Crafted item');
|
||||
await page.waitToClick(selectors.entryLatestBuys.acceptEditBuysDialog);
|
||||
});
|
||||
|
||||
it('should navigate to the entry.buy section by clicking one of the buys', async() => {
|
||||
await page.waitToClick(selectors.entryLatestBuys.firstBuy);
|
||||
await page.waitForState('entry.card.buy');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,33 @@
|
|||
import selectors from '../../helpers/selectors.js';
|
||||
import getBrowser from '../../helpers/puppeteer';
|
||||
|
||||
describe('Entry create path', () => {
|
||||
let browser;
|
||||
let page;
|
||||
|
||||
beforeAll(async() => {
|
||||
browser = await getBrowser();
|
||||
page = browser.page;
|
||||
await page.loginAndModule('buyer', 'entry');
|
||||
});
|
||||
|
||||
afterAll(async() => {
|
||||
await browser.close();
|
||||
});
|
||||
|
||||
it('should click the create entry button to open the form', async() => {
|
||||
await page.waitToClick(selectors.entryIndex.createEntryButton);
|
||||
await page.waitForState('entry.create');
|
||||
});
|
||||
|
||||
it('should fill the form to create a valid entry', async() => {
|
||||
await page.autocompleteSearch(selectors.entryIndex.newEntrySupplier, '2');
|
||||
await page.autocompleteSearch(selectors.entryIndex.newEntryTravel, 'Warehouse Three');
|
||||
await page.autocompleteSearch(selectors.entryIndex.newEntryCompany, 'ORN');
|
||||
await page.waitToClick(selectors.entryIndex.saveNewEntry);
|
||||
});
|
||||
|
||||
it('should be redirected to entry basic data', async() => {
|
||||
await page.waitForState('entry.card.basicData');
|
||||
});
|
||||
});
|
|
@ -67,13 +67,13 @@ export default class Contextmenu {
|
|||
get cell() {
|
||||
if (!this.target) return null;
|
||||
|
||||
return this.target.closest('vn-td, .vn-td');
|
||||
return this.target.closest('vn-td, .vn-td, vn-td-editable');
|
||||
}
|
||||
|
||||
get cellIndex() {
|
||||
if (!this.row) return null;
|
||||
|
||||
const cells = this.row.querySelectorAll('vn-td, .vn-td');
|
||||
const cells = this.row.querySelectorAll('vn-td, .vn-td, vn-td-editable');
|
||||
return Array.from(cells).findIndex(
|
||||
cellItem => cellItem == this.cell
|
||||
);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<vn-check
|
||||
ng-model="$ctrl.checked"
|
||||
intermediate="$ctrl.isIntermediate"
|
||||
indeterminate="$ctrl.isIndeterminate"
|
||||
translate-attr="{title: 'Check all'}">
|
||||
</vn-check>
|
|
@ -15,6 +15,19 @@ export default class MultiCheck extends FormInput {
|
|||
this._checked = false;
|
||||
this.checkField = 'checked';
|
||||
this.isIntermediate = false;
|
||||
this.mayusEnabled = false;
|
||||
this.window.addEventListener('keydown', event => {
|
||||
if (event.key === 'Shift')
|
||||
this.mayusEnabled = true;
|
||||
});
|
||||
this.window.addEventListener('keyup', event => {
|
||||
if (event.key === 'Shift')
|
||||
this.mayusEnabled = false;
|
||||
});
|
||||
this.window.addEventListener('selectstart', event => {
|
||||
if (this.mayusEnabled)
|
||||
event.preventDefault();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -28,7 +41,7 @@ export default class MultiCheck extends FormInput {
|
|||
|
||||
/**
|
||||
* Sets the array model instance
|
||||
* Changes intermediate property for
|
||||
* Changes indeterminate property for
|
||||
* the check component
|
||||
*
|
||||
* @param {ArrayModel} value - Array model instance
|
||||
|
@ -37,8 +50,17 @@ export default class MultiCheck extends FormInput {
|
|||
this._model = value;
|
||||
|
||||
if (value) {
|
||||
value.on('rowChange', () => {
|
||||
this.isIntermediate = !this.areAllUnchecked() && !this.areAllChecked();
|
||||
value.on('rowChange', row => {
|
||||
this.isIndeterminate = !this.areAllUnchecked() && !this.areAllChecked();
|
||||
|
||||
if (this.mayusEnabled) {
|
||||
this.currentSelection = row.obj.$orgIndex;
|
||||
|
||||
if (this.lastSelection != undefined && this.currentSelection != undefined)
|
||||
this.setSelection(row.value, this.lastSelection, this.currentSelection);
|
||||
}
|
||||
|
||||
this.lastSelection = row.obj.$orgIndex;
|
||||
|
||||
if (this.areAllChecked())
|
||||
this._checked = true;
|
||||
|
@ -52,6 +74,20 @@ export default class MultiCheck extends FormInput {
|
|||
}
|
||||
}
|
||||
|
||||
setSelection(value, from, to) {
|
||||
let start = from;
|
||||
let end = to;
|
||||
|
||||
if (from > to) {
|
||||
start = to;
|
||||
end = from;
|
||||
}
|
||||
|
||||
const data = this.model.data;
|
||||
for (let i = start; i <= end; i++)
|
||||
data[i].checked = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets current check state
|
||||
*/
|
||||
|
|
|
@ -62,7 +62,7 @@ describe('Component vnMultiCheck', () => {
|
|||
});
|
||||
|
||||
describe('areAllChecked()', () => {
|
||||
it(`should set return true if all elements are checked`, () => {
|
||||
it(`should return true if all elements are checked`, () => {
|
||||
const data = controller.model.data;
|
||||
data[0].checked = true;
|
||||
data[1].checked = true;
|
||||
|
@ -71,7 +71,7 @@ describe('Component vnMultiCheck', () => {
|
|||
expect(controller.areAllChecked()).toBeTruthy();
|
||||
});
|
||||
|
||||
it(`should set return false if not all elements are checked`, () => {
|
||||
it(`should return false if not all elements are checked`, () => {
|
||||
const data = controller.model.data;
|
||||
data[0].checked = true;
|
||||
data[1].checked = false;
|
||||
|
@ -82,7 +82,7 @@ describe('Component vnMultiCheck', () => {
|
|||
});
|
||||
|
||||
describe('areAllUnchecked()', () => {
|
||||
it(`should set return true if all elements are unchecked`, () => {
|
||||
it(`should return true if all elements are unchecked`, () => {
|
||||
const data = controller.model.data;
|
||||
data[0].checked = false;
|
||||
data[1].checked = false;
|
||||
|
@ -91,7 +91,7 @@ describe('Component vnMultiCheck', () => {
|
|||
expect(controller.areAllUnchecked()).toBeTruthy();
|
||||
});
|
||||
|
||||
it(`should set return false if not all elements are unchecked`, () => {
|
||||
it(`should return false if not all elements are unchecked`, () => {
|
||||
const data = controller.model.data;
|
||||
data[0].checked = false;
|
||||
data[1].checked = true;
|
||||
|
@ -100,4 +100,36 @@ describe('Component vnMultiCheck', () => {
|
|||
expect(controller.areAllUnchecked()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('setSelection()', () => {
|
||||
it(`should check all elements between the index range`, () => {
|
||||
controller.setSelection(true, 0, 2);
|
||||
|
||||
const data = controller.model.data;
|
||||
const firstRow = data[0];
|
||||
const secondRow = data[1];
|
||||
const thirdRow = data[2];
|
||||
|
||||
expect(firstRow.checked).toBeTruthy();
|
||||
expect(secondRow.checked).toBeTruthy();
|
||||
expect(thirdRow.checked).toBeTruthy();
|
||||
});
|
||||
|
||||
it(`should uncheck all elements between the index range`, () => {
|
||||
const data = controller.model.data;
|
||||
const firstRow = data[0];
|
||||
const secondRow = data[1];
|
||||
const thirdRow = data[2];
|
||||
|
||||
firstRow.checked = true;
|
||||
secondRow.checked = true;
|
||||
thirdRow.checked = true;
|
||||
|
||||
controller.setSelection(false, 0, 1);
|
||||
|
||||
expect(firstRow.checked).toBeFalsy();
|
||||
expect(secondRow.checked).toBeFalsy();
|
||||
expect(thirdRow.checked).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,7 +7,6 @@ export default class Table {
|
|||
this.table = $element[0];
|
||||
this.field = null;
|
||||
this.order = null;
|
||||
this.autoLoad = true;
|
||||
}
|
||||
|
||||
setOrder(field, order) {
|
||||
|
@ -25,9 +24,7 @@ export default class Table {
|
|||
}
|
||||
|
||||
$onChanges() {
|
||||
// FIXME: The autoload property should be removed from vnTable
|
||||
// because it's already implemented at vnModel
|
||||
if (this.autoLoad && this.model && !this.model.data)
|
||||
if (this.model && !this.model.data)
|
||||
this.applyOrder();
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import './visible-by';
|
|||
import './bind';
|
||||
import './repeat-last';
|
||||
import './title';
|
||||
import './uvc';
|
||||
import './smart-table';
|
||||
import './droppable';
|
||||
import './http-click';
|
||||
import './http-submit';
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
<div style="position: relative;">
|
||||
<div style="position: absolute; top: 0; left: 0; padding: .3em; z-index: 1">
|
||||
<div style="position: absolute; top: 0; left: 0; z-index: 1">
|
||||
<vn-icon-button
|
||||
icon="menu"
|
||||
ng-click="$ctrl.showUvc($event)">
|
||||
class="vn-pt-sm"
|
||||
icon="more_vert"
|
||||
ng-click="$ctrl.showSmartTable($event)">
|
||||
</vn-icon-button>
|
||||
<vn-dialog
|
||||
<vn-popover
|
||||
class="modal-form"
|
||||
vn-id="uvc"
|
||||
vn-id="smart-table"
|
||||
message="Fields to show">
|
||||
<tpl-body>
|
||||
<div class="vn-pa-md">
|
||||
|
@ -24,6 +25,6 @@
|
|||
</vn-horizontal>
|
||||
</div>
|
||||
</tpl-body>
|
||||
</vn-dialog>
|
||||
</vn-popover>
|
||||
</div>
|
||||
</div>
|
|
@ -1,23 +1,28 @@
|
|||
import ngModule from '../module';
|
||||
import template from './uvc.html';
|
||||
import './uvc.scss';
|
||||
import template from './smart-table.html';
|
||||
import './smart-table.scss';
|
||||
|
||||
/**
|
||||
* Directive to hide/show selected columns of a table, don't use with rowspan.
|
||||
* Property smart-table-ignore ignores one or more vn-th with prop field.
|
||||
*/
|
||||
directive.$inject = ['$http', '$compile', 'vnApp', '$translate'];
|
||||
export function directive($http, $compile, vnApp, $translate) {
|
||||
function getHeaderList($element, $scope) {
|
||||
let allHeaders = $element[0].querySelectorAll(`vn-th[field], vn-th[th-id]`);
|
||||
let headerList = Array.from(allHeaders);
|
||||
let filtrableHeaders = $element[0].querySelectorAll('vn-th[field]:not([smart-table-ignore])');
|
||||
let headerList = Array.from(filtrableHeaders);
|
||||
let ids = [];
|
||||
let titles = {};
|
||||
|
||||
headerList.forEach(header => {
|
||||
let id = header.getAttribute('th-id') || header.getAttribute('field');
|
||||
let id = header.getAttribute('field');
|
||||
ids.push(id);
|
||||
titles[id] = header.innerText || id.charAt(0).toUpperCase() + id.slice(1);
|
||||
});
|
||||
|
||||
$scope.fields = ids;
|
||||
$scope.titles = titles;
|
||||
$scope.allHeaders = Array.from($element[0].querySelectorAll('vn-th'));
|
||||
|
||||
return headerList;
|
||||
}
|
||||
|
@ -38,34 +43,33 @@ export function directive($http, $compile, vnApp, $translate) {
|
|||
Object.keys(userConfig.configuration).forEach(key => {
|
||||
let index;
|
||||
if (userConfig.configuration[key] === false) {
|
||||
index = headerList.findIndex(el => {
|
||||
return (el.getAttribute('th-id') == key || el.getAttribute('field') == key);
|
||||
index = $scope.allHeaders.findIndex(el => {
|
||||
return el.getAttribute('field') == key;
|
||||
});
|
||||
|
||||
let baseSelector = `vn-table[vn-uvc=${userConfig.tableCode}] > div`;
|
||||
let baseSelector = `vn-table[vn-smart-table=${userConfig.tableCode}] > div`;
|
||||
selectors.push(`${baseSelector} vn-thead > vn-tr > vn-th:nth-child(${index + 1})`);
|
||||
selectors.push(`${baseSelector} vn-tbody > vn-tr > vn-td:nth-child(${index + 1})`);
|
||||
selectors.push(`${baseSelector} vn-tbody > .vn-tr > vn-td:nth-child(${index + 1})`);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (document.querySelector('style[id="uvc"]')) {
|
||||
let child = document.querySelector('style[id="uvc"]');
|
||||
if (document.querySelector('style[id="smart-table"]')) {
|
||||
let child = document.querySelector('style[id="smart-table"]');
|
||||
child.parentNode.removeChild(child);
|
||||
}
|
||||
|
||||
if (selectors.length) {
|
||||
let rule = selectors.join(', ') + '{display: none;}';
|
||||
$scope.css = document.createElement('style');
|
||||
$scope.css.setAttribute('id', 'uvc');
|
||||
$scope.css.setAttribute('id', 'smart-table');
|
||||
document.head.appendChild($scope.css);
|
||||
$scope.css.appendChild(document.createTextNode(rule));
|
||||
}
|
||||
|
||||
$scope.$on('$destroy', () => {
|
||||
if ($scope.css && document.querySelector('style[id="uvc"]')) {
|
||||
let child = document.querySelector('style[id="uvc"]');
|
||||
if ($scope.css && document.querySelector('style[id="smart-table"]')) {
|
||||
let child = document.querySelector('style[id="smart-table"]');
|
||||
child.parentNode.removeChild(child);
|
||||
}
|
||||
});
|
||||
|
@ -80,13 +84,13 @@ export function directive($http, $compile, vnApp, $translate) {
|
|||
restrict: 'A',
|
||||
link: async function($scope, $element, $attrs) {
|
||||
let cTemplate = $compile(template)($scope)[0];
|
||||
$scope.$ctrl.showUvc = event => {
|
||||
$scope.$ctrl.showSmartTable = event => {
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
$scope.uvc.show();
|
||||
$scope.smartTable.show(event.target);
|
||||
};
|
||||
|
||||
let tableCode = $attrs.vnUvc.trim();
|
||||
let tableCode = $attrs.vnSmartTable.trim();
|
||||
let headerList = getHeaderList($element, $scope);
|
||||
|
||||
let defaultConfigView = {tableCode: tableCode, configuration: {}};
|
||||
|
@ -98,16 +102,16 @@ export function directive($http, $compile, vnApp, $translate) {
|
|||
|
||||
addHideClass($scope, headerList, config);
|
||||
|
||||
let table = document.querySelector(`vn-table[vn-uvc=${tableCode}]`);
|
||||
let table = document.querySelector(`vn-table[vn-smart-table=${tableCode}]`);
|
||||
|
||||
table.insertBefore(cTemplate, table.firstChild);
|
||||
$scope.$ctrl.saveConfiguration = async tableConfiguration => {
|
||||
let newConfig = await saveConfiguration(tableConfiguration);
|
||||
vnApp.showSuccess($translate.instant('Data saved!'));
|
||||
addHideClass($scope, headerList, newConfig.data);
|
||||
$scope.uvc.hide();
|
||||
$scope.smartTable.hide();
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
ngModule.directive('vnUvc', directive);
|
||||
ngModule.directive('vnSmartTable', directive);
|
|
@ -1,4 +1,4 @@
|
|||
vn-table vn-dialog[vn-id="uvc"]{
|
||||
vn-table vn-popover[vn-id="smart-table"]{
|
||||
& > div {
|
||||
min-width: 288px;
|
||||
align-items: center;
|
|
@ -22,7 +22,9 @@
|
|||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-latestBuys:before {
|
||||
content: "\e95f";
|
||||
}
|
||||
.icon-zone:before {
|
||||
content: "\e95d";
|
||||
}
|
||||
|
|
|
@ -102,6 +102,7 @@
|
|||
<glyph unicode="" glyph-name="anonymous" d="M230.4 605.867c12.8 46.933 29.867 93.867 46.933 140.8 8.533 34.133 21.333 64 29.867 98.133 4.267 12.8 8.533 12.8 21.333 12.8 38.4-12.8 72.533-21.333 110.933-25.6 12.8-4.267 29.867 0 46.933 0 34.133 4.267 68.267 8.533 102.4 12.8s72.533 12.8 106.667 17.067c4.267 0 8.533 0 12.8 0s8.533 0 12.8-8.533c12.8-46.933 29.867-93.867 42.667-136.533 12.8-38.4 25.6-76.8 34.133-115.2-192 4.267-379.733 4.267-567.467 4.267zM456.533 247.467c34.133 8.533 64 12.8 98.133 4.267 8.533 0 12.8 0 12.8 8.533 17.067 34.133 42.667 59.733 76.8 72.533 38.4 17.067 76.8 21.333 115.2 8.533 34.133-8.533 59.733-29.867 81.067-55.467 25.6-34.133 38.4-72.533 34.133-119.467-8.533-51.2-34.133-89.6-76.8-115.2-51.2-34.133-132.267-29.867-179.2 12.8-42.667 34.133-59.733 76.8-64 128 0 8.533-4.267 12.8-12.8 17.067-21.333 4.267-42.667 4.267-64 0-8.533-4.267-8.533-4.267-8.533-12.8 0-21.333-4.267-46.933-12.8-68.267-12.8-29.867-34.133-55.467-64-72.533-55.467-38.4-136.533-34.133-183.467 8.533-42.667 34.133-64 76.8-59.733 128 0 59.733 29.867 106.667 85.333 136.533s115.2 25.6 170.667-12.8c12.8-8.533 21.333-17.067 34.133-29.867 0-8.533 8.533-21.333 17.067-38.4zM307.2 302.933c-64 0-115.2-51.2-115.2-110.933 0-64 46.933-115.2 110.933-115.2s115.2 46.933 115.2 110.933c4.267 64-46.933 115.2-110.933 115.2zM712.533 302.933c-64 0-115.2-51.2-115.2-110.933 0-64 46.933-115.2 110.933-115.2 59.733 0 115.2 46.933 115.2 110.933 0 59.733-46.933 115.2-110.933 115.2zM1024 409.6c-341.333 0-682.667 0-1024 0 0 0 0 0 0 0 17.067 8.533 29.867 17.067 46.933 21.333 42.667 12.8 85.333 29.867 132.267 42.667 34.133 8.533 68.267 17.067 102.4 21.333 89.6 17.067 183.467 21.333 277.333 17.067 55.467-4.267 110.933-8.533 166.4-17.067 38.4-4.267 72.533-12.8 110.933-21.333s72.533-21.333 110.933-34.133c21.333-4.267 51.2-17.067 76.8-29.867 0 0 0 0 0 0z" />
|
||||
<glyph unicode="" glyph-name="zone" d="M243.2 448c-12.8 17.067-25.6 34.133-38.4 51.2-34.133 46.933-68.267 98.133-89.6 153.6-17.067 34.133-25.6 72.533-17.067 110.933 8.533 51.2 38.4 89.6 85.333 110.933 59.733 25.6 132.267 8.533 174.933-34.133 34.133-38.4 42.667-81.067 34.133-132.267-8.533-46.933-29.867-85.333-51.2-123.733-29.867-46.933-59.733-89.6-89.6-132.267-4.267 0-4.267 0-8.533-4.267zM247.467 823.467c-46.933 0-89.6-38.4-89.6-89.6 0-46.933 38.4-89.6 85.333-89.6s89.6 38.4 89.6 85.333c0 55.467-38.4 93.867-85.333 93.867zM490.667 379.733l-17.067 25.6 12.8 8.533-34.133 183.467c0 0 0 8.533-8.533 8.533l-42.667 4.267c0 0-68.267-110.933-157.867-217.6 4.267 4.267-93.867 110.933-132.267 187.733l-110.933-51.2c0 0-4.267 0-4.267-8.533l25.6-145.067 34.133-21.333-8.533-21.333-17.067 8.533 59.733-332.8 213.333 102.4 238.933-21.333-51.2 290.133zM149.333 285.867c-12.8 4.267-29.867 12.8-42.667 17.067 4.267 8.533 4.267 17.067 8.533 21.333 17.067 0 29.867-4.267 42.667-12.8-4.267-8.533-4.267-17.067-8.533-25.6zM256 268.8c-17.067 0-34.133 4.267-46.933 4.267 0 8.533 4.267 17.067 4.267 25.6 12.8 0 29.867-4.267 42.667-4.267 0-8.533 0-17.067 0-25.6zM315.733 277.333c-4.267 8.533-4.267 12.8-8.533 21.333 17.067 8.533 29.867 17.067 42.667 21.333 4.267-8.533 8.533-12.8 8.533-21.333-12.8-8.533-25.6-12.8-42.667-21.333zM405.333 328.533c-4.267 8.533-8.533 12.8-12.8 21.333 12.8 8.533 25.6 17.067 38.4 25.6 4.267-4.267 8.533-12.8 12.8-21.333-8.533-8.533-21.333-17.067-38.4-25.6zM972.8 460.8l-29.867 25.6 12.8 21.333 12.8-8.533-34.133 187.733c0 0 0 8.533-8.533 8.533l-226.133 17.067-209.067-93.867c0 0-8.533-4.267-4.267-12.8l29.867-170.667 21.333-12.8-17.067-17.067 55.467-307.2 213.333 102.4 234.667-21.333-51.2 281.6zM580.267 465.067c-4.267 4.267-8.533 12.8-12.8 17.067 12.8 12.8 21.333 21.333 29.867 34.133 4.267-4.267 12.8-12.8 17.067-17.067-12.8-8.533-25.6-21.333-34.133-34.133zM657.067 541.867c-4.267 4.267-8.533 12.8-12.8 21.333 12.8 8.533 25.6 17.067 38.4 25.6 8.533-8.533 12.8-17.067 12.8-21.333-12.8-8.533-25.6-17.067-38.4-25.6zM797.867 571.733c-12.8 4.267-25.6 4.267-42.667 4.267 0 8.533 0 17.067 0 25.6 17.067 0 34.133 0 51.2-4.267-4.267-8.533-4.267-17.067-8.533-25.6zM891.733 520.533c-12.8 8.533-25.6 17.067-38.4 25.6 4.267 8.533 8.533 12.8 12.8 21.333 12.8-8.533 25.6-17.067 38.4-25.6-4.267-8.533-8.533-12.8-12.8-21.333z" />
|
||||
<glyph unicode="" glyph-name="inventory" d="M273.067 226.133c4.267 0 8.533 4.267 8.533 8.533v85.333h98.133v-221.867h-217.6v221.867h98.133v-81.067c0-8.533 8.533-12.8 12.8-12.8zM512 226.133c4.267 0 8.533 4.267 8.533 8.533v85.333h98.133v-221.867h-217.6v221.867h98.133v-81.067c0-8.533 8.533-12.8 12.8-12.8zM750.933 226.133c4.267 0 8.533 4.267 8.533 8.533v85.333h98.133v-221.867h-217.6v221.867h98.133v-81.067c4.267-8.533 8.533-12.8 12.8-12.8zM644.267 780.8h98.133v-81.067c0-4.267 4.267-8.533 8.533-8.533s8.533 4.267 8.533 8.533v81.067h98.133v-221.867h-217.6v221.867h4.267zM401.067 780.8h98.133v-81.067c0-4.267 4.267-8.533 8.533-8.533s8.533 4.267 8.533 8.533v81.067h98.133v-221.867h-213.333v221.867zM162.133 780.8h98.133v-81.067c0-4.267 4.267-8.533 8.533-8.533s8.533 4.267 8.533 8.533v81.067h98.133v-221.867h-213.333v221.867zM153.6 537.6h780.8v-38.4h-844.8v38.4zM68.267-42.667h-42.667v981.333h42.667v-908.8zM89.6 38.4v38.4h844.8v-38.4zM998.4-42.667h-42.667v981.333h42.667z" />
|
||||
<glyph unicode="" glyph-name="latestBuys" d="M183.467 750.933h712.533v-38.4h-768v38.4zM89.6 64c8.533 0 12.8 0 21.333-4.267v900.267h-42.667v-900.267c8.533 4.267 12.8 4.267 21.333 4.267zM955.733 512v448h-42.667v-413.867c17.067-12.8 29.867-21.333 42.667-34.133zM145.067-8.533c0-30.633-24.833-55.467-55.467-55.467s-55.467 24.833-55.467 55.467c0 30.633 24.833 55.467 55.467 55.467s55.467-24.833 55.467-55.467zM418.133 426.667h-290.133v-38.4h273.067c4.267 17.067 8.533 29.867 17.067 38.4zM392.533 106.667h-264.533v-38.4h281.6c-8.533 12.8-12.8 25.6-17.067 38.4zM725.333 247.467c-12.8 0-21.333-8.533-21.333-21.333s8.533-21.333 21.333-21.333c12.8 0 21.333 8.533 21.333 21.333 0 8.533-12.8 21.333-21.333 21.333zM721.067 541.867c-166.4 0-298.667-136.533-298.667-302.933s132.267-302.933 298.667-302.933c166.4 0 298.667 136.533 298.667 302.933 0 170.667-132.267 302.933-298.667 302.933zM725.333 34.133c-98.133 0-174.933 72.533-187.733 162.133h-34.133l51.2 64 59.733-64h-38.4c8.533-68.267 72.533-123.733 149.333-123.733 81.067 0 149.333 64 149.333 145.067s-68.267 145.067-149.333 145.067c-68.267 0-128-46.933-145.067-110.933l-21.333 29.867-17.067-12.8c8.533 29.867 25.6 55.467 46.933 76.8l-25.6 21.333c-4.267 4.267-4.267 12.8 0 17.067l12.8 12.8c4.267 4.267 12.8 4.267 17.067 0l25.6-25.6c21.333 12.8 51.2 25.6 76.8 25.6v29.867h-8.533c-8.533 0-12.8 4.267-12.8 12.8v17.067c0 8.533 4.267 12.8 12.8 12.8h59.733c8.533 0 12.8-4.267 12.8-12.8v-17.067c0-8.533-4.267-12.8-12.8-12.8h-8.533v-21.333c29.867-4.267 55.467-12.8 81.067-29.867l34.133 29.867c4.267 4.267 12.8 4.267 17.067 0l12.8-12.8c4.267-4.267 4.267-12.8 0-17.067l-25.6-25.6c29.867-34.133 51.2-76.8 51.2-128 4.267-102.4-81.067-187.733-183.467-187.733zM772.267 226.133c0-25.6-21.333-46.933-46.933-46.933s-46.933 21.333-46.933 46.933c0 25.6 21.333 46.933 46.933 46.933 8.533 0 17.067-4.267 21.333-4.267l46.933 46.933 21.333-21.333-46.933-46.933c4.267-4.267 4.267-12.8 4.267-21.333z" />
|
||||
<glyph unicode="" glyph-name="wiki" d="M793.6 733.867c0 0 4.267 0 4.267 0l76.8 12.8v-42.667c0-34.133-21.333-68.267-46.933-72.533 0 0-4.267 0-4.267 0l-76.8-12.8v42.667c0 34.133 21.333 64 46.933 72.533zM742.4 597.333l38.4 4.267c12.8 0 25.6-12.8 25.6-29.867v-21.333l-38.4-4.267c-12.8 0-25.6 12.8-25.6 29.867v21.333zM618.667 699.733l68.267 8.533c25.6 4.267 42.667-21.333 42.667-55.467v-38.4l-68.267-8.533c-25.6-4.267-42.667 21.333-42.667 55.467v38.4zM665.6 588.8c4.267 0 4.267 0 0 0l59.733 4.267v-29.867c0-25.6-17.067-46.933-34.133-55.467 0 0-4.267 0-4.267 0l-55.467-8.533v29.867c4.267 29.867 17.067 51.2 34.133 59.733zM443.733 648.533c0 0-4.267 0-4.267 0-119.467 85.333-273.067 46.933-277.333 46.933s-8.533 0-12.8 8.533c0 4.267 0 8.533 8.533 12.8 0 0 42.667 12.8 98.133 8.533 51.2 0 128-12.8 196.267-59.733 4.267-4.267 4.267-8.533 4.267-12.8-4.267-4.267-8.533-4.267-12.8-4.267zM443.733 512c0 0-4.267 0-4.267 0-119.467 85.333-273.067 46.933-277.333 46.933s-8.533 0-12.8 8.533c0 4.267 0 8.533 8.533 12.8 0 0 42.667 12.8 98.133 8.533 51.2 0 128-12.8 196.267-59.733 4.267-4.267 4.267-8.533 4.267-12.8-4.267 0-8.533-4.267-12.8-4.267zM443.733 379.733c0 0-4.267 0-4.267 0-119.467 85.333-273.067 46.933-277.333 46.933s-8.533 0-12.8 8.533c0 4.267 0 8.533 8.533 12.8 0 0 42.667 12.8 98.133 8.533 51.2 0 128-12.8 196.267-59.733 4.267-4.267 4.267-8.533 4.267-12.8-4.267 0-8.533-4.267-12.8-4.267zM443.733 247.467c0 0-4.267 0-4.267 0-119.467 85.333-273.067 46.933-277.333 46.933s-8.533 0-12.8 8.533c0 4.267 0 8.533 8.533 12.8 0 0 42.667 12.8 98.133 8.533 51.2 0 128-12.8 196.267-59.733 4.267-4.267 4.267-8.533 4.267-12.8-4.267 0-8.533-4.267-12.8-4.267zM588.8 379.733c-4.267 0-4.267 0-8.533 4.267s0 8.533 4.267 12.8c68.267 46.933 140.8 59.733 196.267 59.733s93.867-8.533 98.133-8.533c4.267 0 8.533-8.533 8.533-12.8s-8.533-8.533-12.8-8.533v0c0 0-153.6 38.4-277.333-46.933-4.267 4.267-4.267 0-8.533 0zM588.8 247.467c-4.267 0-4.267 0-8.533 4.267s0 8.533 4.267 12.8c68.267 46.933 140.8 59.733 196.267 59.733s93.867-8.533 98.133-8.533c4.267 0 8.533-8.533 8.533-12.8s-8.533-8.533-12.8-8.533v0c0 0-153.6 38.4-277.333-46.933-4.267 4.267-4.267 0-8.533 0zM985.6 738.133v64l-8.533 4.267c-4.267 0-81.067 29.867-179.2 29.867-106.667 0-200.533-34.133-277.333-98.133-76.8 64-170.667 98.133-277.333 98.133-102.4 0-174.933-29.867-179.2-29.867l-12.8-4.267v-59.733c-34.133-4.267-51.2-17.067-51.2-34.133v-614.4h452.267c17.067-12.8 38.4-21.333 64-21.333s46.933 8.533 64 21.333h443.733v614.4c0 17.067-17.067 25.6-38.4 29.867v0zM512 145.067c-38.4 17.067-166.4 64-298.667 64-51.2 0-98.133-8.533-136.533-21.333v597.333c21.333 8.533 85.333 25.6 162.133 25.6 98.133 0 183.467-29.867 256-89.6v-358.4l17.067 17.067v-234.667zM955.733 183.467c-42.667 17.067-89.6 25.6-140.8 25.6-128 0-251.733-51.2-290.133-64v238.933l17.067-17.067v349.867c68.267 59.733 153.6 89.6 256 89.6 76.8 0 136.533-17.067 162.133-25.6v-597.333z" />
|
||||
<glyph unicode="" glyph-name="attach" d="M960 866.133c-42.667 42.667-98.133 64-157.867 64s-115.2-21.333-157.867-64l-593.067-593.067c-34.133-34.133-55.467-85.333-51.2-136.533 0-42.667 17.067-81.067 46.933-110.933 34.133-38.4 81.067-59.733 132.267-59.733 46.933 0 93.867 17.067 128 51.2l541.867 546.133c25.6 25.6 42.667 64 42.667 98.133s-12.8 68.267-38.4 93.867c-25.6 25.6-59.733 38.4-98.133 38.4-34.133 0-72.533-17.067-98.133-42.667l-354.133-354.133c-4.267 0-4.267-4.267-4.267-12.8s4.267-12.8 8.533-17.067 25.6-8.533 34.133 0l354.133 354.133c12.8 17.067 38.4 25.6 59.733 25.6 25.6 0 51.2-12.8 68.267-34.133 8.533-12.8 17.067-25.6 17.067-42.667 4.267-25.6-4.267-55.467-25.6-72.533l-541.867-541.867c-25.6-25.6-55.467-38.4-93.867-38.4-34.133 0-68.267 12.8-93.867 38.4s-38.4 59.733-38.4 93.867c0 34.133 12.8 68.267 38.4 93.867l588.8 584.533c34.133 34.133 76.8 51.2 123.733 51.2s89.6-17.067 123.733-51.2c34.133-34.133 51.2-76.8 51.2-123.733s-17.067-89.6-51.2-123.733l-401.067-401.067c-4.267-4.267-8.533-12.8-8.533-17.067 0-8.533 4.267-12.8 8.533-17.067 8.533-8.533 25.6-8.533 34.133 0l401.067 401.067c89.6 89.6 89.6 230.4 4.267 320z" />
|
||||
<glyph unicode="" glyph-name="zone2" d="M98.133 17.067c-4.267 29.867-12.8 64-17.067 93.867-17.067 98.133-34.133 192-51.2 290.133-12.8 46.933-21.333 98.133-29.867 149.333 0 4.267 0 8.533 4.267 8.533 42.667 21.333 85.333 42.667 128 59.733 0 0 0 0 4.267 0 4.267-8.533 8.533-12.8 12.8-21.333-21.333-8.533-42.667-21.333-64-29.867-17.067-8.533-34.133-17.067-51.2-21.333-4.267 0-4.267-4.267-4.267-8.533 8.533-42.667 17.067-85.333 25.6-132.267 0-4.267 4.267-4.267 4.267-8.533 8.533-4.267 17.067-8.533 25.6-17.067 0-4.267-4.267-12.8-8.533-17.067-4.267 4.267-12.8 4.267-17.067 8.533 17.067-102.4 38.4-209.067 55.467-311.467 17.067 8.533 29.867 12.8 42.667 21.333 51.2 25.6 102.4 51.2 153.6 72.533 4.267 0 8.533 0 17.067 0 68.267-4.267 136.533-12.8 204.8-17.067 0 0 4.267 0 8.533 0-4.267 17.067-4.267 34.133-8.533 51.2-12.8 68.267-25.6 136.533-38.4 204.8 0 8.533-4.267 17.067-12.8 25.6-4.267 4.267-4.267 8.533-8.533 12.8 12.8 4.267 8.533 17.067 8.533 25.6-8.533 51.2-17.067 106.667-29.867 157.867 0 4.267 0 4.267-8.533 4.267-17.067 0-38.4 4.267-55.467 4.267 4.267 8.533 8.533 17.067 12.8 21.333 0 0 4.267 4.267 8.533 4.267 17.067 0 34.133-4.267 46.933-4.267 4.267 0 8.533 0 12.8 0 68.267 29.867 132.267 64 200.533 93.867 4.267 4.267 8.533 8.533 12.8 8.533 68.267-4.267 136.533-8.533 204.8-17.067 8.533 0 17.067 0 29.867-4.267 4.267 0 8.533-4.267 8.533-8.533 12.8-64 25.6-132.267 34.133-196.267 17.067-102.4 38.4-204.8 55.467-311.467 0-8.533 4.267-17.067 4.267-25.6-17.067 0-34.133 4.267-51.2 4.267-42.667 4.267-89.6 8.533-132.267 12.8-17.067 0-38.4 4.267-55.467 4.267-4.267 0-12.8 0-17.067-4.267-68.267-29.867-132.267-64-200.533-93.867 0 0-4.267 0-8.533 0-76.8 8.533-149.333 12.8-226.133 21.333-4.267 0-8.533 0-12.8 0-72.533-34.133-140.8-68.267-213.333-102.4 0-4.267 0-8.533-4.267-8.533zM989.867 217.6c0 4.267 0 4.267 0 8.533-8.533 34.133-12.8 72.533-21.333 106.667-8.533 46.933-17.067 89.6-25.6 136.533 0 8.533-4.267 12.8-8.533 17.067-8.533 4.267-12.8 12.8-21.333 17.067 4.267 8.533 8.533 12.8 12.8 17.067 4.267-4.267 8.533-4.267 12.8-8.533-4.267 12.8-4.267 21.333-4.267 34.133-8.533 46.933-17.067 93.867-25.6 145.067 0 4.267-4.267 8.533-8.533 8.533-68.267 4.267-136.533 12.8-209.067 17.067-4.267 0-8.533 0-12.8-4.267-64-29.867-123.733-59.733-187.733-85.333-4.267-4.267-8.533-4.267-4.267-12.8 4.267-29.867 12.8-64 17.067-93.867 4.267-21.333 8.533-42.667 12.8-59.733 12.8-4.267 12.8-12.8 21.333-21.333-12.8-4.267-12.8-12.8-12.8-25.6 12.8-68.267 25.6-132.267 38.4-200.533 4.267-25.6 8.533-51.2 12.8-76.8 4.267 0 4.267 0 8.533 4.267 59.733 29.867 119.467 59.733 183.467 89.6-4.267 4.267 0 4.267 4.267 4.267 51.2-4.267 106.667-8.533 157.867-12.8 21.333 0 38.4-4.267 59.733-4.267zM260.267 469.333c-12.8 17.067-25.6 34.133-38.4 46.933-29.867 46.933-59.733 93.867-85.333 145.067-12.8 29.867-21.333 64-17.067 102.4 8.533 51.2 34.133 85.333 81.067 102.4 55.467 21.333 123.733 8.533 162.133-34.133 34.133-34.133 42.667-76.8 34.133-123.733-8.533-42.667-25.6-76.8-46.933-115.2-25.6-42.667-55.467-81.067-85.333-123.733 0 4.267-4.267 0-4.267 0zM260.267 819.2c-46.933 0-81.067-34.133-81.067-81.067s38.4-81.067 81.067-81.067c46.933 0 81.067 38.4 85.333 81.067 0 42.667-38.4 81.067-85.333 81.067zM358.4 349.867c4.267-8.533 4.267-12.8 8.533-21.333-12.8-4.267-25.6-12.8-38.4-17.067-4.267 8.533-4.267 12.8-8.533 21.333 12.8 4.267 25.6 12.8 38.4 17.067zM226.133 302.933c0 8.533 4.267 17.067 4.267 21.333 12.8 0 25.6-4.267 38.4-4.267 0-8.533 0-12.8 0-25.6-12.8 8.533-29.867 8.533-42.667 8.533zM413.867 354.133c-4.267 8.533-8.533 12.8-12.8 21.333 12.8 8.533 21.333 17.067 34.133 25.6 4.267-4.267 8.533-12.8 12.8-17.067-12.8-12.8-21.333-21.333-34.133-29.867zM179.2 341.333c-4.267-8.533-4.267-12.8-8.533-21.333-12.8 4.267-25.6 8.533-38.4 17.067 4.267 8.533 4.267 12.8 8.533 21.333 12.8-8.533 25.6-12.8 38.4-17.067zM682.667 580.267c-12.8-8.533-21.333-17.067-34.133-21.333-4.267 4.267-8.533 12.8-12.8 17.067 12.8 8.533 25.6 17.067 38.4 25.6 4.267-8.533 4.267-17.067 8.533-21.333zM878.933 558.933c-4.267-8.533-8.533-12.8-12.8-21.333-12.8 8.533-25.6 17.067-34.133 21.333 4.267 8.533 8.533 12.8 8.533 21.333 12.8-8.533 25.6-17.067 38.4-21.333zM571.733 486.4c-4.267 4.267-8.533 12.8-12.8 17.067 8.533 8.533 21.333 21.333 29.867 29.867 4.267-4.267 8.533-12.8 12.8-17.067-8.533-8.533-17.067-21.333-29.867-29.867zM785.067 610.133c-4.267-8.533-4.267-17.067-8.533-21.333-12.8 0-25.6 4.267-38.4 4.267 0 8.533 0 12.8 0 21.333 17.067 0 29.867-4.267 46.933-4.267z" />
|
||||
|
|
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 109 KiB |
Binary file not shown.
Binary file not shown.
|
@ -403,8 +403,8 @@ module.exports = {
|
|||
back,
|
||||
backOnly,
|
||||
backWatch,
|
||||
backTestOnce,
|
||||
backTest,
|
||||
backTestOnce,
|
||||
e2e,
|
||||
i,
|
||||
install,
|
||||
|
|
|
@ -70,7 +70,8 @@ module.exports = {
|
|||
`front`,
|
||||
`modules`,
|
||||
`front/node_modules`,
|
||||
`node_modules`
|
||||
`node_modules`,
|
||||
`print`
|
||||
],
|
||||
|
||||
// An array of file extensions your modules use
|
||||
|
@ -153,6 +154,7 @@ module.exports = {
|
|||
// The glob patterns Jest uses to detect test files
|
||||
testMatch: [
|
||||
'**/front/**/*.spec.js',
|
||||
'**/print/**/*.spec.js',
|
||||
// 'loopback/**/*.spec.js',
|
||||
// 'modules/*/back/**/*.spec.js'
|
||||
// "**/__tests__/**/*.[jt]s?(x)",
|
||||
|
|
|
@ -134,5 +134,5 @@
|
|||
"This ticket is deleted": "Este ticket está eliminado",
|
||||
"A travel with this data already exists": "Ya existe un travel con estos datos",
|
||||
"This thermograph id already exists": "La id del termógrafo ya existe",
|
||||
"ORDER_ALREADY_CONFIRMED": "ORDER_ALREADY_CONFIRMED"
|
||||
"Choose a date range or days forward": "Selecciona un rango de fechas o días en adelante"
|
||||
}
|
|
@ -36,7 +36,7 @@ module.exports = Self => {
|
|||
relation: 'client',
|
||||
scope: {
|
||||
include: {
|
||||
relation: 'salesPerson'
|
||||
relation: 'salesPersonUser'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ module.exports = Self => {
|
|||
const updatedClaim = await claim.updateAttributes(data);
|
||||
|
||||
// Get sales person from claim client
|
||||
const salesPerson = claim.client().salesPerson();
|
||||
const salesPerson = claim.client().salesPersonUser();
|
||||
if (salesPerson && changedHasToPickUp && updatedClaim.hasToPickUp) {
|
||||
const origin = ctx.req.headers.origin;
|
||||
const message = $t('Claim will be picked', {
|
||||
|
|
|
@ -34,17 +34,7 @@ class Controller extends ModuleCard {
|
|||
scope: {
|
||||
fields: ['salesPersonFk', 'name', 'email'],
|
||||
include: {
|
||||
relation: 'salesPerson',
|
||||
scope: {
|
||||
fields: ['userFk'],
|
||||
include: {
|
||||
relation: 'user',
|
||||
scope: {
|
||||
fields: ['nickname']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
relation: 'salesPersonUser'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
</vn-label-value>
|
||||
<vn-label-value
|
||||
label="Salesperson"
|
||||
value="{{$ctrl.claim.client.salesPerson.user.nickname}}">
|
||||
value="{{$ctrl.claim.client.salesPersonUser.nickname}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value
|
||||
label="Attended by"
|
||||
|
@ -78,4 +78,4 @@
|
|||
on-accept="$ctrl.deleteClaim()"
|
||||
question="Delete claim"
|
||||
message="Are you sure you want to delete this claim?">
|
||||
</vn-confirm>
|
||||
</vn-confirm>
|
|
@ -42,11 +42,11 @@ module.exports = Self => {
|
|||
r.workerFk,
|
||||
c.code company,
|
||||
r.created,
|
||||
r.invoiceFk ref,
|
||||
r.invoiceFk description,
|
||||
NULL debit,
|
||||
r.amountPaid credit,
|
||||
r.bankFk,
|
||||
u.nickname userNickname,
|
||||
u.name userName,
|
||||
r.clientFk,
|
||||
FALSE hasPdf,
|
||||
FALSE isInvoice
|
||||
|
|
|
@ -46,7 +46,11 @@
|
|||
style="overflow: hidden; min-width: 14em;">
|
||||
<div class="ellipsize"><b>{{::address.nickname}} - #{{::address.id}}</b></div>
|
||||
<div class="ellipsize" name="street">{{::address.street}}</div>
|
||||
<div class="ellipsize">{{::address.city}}, {{::address.province.name}}</div>
|
||||
<div class="ellipsize">
|
||||
<span ng-show="::address.postalCode">{{::address.postalCode}} -</span>
|
||||
<span ng-show="::address.city">{{::address.city}},</span>
|
||||
{{::address.province.name}}
|
||||
</div>
|
||||
<div class="ellipsize">
|
||||
{{::address.phone}}<span ng-if="::address.mobile">, </span>
|
||||
{{::address.mobile}}
|
||||
|
|
|
@ -16,7 +16,8 @@ class Controller extends Section {
|
|||
'provinceFk',
|
||||
'phone',
|
||||
'mobile',
|
||||
'isEqualizated'
|
||||
'isEqualizated',
|
||||
'postalCode'
|
||||
],
|
||||
order: [
|
||||
'isDefaultAddress DESC',
|
||||
|
|
|
@ -17,11 +17,17 @@
|
|||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
url="Banks"
|
||||
label="Bank"
|
||||
url="Banks"
|
||||
show-field="bank"
|
||||
value-field="id"
|
||||
ng-model="$ctrl.receipt.bankFk">
|
||||
fields="['accountingTypeFk']"
|
||||
include="{relation: 'accountingType'}"
|
||||
order="id"
|
||||
ng-model="$ctrl.receipt.bankFk"
|
||||
search-function="{or: [{id: $search}, {bank: {like: '%'+ $search +'%'}}]}"
|
||||
selection="$ctrl.bankSelection">
|
||||
<tpl-item>{{id}}: {{bank}}</tpl-item>
|
||||
</vn-autocomplete>
|
||||
<vn-input-number
|
||||
vn-focus
|
||||
|
@ -31,6 +37,13 @@
|
|||
rule>
|
||||
</vn-input-number>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
label="Reference"
|
||||
ng-model="$ctrl.receipt.description"
|
||||
rule>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
</tpl-body>
|
||||
<tpl-buttons>
|
||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
||||
|
|
|
@ -50,6 +50,19 @@ class Controller extends Dialog {
|
|||
return this.receipt.description;
|
||||
}
|
||||
|
||||
get bankSelection() {
|
||||
return this._bankSelection;
|
||||
}
|
||||
|
||||
set bankSelection(value) {
|
||||
this._bankSelection = value;
|
||||
|
||||
if (value) {
|
||||
const accountingType = value.accountingType;
|
||||
this.receipt.description = accountingType && accountingType.receiptDescription;
|
||||
}
|
||||
}
|
||||
|
||||
getAmountPaid() {
|
||||
const filter = {
|
||||
where: {
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
import './index';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientBalancCreate', () => {
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
let $httpParamSerializer;
|
||||
|
||||
beforeEach(ngModule('client'));
|
||||
|
||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_, _$httpParamSerializer_) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
$httpParamSerializer = _$httpParamSerializer_;
|
||||
let $scope = $rootScope.$new();
|
||||
const $element = angular.element('<vn-client-balance-create></vn-client-balance-create>');
|
||||
const $transclude = {
|
||||
$$boundTransclude: {
|
||||
$$slots: []
|
||||
}
|
||||
};
|
||||
controller = $componentController('vnClientBalanceCreate', {$element, $scope, $transclude});
|
||||
controller.receipt = {
|
||||
clientFk: 101,
|
||||
companyFk: 442
|
||||
};
|
||||
}));
|
||||
|
||||
describe('bankSelection() setter', () => {
|
||||
it('should set the receipt description property', () => {
|
||||
controller.bankSelection = {
|
||||
id: 1,
|
||||
bank: 'Cash',
|
||||
accountingType: {
|
||||
id: 2,
|
||||
receiptDescription: 'Cash'
|
||||
}
|
||||
};
|
||||
|
||||
expect(controller.receipt.description).toEqual('Cash');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAmountPaid()', () => {
|
||||
it('should make an http GET query and then set the receipt amountPaid property', () => {
|
||||
controller.$params = {id: 101};
|
||||
const receipt = controller.receipt;
|
||||
const filter = {
|
||||
where: {
|
||||
clientFk: 101,
|
||||
companyFk: 442
|
||||
}
|
||||
};
|
||||
const serializedParams = $httpParamSerializer({filter});
|
||||
$httpBackend.expect('GET', `ClientRisks?${serializedParams}`,).respond([{amount: 20}]);
|
||||
controller.getAmountPaid();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(receipt.amountPaid).toEqual(20);
|
||||
});
|
||||
});
|
||||
|
||||
describe('responseHandler()', () => {
|
||||
it('should make an http POST query and then call to the parent responseHandler() method', () => {
|
||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
||||
|
||||
controller.$params = {id: 101};
|
||||
|
||||
$httpBackend.expect('POST', `Receipts`,).respond({id: 1});
|
||||
controller.responseHandler('accept');
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -68,25 +68,33 @@
|
|||
<span
|
||||
vn-click-stop="workerDescriptor.show($event, balance.workerFk)"
|
||||
class="link">
|
||||
{{::balance.userNickname}}
|
||||
{{::balance.userName}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td expand>
|
||||
<div ng-show="::balance.ref">
|
||||
<span
|
||||
ng-if="balance.isInvoice"
|
||||
title="{{'BILL' | translate: {ref: balance.ref} }}"
|
||||
vn-click-stop="$ctrl.showInvoiceOutDescriptor($event, balance)"
|
||||
class="link">
|
||||
{{'BILL' | translate: {ref: balance.ref} }}
|
||||
</span>
|
||||
<span
|
||||
ng-if="!balance.isInvoice"
|
||||
title="{{::balance.ref}}">
|
||||
{{::balance.ref}}
|
||||
</span>
|
||||
</div>
|
||||
</vn-td>
|
||||
<vn-td-editable disabled="balance.isInvoice || !$ctrl.isAdministrative" expand>
|
||||
<text>
|
||||
<div ng-show="::balance.description">
|
||||
<span
|
||||
ng-if="balance.isInvoice"
|
||||
title="{{'BILL' | translate: {ref: balance.description} }}"
|
||||
vn-click-stop="$ctrl.showInvoiceOutDescriptor($event, balance)"
|
||||
class="link">
|
||||
{{'BILL' | translate: {ref: balance.description} }}
|
||||
</span>
|
||||
<span
|
||||
ng-if="!balance.isInvoice"
|
||||
title="{{::balance.description}}">
|
||||
{{balance.description}}
|
||||
</span>
|
||||
</div>
|
||||
</text>
|
||||
<field>
|
||||
<vn-textfield vn-acl="administrative" class="dense" vn-focus
|
||||
ng-model="balance.description"
|
||||
on-change="$ctrl.changeDescription(balance)">
|
||||
</vn-textfield>
|
||||
</field>
|
||||
</vn-td-editable>
|
||||
<vn-td number>{{::balance.bankFk}}</vn-td>
|
||||
<vn-td number expand>{{::balance.debit | currency: 'EUR':2}}</vn-td>
|
||||
<vn-td number expand>{{::balance.credit | currency: 'EUR':2}}</vn-td>
|
||||
|
|
|
@ -39,6 +39,10 @@ class Controller extends Section {
|
|||
this.getBalances();
|
||||
}
|
||||
|
||||
get isAdministrative() {
|
||||
return this.aclService.hasAny(['administrative']);
|
||||
}
|
||||
|
||||
getData() {
|
||||
return this.$.model.applyFilter(null, {
|
||||
clientId: this.$params.id,
|
||||
|
@ -58,7 +62,7 @@ class Controller extends Section {
|
|||
return balance.companyFk === selectedCompany;
|
||||
});
|
||||
|
||||
return currentBalance.amount;
|
||||
return currentBalance && currentBalance.amount;
|
||||
}
|
||||
|
||||
getBalances() {
|
||||
|
@ -79,6 +83,13 @@ class Controller extends Section {
|
|||
|
||||
this.$.invoiceOutDescriptor.show(event.target, balance.id);
|
||||
}
|
||||
|
||||
changeDescription(balance) {
|
||||
const params = {description: balance.description};
|
||||
const endpoint = `Receipts/${balance.id}`;
|
||||
this.$http.patch(endpoint, params)
|
||||
.then(() => this.vnApp.showSuccess(this.$t('Data saved!')));
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope'];
|
||||
|
|
|
@ -3,10 +3,12 @@ import './index';
|
|||
describe('Client', () => {
|
||||
describe('Component vnClientBalanceIndex', () => {
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
|
||||
beforeEach(ngModule('client'));
|
||||
|
||||
beforeEach(inject(($componentController, $rootScope) => {
|
||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
let $scope = $rootScope.$new();
|
||||
const $element = angular.element('<vn-client-balance-index></vn-client-balance-index>');
|
||||
controller = $componentController('vnClientBalanceIndex', {$element, $scope});
|
||||
|
@ -133,5 +135,21 @@ describe('Client', () => {
|
|||
expect(controller.getBalances).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('changeDescription()', () => {
|
||||
it('should make an http PATCH query', () => {
|
||||
const expectedParams = {description: 'Web'};
|
||||
|
||||
$httpBackend.expect('PATCH', `Receipts/1`, expectedParams).respond(200);
|
||||
controller.changeDescription({
|
||||
id: 1,
|
||||
description: 'Web',
|
||||
accountingType: {
|
||||
description: 'Cash'
|
||||
}
|
||||
});
|
||||
$httpBackend.flush();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethod('editLatestBuys', {
|
||||
description: 'Updates a column for one or more buys',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'field',
|
||||
type: 'String',
|
||||
required: true,
|
||||
description: `the column to edit`
|
||||
},
|
||||
{
|
||||
arg: 'newValue',
|
||||
type: 'Any',
|
||||
required: true,
|
||||
description: `The new value to save`
|
||||
},
|
||||
{
|
||||
arg: 'lines',
|
||||
type: ['Object'],
|
||||
required: true,
|
||||
description: `the buys which will be modified`
|
||||
}],
|
||||
returns: {
|
||||
type: 'Object',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/editLatestBuys`,
|
||||
verb: 'POST'
|
||||
}
|
||||
});
|
||||
|
||||
Self.editLatestBuys = async(field, newValue, lines) => {
|
||||
let modelName;
|
||||
let identifier;
|
||||
|
||||
switch (field) {
|
||||
case 'size':
|
||||
case 'density':
|
||||
case 'minPrice':
|
||||
case 'description':
|
||||
modelName = 'Item';
|
||||
identifier = 'itemFk';
|
||||
break;
|
||||
case 'quantity':
|
||||
case 'buyingValue':
|
||||
case 'freightValue':
|
||||
case 'packing':
|
||||
case 'grouping':
|
||||
case 'groupingMode':
|
||||
case 'comissionValue':
|
||||
case 'packageValue':
|
||||
case 'price2':
|
||||
case 'price3':
|
||||
case 'weight':
|
||||
modelName = 'Buy';
|
||||
identifier = 'id';
|
||||
}
|
||||
|
||||
const models = Self.app.models;
|
||||
const model = models[modelName];
|
||||
|
||||
let tx = await model.beginTransaction({});
|
||||
|
||||
try {
|
||||
let promises = [];
|
||||
let options = {transaction: tx};
|
||||
|
||||
let targets = lines.map(line => {
|
||||
return line[identifier];
|
||||
});
|
||||
|
||||
let value = {};
|
||||
value[field] = newValue;
|
||||
|
||||
// intentarlo con updateAll
|
||||
for (let target of targets)
|
||||
promises.push(model.upsertWithWhere({id: target}, value, options));
|
||||
|
||||
await Promise.all(promises);
|
||||
await tx.commit();
|
||||
} catch (error) {
|
||||
await tx.rollback();
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
};
|
|
@ -0,0 +1,171 @@
|
|||
|
||||
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('latestBuysFilter', {
|
||||
description: 'Find all instances of the model matched by filter from the data source.',
|
||||
accessType: 'READ',
|
||||
accepts: [
|
||||
{
|
||||
arg: 'filter',
|
||||
type: 'Object',
|
||||
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
|
||||
},
|
||||
{
|
||||
arg: 'search',
|
||||
type: 'String',
|
||||
description: `If it's and integer searchs by id, otherwise it searchs by name`,
|
||||
}, {
|
||||
arg: 'id',
|
||||
type: 'Integer',
|
||||
description: 'Item id',
|
||||
}, {
|
||||
arg: 'tags',
|
||||
type: ['Object'],
|
||||
description: 'List of tags to filter with',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'description',
|
||||
type: 'String',
|
||||
description: 'The item description',
|
||||
}, {
|
||||
arg: 'salesPersonFk',
|
||||
type: 'Integer',
|
||||
description: 'The buyer of the item',
|
||||
}, {
|
||||
arg: 'active',
|
||||
type: 'Boolean',
|
||||
description: 'Whether the the item is or not active',
|
||||
}, {
|
||||
arg: 'visible',
|
||||
type: 'Boolean',
|
||||
description: 'Whether the the item is or not visible',
|
||||
}, {
|
||||
arg: 'typeFk',
|
||||
type: 'Integer',
|
||||
description: 'Type id',
|
||||
}, {
|
||||
arg: 'categoryFk',
|
||||
type: 'Integer',
|
||||
description: 'Category id',
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: ['Object'],
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/latestBuysFilter`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.latestBuysFilter = async(ctx, filter) => {
|
||||
let conn = Self.dataSource.connector;
|
||||
let where = buildFilter(ctx.args, (param, value) => {
|
||||
switch (param) {
|
||||
case 'search':
|
||||
return /^\d+$/.test(value)
|
||||
? {'i.id': value}
|
||||
: {'i.name': {like: `%${value}%`}};
|
||||
case 'id':
|
||||
return {'i.id': value};
|
||||
case 'description':
|
||||
return {'i.description': {like: `%${value}%`}};
|
||||
case 'categoryFk':
|
||||
return {'ic.id': value};
|
||||
case 'salesPersonFk':
|
||||
return {'it.workerFk': value};
|
||||
case 'typeFk':
|
||||
return {'i.typeFk': value};
|
||||
case 'active':
|
||||
return {'i.isActive': value};
|
||||
case 'visible':
|
||||
if (value)
|
||||
return {'v.visible': {gt: 0}};
|
||||
else if (!value)
|
||||
return {'v.visible': {lte: 0}};
|
||||
}
|
||||
});
|
||||
filter = mergeFilters(ctx.args.filter, {where});
|
||||
|
||||
let stmts = [];
|
||||
let stmt;
|
||||
|
||||
stmts.push('CALL cache.last_buy_refresh(FALSE)');
|
||||
stmts.push('CALL cache.visible_refresh(@calc_id, FALSE, 1)');
|
||||
|
||||
stmt = new ParameterizedSQL(`
|
||||
SELECT
|
||||
i.image,
|
||||
i.id AS itemFk,
|
||||
i.size,
|
||||
i.density,
|
||||
i.typeFk,
|
||||
i.family,
|
||||
i.isActive,
|
||||
i.minPrice,
|
||||
i.description,
|
||||
t.name AS type,
|
||||
intr.description AS intrastat,
|
||||
ori.code AS origin,
|
||||
b.entryFk,
|
||||
b.id,
|
||||
b.quantity,
|
||||
b.buyingValue,
|
||||
b.freightValue,
|
||||
b.isIgnored,
|
||||
b.packing,
|
||||
b.grouping,
|
||||
b.groupingMode,
|
||||
b.comissionValue,
|
||||
b.packageValue,
|
||||
b.price2,
|
||||
b.price3,
|
||||
b.ektFk,
|
||||
b.weight
|
||||
FROM cache.last_buy lb
|
||||
LEFT JOIN cache.visible v ON v.item_id = lb.item_id
|
||||
AND v.calc_id = @calc_id
|
||||
JOIN item i ON i.id = lb.item_id
|
||||
JOIN itemType it ON it.id = i.typeFk AND lb.warehouse_id = it.warehouseFk
|
||||
JOIN buy b ON b.id = lb.buy_id
|
||||
LEFT JOIN itemCategory ic ON ic.id = it.categoryFk
|
||||
LEFT JOIN itemType t ON t.id = i.typeFk
|
||||
LEFT JOIN intrastat intr ON intr.id = i.intrastatFk
|
||||
LEFT JOIN origin ori ON ori.id = i.originFk`
|
||||
);
|
||||
|
||||
if (ctx.args.tags) {
|
||||
let i = 1;
|
||||
for (const tag of ctx.args.tags) {
|
||||
const tAlias = `it${i++}`;
|
||||
|
||||
if (tag.tagFk) {
|
||||
stmt.merge({
|
||||
sql: `JOIN vn.itemTag ${tAlias} ON ${tAlias}.itemFk = i.id
|
||||
AND ${tAlias}.tagFk = ?
|
||||
AND ${tAlias}.value LIKE ?`,
|
||||
params: [tag.tagFk, `%${tag.value}%`],
|
||||
});
|
||||
} else {
|
||||
stmt.merge({
|
||||
sql: `JOIN vn.itemTag ${tAlias} ON ${tAlias}.itemFk = i.id
|
||||
AND ${tAlias}.value LIKE ?`,
|
||||
params: [`%${tag.value}%`],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stmt.merge(conn.makeSuffix(filter));
|
||||
let buysIndex = stmts.push(stmt) - 1;
|
||||
|
||||
let sql = ParameterizedSQL.join(stmts, ';');
|
||||
let result = await conn.executeStmt(sql);
|
||||
return buysIndex === 0 ? result : result[buysIndex];
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
const model = app.models.Buy;
|
||||
|
||||
describe('Buy editLatestsBuys()', () => {
|
||||
it('should change the value of a given column for the selected buys', async() => {
|
||||
let ctx = {
|
||||
args: {
|
||||
search: 'Ranged weapon longbow 2m'
|
||||
}
|
||||
};
|
||||
|
||||
let [original] = await model.latestBuysFilter(ctx);
|
||||
|
||||
const field = 'size';
|
||||
let newValue = 99;
|
||||
const lines = [{itemFk: original.itemFk, id: original.id}];
|
||||
|
||||
await model.editLatestBuys(field, newValue, lines);
|
||||
|
||||
let [result] = await model.latestBuysFilter(ctx);
|
||||
|
||||
expect(result.size).toEqual(99);
|
||||
|
||||
newValue = original.size;
|
||||
await model.editLatestBuys(field, newValue, lines);
|
||||
|
||||
let [restoredFixture] = await model.latestBuysFilter(ctx);
|
||||
|
||||
expect(restoredFixture.size).toEqual(original.size);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,139 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
describe('Buy latests buys filter()', () => {
|
||||
it('should return the entry matching "search"', async() => {
|
||||
let ctx = {
|
||||
args: {
|
||||
search: 'Ranged weapon longbow 2m'
|
||||
}
|
||||
};
|
||||
|
||||
let results = await app.models.Buy.latestBuysFilter(ctx);
|
||||
let firstBuy = results[0];
|
||||
|
||||
expect(results.length).toEqual(1);
|
||||
expect(firstBuy.size).toEqual(70);
|
||||
});
|
||||
|
||||
it('should return the entry matching "id"', async() => {
|
||||
let ctx = {
|
||||
args: {
|
||||
id: 1
|
||||
}
|
||||
};
|
||||
|
||||
let results = await app.models.Buy.latestBuysFilter(ctx);
|
||||
|
||||
expect(results.length).toEqual(1);
|
||||
});
|
||||
|
||||
it('should return results matching "tags"', async() => {
|
||||
let ctx = {
|
||||
args: {
|
||||
tags: [
|
||||
{tagFk: 27, value: '2m'}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
let results = await app.models.Buy.latestBuysFilter(ctx);
|
||||
|
||||
expect(results.length).toBe(2);
|
||||
});
|
||||
|
||||
it('should return results matching "categoryFk"', async() => {
|
||||
let ctx = {
|
||||
args: {
|
||||
categoryFk: 1
|
||||
}
|
||||
};
|
||||
|
||||
let results = await app.models.Buy.latestBuysFilter(ctx);
|
||||
|
||||
expect(results.length).toBe(4);
|
||||
});
|
||||
|
||||
it('should return results matching "typeFk"', async() => {
|
||||
let ctx = {
|
||||
args: {
|
||||
typeFk: 2
|
||||
}
|
||||
};
|
||||
|
||||
let results = await app.models.Buy.latestBuysFilter(ctx);
|
||||
|
||||
expect(results.length).toBe(4);
|
||||
});
|
||||
|
||||
it('should return results matching "active"', async() => {
|
||||
let ctx = {
|
||||
args: {
|
||||
active: true
|
||||
}
|
||||
};
|
||||
|
||||
let results = await app.models.Buy.latestBuysFilter(ctx);
|
||||
|
||||
expect(results.length).toBe(6);
|
||||
});
|
||||
|
||||
it('should return results matching "not active"', async() => {
|
||||
let ctx = {
|
||||
args: {
|
||||
active: false
|
||||
}
|
||||
};
|
||||
|
||||
let results = await app.models.Buy.latestBuysFilter(ctx);
|
||||
|
||||
expect(results.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should return results matching "visible"', async() => {
|
||||
let ctx = {
|
||||
args: {
|
||||
visible: true
|
||||
}
|
||||
};
|
||||
|
||||
let results = await app.models.Buy.latestBuysFilter(ctx);
|
||||
|
||||
expect(results.length).toBe(5);
|
||||
});
|
||||
|
||||
it('should return results matching "not visible"', async() => {
|
||||
let ctx = {
|
||||
args: {
|
||||
visible: false
|
||||
}
|
||||
};
|
||||
|
||||
let results = await app.models.Buy.latestBuysFilter(ctx);
|
||||
|
||||
expect(results.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should return results matching "salesPersonFk"', async() => {
|
||||
let ctx = {
|
||||
args: {
|
||||
salesPersonFk: 35
|
||||
}
|
||||
};
|
||||
|
||||
let results = await app.models.Buy.latestBuysFilter(ctx);
|
||||
|
||||
expect(results.length).toBe(6);
|
||||
});
|
||||
|
||||
it('should return results matching "description"', async() => {
|
||||
let ctx = {
|
||||
args: {
|
||||
description: 'Increases block'
|
||||
}
|
||||
};
|
||||
|
||||
let results = await app.models.Buy.latestBuysFilter(ctx);
|
||||
|
||||
expect(results.length).toBe(1);
|
||||
});
|
||||
});
|
|
@ -2,6 +2,9 @@
|
|||
"Entry": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"Buy": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"EntryLog": {
|
||||
"dataSource": "vn"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
module.exports = Self => {
|
||||
require('../methods/entry/editLatestBuys')(Self);
|
||||
require('../methods/entry/latestBuysFilter')(Self);
|
||||
};
|
|
@ -0,0 +1,61 @@
|
|||
{
|
||||
"name": "Buy",
|
||||
"base": "Loggable",
|
||||
"log": {
|
||||
"model": "EntryLog",
|
||||
"relation": "entry"
|
||||
},
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "buy"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
"quantity": {
|
||||
"type": "number"
|
||||
},
|
||||
"buyingValue": {
|
||||
"type": "number"
|
||||
},
|
||||
"freightValue": {
|
||||
"type": "number"
|
||||
},
|
||||
"packing": {
|
||||
"type": "number"
|
||||
},
|
||||
"grouping": {
|
||||
"type": "number"
|
||||
},
|
||||
"groupingMode": {
|
||||
"type": "number"
|
||||
},
|
||||
"comissionValue": {
|
||||
"type": "number"
|
||||
},
|
||||
"packageValue": {
|
||||
"type": "number"
|
||||
},
|
||||
"price2": {
|
||||
"type": "number"
|
||||
},
|
||||
"price3": {
|
||||
"type": "number"
|
||||
},
|
||||
"weight": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
"entry": {
|
||||
"type": "belongsTo",
|
||||
"model": "Entry",
|
||||
"foreignKey": "entryFk",
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
module.exports = Self => {
|
||||
require('../methods/entry/filter')(Self);
|
||||
require('../methods/entry/getEntry')(Self);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "Entry",
|
||||
"base": "VnModel",
|
||||
"base": "Loggable",
|
||||
"log": {
|
||||
"model":"EntryLog"
|
||||
},
|
||||
|
@ -62,6 +62,18 @@
|
|||
},
|
||||
"loadPriority": {
|
||||
"type": "number"
|
||||
},
|
||||
"supplierFk": {
|
||||
"type": "number",
|
||||
"required": true
|
||||
},
|
||||
"travelFk": {
|
||||
"type": "number",
|
||||
"required": true
|
||||
},
|
||||
"companyFk": {
|
||||
"type": "number",
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'salix/components/section';
|
||||
|
||||
ngModule.vnComponent('vnEntryBasicData', {
|
||||
template: require('./index.html'),
|
||||
controller: Section,
|
||||
bindings: {
|
||||
entry: '<'
|
||||
}
|
||||
});
|
|
@ -10,7 +10,8 @@ class Controller extends ModuleCard {
|
|||
scope: {
|
||||
fields: ['id', 'code']
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
relation: 'travel',
|
||||
scope: {
|
||||
fields: ['id', 'landed', 'agencyFk', 'warehouseOutFk'],
|
||||
|
@ -35,12 +36,14 @@ class Controller extends ModuleCard {
|
|||
}
|
||||
]
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
relation: 'supplier',
|
||||
scope: {
|
||||
fields: ['id', 'nickname']
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
relation: 'currency'
|
||||
}
|
||||
]
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
<mg-ajax path="Entries" options="vnPost"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.entry"
|
||||
form="form"
|
||||
save="post">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
|
||||
<vn-card class="vn-pa-lg">
|
||||
<vn-icon color-marginal
|
||||
icon="info"
|
||||
vn-tooltip="Required fields (*)">
|
||||
</vn-icon>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
ng-model="$ctrl.entry.supplierFk"
|
||||
url="Suppliers"
|
||||
show-field="nickname"
|
||||
search-function="{or: [{id: $search}, {nickname: {like: '%'+ $search +'%'}}]}"
|
||||
value-field="id"
|
||||
order="nickname"
|
||||
label="Supplier"
|
||||
required="true">
|
||||
<tpl-item>
|
||||
{{::id}} - {{::nickname}}
|
||||
</tpl-item>
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
ng-model="$ctrl.entry.travelFk"
|
||||
url="Travels/filter"
|
||||
search-function="$ctrl.searchFunction($search)"
|
||||
value-field="id"
|
||||
order="id"
|
||||
label="Travel"
|
||||
required="true">
|
||||
<tpl-item>
|
||||
{{::agencyModeName}} - {{::warehouseInName}} ({{::shipped | date: 'dd/MM/yyyy'}}) →
|
||||
{{::warehouseOutName}} ({{::landed | date: 'dd/MM/yyyy'}})
|
||||
</tpl-item>
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
url="Companies"
|
||||
label="Company"
|
||||
show-field="code"
|
||||
value-field="id"
|
||||
ng-model="$ctrl.entry.companyFk"
|
||||
required="true">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Create"></vn-submit>
|
||||
<vn-button ui-sref="entry.index" label="Cancel"></vn-button>
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -0,0 +1,43 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'salix/components/section';
|
||||
import './style.scss';
|
||||
|
||||
export default class Controller extends Section {
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
|
||||
this.entry = {
|
||||
companyFk: this.vnConfig.companyFk
|
||||
};
|
||||
|
||||
if (this.$params && this.$params.supplierFk)
|
||||
this.entry.supplierFk = parseInt(this.$params.supplierFk);
|
||||
if (this.$params && this.$params.travelFk)
|
||||
this.entry.travelFk = parseInt(this.$params.travelFk);
|
||||
if (this.$params && this.$params.companyFk)
|
||||
this.entry.companyFk = parseInt(this.$params.companyFk);
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
this.$.watcher.submit().then(
|
||||
res => this.$state.go('entry.card.basicData', {id: res.data.id})
|
||||
);
|
||||
}
|
||||
|
||||
searchFunction($search) {
|
||||
return {or: [
|
||||
{'agencyModeName': {like: `%${$search}%`}},
|
||||
{'warehouseInName': {like: `%${$search}%`}},
|
||||
{'warehouseOutName': {like: `%${$search}%`}},
|
||||
{'shipped': new Date($search)},
|
||||
{'landed': new Date($search)}
|
||||
]};
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope'];
|
||||
|
||||
ngModule.vnComponent('vnEntryCreate', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -0,0 +1,2 @@
|
|||
New entry: Nueva entrada
|
||||
Required fields (*): Campos requeridos (*)
|
|
@ -0,0 +1,10 @@
|
|||
vn-entry-create {
|
||||
vn-card {
|
||||
position: relative
|
||||
}
|
||||
vn-icon[icon="info"] {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 16px
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
<slot-descriptor>
|
||||
<vn-entry-descriptor></vn-entry-descriptor>
|
||||
</slot-descriptor>
|
|
@ -0,0 +1,9 @@
|
|||
import ngModule from '../module';
|
||||
import DescriptorPopover from 'salix/components/descriptor-popover';
|
||||
|
||||
class Controller extends DescriptorPopover {}
|
||||
|
||||
ngModule.vnComponent('vnEntryDescriptorPopover', {
|
||||
slotTemplate: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -11,15 +11,23 @@ class Controller extends Descriptor {
|
|||
}
|
||||
|
||||
get travelFilter() {
|
||||
return this.entry && JSON.stringify({
|
||||
agencyFk: this.entry.travel.agencyFk
|
||||
});
|
||||
let travelFilter;
|
||||
const entryTravel = this.entry && this.entry.travel;
|
||||
|
||||
if (entryTravel && entryTravel.agencyFk) {
|
||||
travelFilter = this.entry && JSON.stringify({
|
||||
agencyFk: entryTravel.agencyFk
|
||||
});
|
||||
}
|
||||
return travelFilter;
|
||||
}
|
||||
|
||||
get entryFilter() {
|
||||
if (!this.entry) return null;
|
||||
let entryTravel = this.entry && this.entry.travel;
|
||||
|
||||
const date = new Date(this.entry.travel.landed);
|
||||
if (!entryTravel || !entryTravel.landed) return null;
|
||||
|
||||
const date = new Date(entryTravel.landed);
|
||||
date.setHours(0, 0, 0, 0);
|
||||
|
||||
const from = new Date(date.getTime());
|
||||
|
@ -35,6 +43,48 @@ class Controller extends Descriptor {
|
|||
});
|
||||
}
|
||||
|
||||
loadData() {
|
||||
const filter = {
|
||||
include: [
|
||||
{
|
||||
relation: 'travel',
|
||||
scope: {
|
||||
fields: ['id', 'landed', 'agencyFk', 'warehouseOutFk'],
|
||||
include: [
|
||||
{
|
||||
relation: 'agency',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
},
|
||||
{
|
||||
relation: 'warehouseOut',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
},
|
||||
{
|
||||
relation: 'warehouseIn',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
relation: 'supplier',
|
||||
scope: {
|
||||
fields: ['id', 'nickname']
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
return this.getData(`Entries/${this.id}`, {filter})
|
||||
.then(res => this.entity = res.data);
|
||||
}
|
||||
|
||||
showEntryReport() {
|
||||
this.vnReport.show('entry-order', {
|
||||
entryId: this.entry.id
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import './index.js';
|
||||
|
||||
describe('Entry Component vnEntryDescriptor', () => {
|
||||
let $httpBackend;
|
||||
let controller;
|
||||
const entry = {id: 2};
|
||||
|
||||
beforeEach(ngModule('entry'));
|
||||
|
||||
beforeEach(inject($componentController => {
|
||||
beforeEach(inject(($componentController, _$httpBackend_) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
controller = $componentController('vnEntryDescriptor', {$element: null}, {entry});
|
||||
}));
|
||||
|
||||
|
@ -24,4 +26,18 @@ describe('Entry Component vnEntryDescriptor', () => {
|
|||
expect(controller.vnReport.show).toHaveBeenCalledWith('entry-order', params);
|
||||
});
|
||||
});
|
||||
|
||||
describe('loadData()', () => {
|
||||
it('should perform ask for the entry', () => {
|
||||
let query = `Entries/${entry.id}`;
|
||||
jest.spyOn(controller, 'getData');
|
||||
|
||||
$httpBackend.expectGET(query).respond();
|
||||
controller.loadData();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.getData).toHaveBeenCalledTimes(1);
|
||||
expect(controller.getData).toHaveBeenCalledWith(query, jasmine.any(Object));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,8 +2,12 @@ export * from './module';
|
|||
|
||||
import './main';
|
||||
import './index/';
|
||||
import './create';
|
||||
import './latest-buys';
|
||||
import './search-panel';
|
||||
import './latest-buys-search-panel';
|
||||
import './descriptor';
|
||||
import './descriptor-popover';
|
||||
import './card';
|
||||
import './summary';
|
||||
import './log';
|
||||
|
|
|
@ -69,4 +69,16 @@
|
|||
</vn-data-viewer>
|
||||
<vn-travel-descriptor-popover
|
||||
vn-id="travelDescriptor">
|
||||
</vn-travel-descriptor-popover>
|
||||
</vn-travel-descriptor-popover>
|
||||
|
||||
<div fixed-bottom-right>
|
||||
<vn-vertical style="align-items: center;">
|
||||
<a ui-sref="entry.create" vn-bind="+">
|
||||
<vn-button class="round md vn-mb-sm"
|
||||
icon="add"
|
||||
vn-tooltip="New entry"
|
||||
tooltip-position="left">
|
||||
</vn-button>
|
||||
</a>
|
||||
</vn-vertical>
|
||||
</div>
|
|
@ -12,4 +12,6 @@ Reference: Referencia
|
|||
Created: Creado
|
||||
Booked: Facturado
|
||||
Is inventory: Inventario
|
||||
Notes: Notas
|
||||
Notes: Notas
|
||||
Status: Estado
|
||||
Selection: Selección
|
|
@ -0,0 +1,167 @@
|
|||
<mg-ajax path="Tags" options="mgIndex as tags"></mg-ajax>
|
||||
<div class="search-panel">
|
||||
<form ng-submit="$ctrl.onSearch()">
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
label="General search"
|
||||
ng-model="filter.search"
|
||||
info="Search items by id, name or barcode"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
vn-focus
|
||||
url="ItemCategories"
|
||||
label="Category"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
ng-model="filter.categoryFk">
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete
|
||||
url="ItemTypes"
|
||||
label="Type"
|
||||
where="{categoryFk: filter.categoryFk}"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
ng-model="filter.typeFk"
|
||||
fields="['categoryFk']"
|
||||
include="'category'">
|
||||
<tpl-item>
|
||||
<div>{{name}}</div>
|
||||
<div class="text-caption text-secondary">
|
||||
{{category.name}}
|
||||
</div>
|
||||
</tpl-item>>
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
disabled="false"
|
||||
ng-model="filter.salesPersonFk"
|
||||
url="Clients/activeWorkersWithRole"
|
||||
show-field="nickname"
|
||||
search-function="{firstName: $search}"
|
||||
value-field="id"
|
||||
where="{role: 'employee'}"
|
||||
label="Buyer">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-check
|
||||
label="Is active"
|
||||
ng-model="filter.active"
|
||||
triple-state="true">
|
||||
</vn-check>
|
||||
<vn-check
|
||||
label="Is visible"
|
||||
ng-model="filter.visible"
|
||||
triple-state="true">
|
||||
</vn-check>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal class="vn-pt-sm">
|
||||
<vn-one class="text-subtitle1" translate>
|
||||
Tags
|
||||
</vn-one>
|
||||
<vn-icon-button
|
||||
vn-none
|
||||
vn-bind="+"
|
||||
vn-tooltip="Add tag"
|
||||
icon="add_circle"
|
||||
ng-click="filter.tags.push({})">
|
||||
</vn-icon-button>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal ng-repeat="itemTag in filter.tags">
|
||||
<vn-autocomplete
|
||||
vn-id="tag"
|
||||
ng-model="itemTag.tagFk"
|
||||
data="tags.model"
|
||||
show-field="name"
|
||||
label="Tag"
|
||||
on-change="itemTag.value = null">
|
||||
</vn-autocomplete>
|
||||
<vn-textfield
|
||||
ng-show="tag.selection.isFree !== false"
|
||||
vn-id="text"
|
||||
label="Value"
|
||||
ng-model="itemTag.value">
|
||||
</vn-textfield>
|
||||
<vn-autocomplete
|
||||
ng-show="tag.selection.isFree === false"
|
||||
url="{{$ctrl.getSourceTable(tag.selection)}}"
|
||||
label="Value"
|
||||
ng-model="itemTag.value"
|
||||
show-field="name"
|
||||
value-field="name">
|
||||
</vn-autocomplete>
|
||||
<vn-icon-button
|
||||
vn-none
|
||||
vn-tooltip="Remove tag"
|
||||
icon="delete"
|
||||
ng-click="filter.tags.splice($index, 1)"
|
||||
tabindex="-1">
|
||||
</vn-icon-button>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal class="vn-pt-sm">
|
||||
<vn-one class="text-subtitle1" translate>
|
||||
More fields
|
||||
</vn-one>
|
||||
<vn-icon-button
|
||||
vn-none
|
||||
vn-bind="+"
|
||||
vn-tooltip="Add field"
|
||||
icon="add_circle"
|
||||
ng-click="$ctrl.fieldFilters.push({})">
|
||||
</vn-icon-button>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal ng-repeat="fieldFilter in $ctrl.fieldFilters">
|
||||
<vn-autocomplete
|
||||
label="Field"
|
||||
ng-model="fieldFilter.name"
|
||||
data="$ctrl.moreFields"
|
||||
value-field="name"
|
||||
show-field="label"
|
||||
show-filter="false"
|
||||
translate-fields="['label']"
|
||||
selection="info"
|
||||
on-change="fieldFilter.value = null">
|
||||
</vn-autocomplete>
|
||||
<vn-one ng-switch="info.type">
|
||||
<div ng-switch-when="Number">
|
||||
<vn-input-number
|
||||
label="Value"
|
||||
ng-model="fieldFilter.value">
|
||||
</vn-input-number>
|
||||
</div>
|
||||
<div ng-switch-when="Boolean">
|
||||
<vn-check
|
||||
label="Value"
|
||||
ng-model="fieldFilter.value">
|
||||
</vn-check>
|
||||
</div>
|
||||
<div ng-switch-when="Date">
|
||||
<vn-date-picker
|
||||
label="Value"
|
||||
ng-model="fieldFilter.value">
|
||||
</vn-date-picker>
|
||||
</div>
|
||||
<div ng-switch-default>
|
||||
<vn-textfield
|
||||
label="Value"
|
||||
ng-model="fieldFilter.value">
|
||||
</vn-textfield>
|
||||
</div>
|
||||
</vn-one>
|
||||
<vn-icon-button
|
||||
vn-none
|
||||
vn-tooltip="Remove field"
|
||||
icon="delete"
|
||||
ng-click="$ctrl.removeField($index, fieldFilter.name)"
|
||||
tabindex="-1">
|
||||
</vn-icon-button>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal class="vn-mt-lg">
|
||||
<vn-submit label="Search"></vn-submit>
|
||||
</vn-horizontal>
|
||||
</form>
|
||||
</div>
|
|
@ -0,0 +1,79 @@
|
|||
import ngModule from '../module';
|
||||
import SearchPanel from 'core/components/searchbar/search-panel';
|
||||
|
||||
class Controller extends SearchPanel {
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
let model = 'Item';
|
||||
let moreFields = ['description', 'name'];
|
||||
|
||||
let properties;
|
||||
let validations = window.validations;
|
||||
|
||||
if (validations && validations[model])
|
||||
properties = validations[model].properties;
|
||||
else
|
||||
properties = {};
|
||||
|
||||
this.moreFields = [];
|
||||
for (let field of moreFields) {
|
||||
let prop = properties[field];
|
||||
this.moreFields.push({
|
||||
name: field,
|
||||
label: prop ? prop.description : field,
|
||||
type: prop ? prop.type : null
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
get filter() {
|
||||
let filter = this.$.filter;
|
||||
|
||||
for (let fieldFilter of this.fieldFilters)
|
||||
filter[fieldFilter.name] = fieldFilter.value;
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
set filter(value) {
|
||||
if (!value)
|
||||
value = {};
|
||||
if (!value.tags)
|
||||
value.tags = [{}];
|
||||
|
||||
this.fieldFilters = [];
|
||||
for (let field of this.moreFields) {
|
||||
if (value[field.name] != undefined) {
|
||||
this.fieldFilters.push({
|
||||
name: field.name,
|
||||
value: value[field.name],
|
||||
info: field
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.$.filter = value;
|
||||
}
|
||||
|
||||
getSourceTable(selection) {
|
||||
if (!selection || selection.isFree === true)
|
||||
return null;
|
||||
|
||||
if (selection.sourceTable) {
|
||||
return ''
|
||||
+ selection.sourceTable.charAt(0).toUpperCase()
|
||||
+ selection.sourceTable.substring(1) + 's';
|
||||
} else if (selection.sourceTable == null)
|
||||
return `ItemTags/filterItemTags/${selection.id}`;
|
||||
}
|
||||
|
||||
removeField(index, field) {
|
||||
this.fieldFilters.splice(index, 1);
|
||||
this.$.filter[field] = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.component('vnLatestBuysSearchPanel', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -0,0 +1,45 @@
|
|||
import './index.js';
|
||||
|
||||
describe('Entry', () => {
|
||||
describe('Component vnLatestBuysSearchPanel', () => {
|
||||
let $element;
|
||||
let controller;
|
||||
|
||||
beforeEach(ngModule('entry'));
|
||||
|
||||
beforeEach(angular.mock.inject($componentController => {
|
||||
$element = angular.element(`<vn-latest-buys-search-panel></vn-latest-buys-search-panel>`);
|
||||
controller = $componentController('vnLatestBuysSearchPanel', {$element});
|
||||
}));
|
||||
|
||||
describe('getSourceTable()', () => {
|
||||
it(`should return null if there's no selection`, () => {
|
||||
let selection = null;
|
||||
let result = controller.getSourceTable(selection);
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it(`should return null if there's a selection but its isFree property is truthy`, () => {
|
||||
let selection = {isFree: true};
|
||||
let result = controller.getSourceTable(selection);
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it(`should return the formated sourceTable concatenated to a path`, () => {
|
||||
let selection = {sourceTable: 'hello guy'};
|
||||
let result = controller.getSourceTable(selection);
|
||||
|
||||
expect(result).toEqual('Hello guys');
|
||||
});
|
||||
|
||||
it(`should return a path if there's no sourceTable and the selection has an id`, () => {
|
||||
let selection = {id: 99};
|
||||
let result = controller.getSourceTable(selection);
|
||||
|
||||
expect(result).toEqual(`ItemTags/filterItemTags/${selection.id}`);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,177 @@
|
|||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="Buys/latestBuysFilter"
|
||||
limit="20"
|
||||
data="$ctrl.buys">
|
||||
</vn-crud-model>
|
||||
<vn-portal slot="topbar">
|
||||
<vn-searchbar
|
||||
panel="vn-latest-buys-search-panel"
|
||||
placeholder="Search by item id or name"
|
||||
info="You can search by item id or name"
|
||||
suggested-filter="{isActive: true}"
|
||||
model="model"
|
||||
auto-state="false">
|
||||
</vn-searchbar>
|
||||
</vn-portal>
|
||||
<vn-data-viewer
|
||||
model="model"
|
||||
class="vn-mb-xl vn-w-xl">
|
||||
<vn-card>
|
||||
<vn-table
|
||||
model="model"
|
||||
show-fields="$ctrl.showFields"
|
||||
vn-smart-table="latestBuys">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th shrink>
|
||||
<vn-multi-check
|
||||
model="model">
|
||||
</vn-multi-check>
|
||||
</vn-th>
|
||||
<vn-th field="Image">Picture</vn-th>
|
||||
<vn-th smart-table-ignore field="id">Id</vn-th>
|
||||
<vn-th field="packing">Packing</vn-th>
|
||||
<vn-th field="grouping">Grouping</vn-th>
|
||||
<vn-th field="description" style="text-align: center">Description</vn-th>
|
||||
<vn-th field="size">Size</vn-th>
|
||||
<vn-th field="type">Type</vn-th>
|
||||
<vn-th field="intrastat">Intrastat</vn-th>
|
||||
<vn-th field="origin">Origin</vn-th>
|
||||
<vn-th field="density">Density</vn-th>
|
||||
<vn-th field="isActive">Active</vn-th>
|
||||
<vn-th field="family">Family</vn-th>
|
||||
<vn-th field="entryFk">Entry</vn-th>
|
||||
<vn-th field="quantity">Quantity</vn-th>
|
||||
<vn-th field="buyingValue">Buying value</vn-th>
|
||||
<vn-th field="freightValue">Freight value</vn-th>
|
||||
<vn-th field="comissionValue" expand>Commission value</vn-th>
|
||||
<vn-th field="packageValue" expand>Package value</vn-th>
|
||||
<vn-th field="isIgnored">Is ignored</vn-th>
|
||||
<vn-th expand field="price2">Grouping price</vn-th>
|
||||
<vn-th expand field="price3">Packing price</vn-th>
|
||||
<vn-th field="minPrice">Min price</vn-th>
|
||||
<vn-th field="ektFk">Ekt</vn-th>
|
||||
<vn-th field="weight">Weight</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<a ng-repeat="buy in $ctrl.buys"
|
||||
class="clickable vn-tr search-result"
|
||||
ui-sref="entry.card.buy({id: {{::buy.entryFk}}})">
|
||||
<vn-td shrink>
|
||||
<vn-check
|
||||
ng-model="buy.checked"
|
||||
vn-click-stop>
|
||||
</vn-check>
|
||||
</vn-td>
|
||||
<vn-td shrink >
|
||||
<img
|
||||
ng-src="{{::$root.imagePath}}/catalog/50x50/{{::buy.image}}"
|
||||
zoom-image="{{::$root.imagePath}}/catalog/1600x900/{{::buy.image}}"
|
||||
vn-click-stop
|
||||
on-error-src/>
|
||||
</vn-td>
|
||||
<vn-td shrink>
|
||||
<span
|
||||
vn-click-stop="itemDescriptor.show($event, buy.itemFk)"
|
||||
class="link">
|
||||
{{::buy.itemFk | zeroFill:6}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td number>
|
||||
<vn-chip translate-attr="buy.groupingMode == 2 ? {title: 'Minimun amount'} : {title: 'Packing'}" ng-class="{'message': buy.groupingMode == 2}">
|
||||
<span translate>{{::buy.packing | dashIfEmpty}}</span>
|
||||
</vn-chip>
|
||||
</vn-td>
|
||||
<vn-td number>
|
||||
<vn-chip translate-attr="buy.groupingMode == 1 ? {title: 'Minimun amount'} : {title: 'Grouping'}" ng-class="{'message': buy.groupingMode == 1}">
|
||||
<span translate>{{::buy.grouping | dashIfEmpty}}</span>
|
||||
</vn-chip>
|
||||
</vn-td>
|
||||
<vn-td vn-two title="{{::buy.description}}">
|
||||
{{::buy.description | dashIfEmpty}}
|
||||
</vn-td>
|
||||
<vn-td number>{{::buy.size}}</vn-td>
|
||||
<vn-td shrink title="{{::buy.type}}">
|
||||
{{::buy.type}}
|
||||
</vn-td>
|
||||
<vn-td shrink title="{{::item.intrastat}}">
|
||||
{{::buy.intrastat}}
|
||||
</vn-td>
|
||||
<vn-td shrink>{{::buy.origin}}</vn-td>
|
||||
<vn-td shrink>{{::buy.density}}</vn-td>
|
||||
<vn-td shrink>
|
||||
<vn-check
|
||||
disabled="true"
|
||||
ng-model="::buy.isActive">
|
||||
</vn-check>
|
||||
</vn-td>
|
||||
<vn-td shrink>{{::buy.family}}</vn-td>
|
||||
<vn-td shrink>
|
||||
<span
|
||||
vn-click-stop="entryDescriptor.show($event, buy.entryFk)"
|
||||
class="link">
|
||||
{{::buy.entryFk}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td number>{{::buy.quantity}}</vn-td>
|
||||
<vn-td number>{{::buy.buyingValue | currency: 'EUR':2}}</vn-td>
|
||||
<vn-td number>{{::buy.freightValue | currency: 'EUR':2}}</vn-td>
|
||||
<vn-td number>{{::buy.comissionValue | currency: 'EUR':2}}</vn-td>
|
||||
<vn-td number>{{::buy.packageValue | currency: 'EUR':2}}</vn-td>
|
||||
<vn-td shrink>{{::buy.isIgnored}}</vn-td>
|
||||
<vn-td number>{{::buy.price2 | currency: 'EUR':2}}</vn-td>
|
||||
<vn-td number>{{::buy.price3 | currency: 'EUR':2}}</vn-td>
|
||||
<vn-td number>{{::buy.minPrice | currency: 'EUR':2}}</vn-td>
|
||||
<vn-td number>{{::buy.ektFk | dashIfEmpty}}</vn-td>
|
||||
<vn-td number>{{::buy.weight}}</vn-td>
|
||||
</a>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
<div fixed-bottom-right>
|
||||
<vn-vertical style="align-items: center;">
|
||||
<vn-button class="round sm vn-mb-sm"
|
||||
icon="edit"
|
||||
ng-show="$ctrl.totalChecked > 0"
|
||||
ng-click="edit.show($event)"
|
||||
vn-tooltip="Edit buy(s)"
|
||||
tooltip-position="left">
|
||||
</vn-button>
|
||||
</vn-vertical>
|
||||
</div>
|
||||
<vn-dialog class="edit"
|
||||
vn-id="edit"
|
||||
on-accept="$ctrl.onEditAccept()"
|
||||
on-close="$ctrl.editedColumn = null"
|
||||
message="Edit buy(s)">
|
||||
<tpl-body>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
vn-two
|
||||
ng-model="$ctrl.editedColumn.field"
|
||||
data="$ctrl.columns"
|
||||
value-field="field"
|
||||
show-field="displayName"
|
||||
label="Field to edit">
|
||||
</vn-autocomplete>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Value"
|
||||
ng-model="$ctrl.editedColumn.newValue">
|
||||
</vn-textfield>
|
||||
</vn-horizontal>
|
||||
</tpl-body>
|
||||
<tpl-buttons>
|
||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
||||
<button response="accept" translate>Create</button>
|
||||
</tpl-buttons>
|
||||
</vn-dialog>
|
||||
<vn-item-descriptor-popover
|
||||
vn-id="itemDescriptor">
|
||||
</vn-item-descriptor-popover>
|
||||
<vn-entry-descriptor-popover
|
||||
vn-id="entryDescriptor">
|
||||
</vn-entry-descriptor-popover>
|
|
@ -0,0 +1,78 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'salix/components/section';
|
||||
|
||||
export default class Controller extends Section {
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
this.showFields = {
|
||||
id: false,
|
||||
actions: false
|
||||
};
|
||||
this.editedColumn;
|
||||
}
|
||||
|
||||
get columns() {
|
||||
if (this._columns) return this._columns;
|
||||
|
||||
this._columns = [
|
||||
{field: 'quantity', displayName: this.$t('Quantity')},
|
||||
{field: 'buyingValue', displayName: this.$t('Buying value')},
|
||||
{field: 'freightValue', displayName: this.$t('Freight value')},
|
||||
{field: 'packing', displayName: this.$t('Packing')},
|
||||
{field: 'grouping', displayName: this.$t('Grouping')},
|
||||
{field: 'comissionValue', displayName: this.$t('Commission value')},
|
||||
{field: 'packageValue', displayName: this.$t('Package value')},
|
||||
{field: 'price2', displayName: this.$t('Grouping price')},
|
||||
{field: 'price3', displayName: this.$t('Packing price')},
|
||||
{field: 'weight', displayName: this.$t('Weight')},
|
||||
{field: 'description', displayName: this.$t('Description')},
|
||||
{field: 'minPrice', displayName: this.$t('Min price')},
|
||||
{field: 'size', displayName: this.$t('Size')},
|
||||
{field: 'density', displayName: this.$t('Density')}
|
||||
];
|
||||
|
||||
return this._columns;
|
||||
}
|
||||
|
||||
get checked() {
|
||||
const buys = this.$.model.data || [];
|
||||
const checkedBuys = [];
|
||||
for (let buy of buys) {
|
||||
if (buy.checked)
|
||||
checkedBuys.push(buy);
|
||||
}
|
||||
|
||||
return checkedBuys;
|
||||
}
|
||||
|
||||
uncheck() {
|
||||
const lines = this.checked;
|
||||
for (let line of lines) {
|
||||
if (line.checked)
|
||||
line.checked = false;
|
||||
}
|
||||
}
|
||||
|
||||
get totalChecked() {
|
||||
return this.checked.length;
|
||||
}
|
||||
|
||||
onEditAccept() {
|
||||
let data = {
|
||||
field: this.editedColumn.field,
|
||||
newValue: this.editedColumn.newValue,
|
||||
lines: this.checked
|
||||
};
|
||||
|
||||
return this.$http.post('Buys/editLatestBuys', data)
|
||||
.then(() => {
|
||||
this.uncheck();
|
||||
this.$.model.refresh();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.component('vnEntryLatestBuys', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -0,0 +1,82 @@
|
|||
import './index.js';
|
||||
|
||||
describe('Entry', () => {
|
||||
describe('Component vnEntryLatestBuys', () => {
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
|
||||
beforeEach(ngModule('entry'));
|
||||
|
||||
beforeEach(angular.mock.inject(($componentController, $compile, $rootScope, _$httpBackend_) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
let $element = $compile('<vn-entry-latest-buys></vn-entry-latest-buys')($rootScope);
|
||||
controller = $componentController('vnEntryLatestBuys', {$element});
|
||||
controller.$ = {
|
||||
model: {refresh: () => {}},
|
||||
edit: {hide: () => {}}
|
||||
};
|
||||
}));
|
||||
|
||||
describe('get columns', () => {
|
||||
it(`should return a set of columns`, () => {
|
||||
let result = controller.columns;
|
||||
|
||||
let length = result.length;
|
||||
let anyColumn = Object.keys(result[Math.floor(Math.random() * Math.floor(length))]);
|
||||
|
||||
expect(anyColumn).toContain('field', 'displayName');
|
||||
});
|
||||
});
|
||||
|
||||
describe('get checked', () => {
|
||||
it(`should return a set of checked lines`, () => {
|
||||
controller.$.model.data = [
|
||||
{checked: true, id: 1},
|
||||
{checked: true, id: 2},
|
||||
{checked: true, id: 3},
|
||||
{checked: false, id: 4},
|
||||
];
|
||||
|
||||
let result = controller.checked;
|
||||
|
||||
expect(result.length).toEqual(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('uncheck()', () => {
|
||||
it(`should clear the selection of lines on the controller`, () => {
|
||||
controller.$.model.data = [
|
||||
{checked: true, id: 1},
|
||||
{checked: true, id: 2},
|
||||
{checked: true, id: 3},
|
||||
{checked: false, id: 4},
|
||||
];
|
||||
|
||||
let result = controller.checked;
|
||||
|
||||
expect(result.length).toEqual(3);
|
||||
|
||||
controller.uncheck();
|
||||
|
||||
result = controller.checked;
|
||||
|
||||
expect(result.length).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onEditAccept()', () => {
|
||||
it(`should perform a query to update columns`, () => {
|
||||
controller.editedColumn = {field: 'my field', newValue: 'the new value'};
|
||||
let query = 'Buys/editLatestBuys';
|
||||
|
||||
$httpBackend.expectPOST(query).respond();
|
||||
controller.onEditAccept();
|
||||
$httpBackend.flush();
|
||||
|
||||
const result = controller.checked;
|
||||
|
||||
expect(result.length).toEqual(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1 @@
|
|||
Minimun amount: Minimun purchase quantity
|
|
@ -0,0 +1,13 @@
|
|||
Edit buy(s): Editar compra(s)
|
||||
Buying value: Precio
|
||||
Freight value: Porte
|
||||
Commission value: Comisión
|
||||
Package value: Embalaje
|
||||
Is ignored: Ignorado
|
||||
Grouping price: Precio grouping
|
||||
Packing price: Precio packing
|
||||
Min price: Precio min
|
||||
Ekt: Ekt
|
||||
Weight: Peso
|
||||
Minimun amount: Cantidad mínima de compra
|
||||
Field to edit: Campo a editar
|
|
@ -1,5 +1,6 @@
|
|||
#Ordenar alfabeticamente
|
||||
|
||||
entry: entrada
|
||||
Latest buys: Últimas compras
|
||||
|
||||
# Sections
|
||||
|
|
|
@ -2,13 +2,15 @@
|
|||
"module": "entry",
|
||||
"name": "Entries",
|
||||
"icon": "icon-entry",
|
||||
"dependencies": ["travel"],
|
||||
"dependencies": ["travel", "item"],
|
||||
"validations": true,
|
||||
"menus": {
|
||||
"main": [
|
||||
{"state": "entry.index", "icon": "icon-entry"}
|
||||
{"state": "entry.index", "icon": "icon-entry"},
|
||||
{"state": "entry.latestBuys", "icon": "icon-latestBuys"}
|
||||
],
|
||||
"card": [
|
||||
{"state": "entry.card.basicData", "icon": "settings"},
|
||||
{"state": "entry.card.buy", "icon": "icon-lines"},
|
||||
{"state": "entry.card.log", "icon": "history"}
|
||||
]
|
||||
|
@ -24,7 +26,20 @@
|
|||
"url": "/index?q",
|
||||
"state": "entry.index",
|
||||
"component": "vn-entry-index",
|
||||
"description": "Entries"
|
||||
"description": "Entries",
|
||||
"acl": ["buyer"]
|
||||
}, {
|
||||
"url": "/latest-buys?q",
|
||||
"state": "entry.latestBuys",
|
||||
"component": "vn-entry-latest-buys",
|
||||
"description": "Latest buys",
|
||||
"acl": ["buyer"]
|
||||
}, {
|
||||
"url": "/create?supplierFk&travelFk&companyFk",
|
||||
"state": "entry.create",
|
||||
"component": "vn-entry-create",
|
||||
"description": "New entry",
|
||||
"acl": ["buyer"]
|
||||
}, {
|
||||
"url": "/:id",
|
||||
"state": "entry.card",
|
||||
|
@ -38,6 +53,14 @@
|
|||
"params": {
|
||||
"entry": "$ctrl.entry"
|
||||
}
|
||||
}, {
|
||||
"url": "/basic-data",
|
||||
"state": "entry.card.basicData",
|
||||
"component": "vn-entry-basic-data",
|
||||
"description": "Basic data",
|
||||
"params": {
|
||||
"entry": "$ctrl.entry"
|
||||
}
|
||||
}, {
|
||||
"url" : "/log",
|
||||
"state": "entry.card.log",
|
||||
|
|
|
@ -20,37 +20,66 @@ module.exports = Self => {
|
|||
const models = Self.app.models;
|
||||
|
||||
try {
|
||||
const imageQueue = await Self.find({limit: 25});
|
||||
const rootPath = models.Image.getPath();
|
||||
const tempPath = path.join(rootPath, 'temp');
|
||||
const tempPath = path.join('/tmp/salix-image');
|
||||
|
||||
// Create temporary path
|
||||
await fs.mkdir(tempPath, {recursive: true});
|
||||
|
||||
for (let image of imageQueue) {
|
||||
const timer = setInterval(async() => {
|
||||
const image = await Self.findOne({where: {error: null}});
|
||||
|
||||
// Exit loop
|
||||
if (!image) return clearInterval(timer);
|
||||
|
||||
const fileName = `${image.itemFk}.png`;
|
||||
const filePath = path.join(tempPath, fileName);
|
||||
const file = fs.createWriteStream(filePath);
|
||||
|
||||
https.get(image.url, async response => {
|
||||
response.pipe(file);
|
||||
const writeStream = fs.createWriteStream(filePath);
|
||||
writeStream.on('open', () => {
|
||||
https.get(image.url, async response => {
|
||||
if (response.statusCode != 200) {
|
||||
const error = new Error(`Could not download the image. Status code ${response.statusCode}`);
|
||||
|
||||
return await errorHandler(image.itemFk, error, filePath);
|
||||
}
|
||||
|
||||
response.pipe(writeStream);
|
||||
}).on('error', async error => {
|
||||
await errorHandler(image.itemFk, error, filePath);
|
||||
});
|
||||
});
|
||||
|
||||
file.on('finish', async function() {
|
||||
await models.Image.registerImage('catalog', fileName, filePath);
|
||||
await image.destroy();
|
||||
writeStream.on('error', async error => {
|
||||
await errorHandler(image.itemFk, error, filePath);
|
||||
});
|
||||
|
||||
file.on('error', err => {
|
||||
fs.unlink(filePath);
|
||||
|
||||
throw err;
|
||||
writeStream.on('finish', async function() {
|
||||
try {
|
||||
await models.Image.registerImage('catalog', fileName, filePath);
|
||||
await image.destroy();
|
||||
} catch (error) {
|
||||
await errorHandler(image.itemFk, error, filePath);
|
||||
}
|
||||
});
|
||||
}, 1000);
|
||||
} catch (error) {
|
||||
throw new Error('Try-catch error: ', error);
|
||||
}
|
||||
|
||||
async function errorHandler(rowId, error, filePath) {
|
||||
try {
|
||||
const row = await Self.findById(rowId);
|
||||
|
||||
if (!row)
|
||||
throw new Error(`Could not update due error ${error}`);
|
||||
|
||||
await row.updateAttribute('error', error);
|
||||
|
||||
if (filePath && fs.existsSync(filePath))
|
||||
await fs.unlink(filePath);
|
||||
} catch (err) {
|
||||
throw new Error(`ErrorHandler error: ${err}`);
|
||||
}
|
||||
|
||||
return imageQueue;
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -12,42 +12,38 @@ 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: 'tags',
|
||||
type: ['Object'],
|
||||
description: 'List of tags to filter with',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'search',
|
||||
type: 'String',
|
||||
description: `If it's and integer searchs by id, otherwise it searchs by name`,
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'id',
|
||||
type: 'Integer',
|
||||
description: 'Item id',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'categoryFk',
|
||||
type: 'Integer',
|
||||
description: 'Category id',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'typeFk',
|
||||
type: 'Integer',
|
||||
description: 'Type id',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'isActive',
|
||||
type: 'Boolean',
|
||||
description: 'Whether the the item is o not active',
|
||||
http: {source: 'query'}
|
||||
description: 'Whether the the item is or not active',
|
||||
}, {
|
||||
arg: 'salesPersonFk',
|
||||
type: 'Integer',
|
||||
description: 'The buyer of the item',
|
||||
http: {source: 'query'}
|
||||
}, {
|
||||
arg: 'description',
|
||||
type: 'String',
|
||||
description: 'The item description',
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethod('getLastEntries', {
|
||||
description: 'Returns last entries',
|
||||
accessType: 'READ',
|
||||
accepts: [{
|
||||
arg: 'filter',
|
||||
type: 'object',
|
||||
required: true,
|
||||
description: 'itemFk, id'
|
||||
}],
|
||||
returns: {
|
||||
type: 'Array',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/getLastEntries`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.getLastEntries = async filter => {
|
||||
let where = filter.where;
|
||||
let query = `CALL vn.itemLastEntries(?, ?)`;
|
||||
let [lastEntries] = await Self.rawSql(query, [where.itemFk, where.date]);
|
||||
|
||||
return lastEntries;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,62 @@
|
|||
|
||||
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('lastEntriesFilter', {
|
||||
description: 'Returns last entries',
|
||||
accessType: 'READ',
|
||||
accepts: [{
|
||||
arg: 'filter',
|
||||
type: 'object',
|
||||
required: true,
|
||||
description: 'itemFk, id'
|
||||
}],
|
||||
returns: {
|
||||
type: 'Array',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/lastEntriesFilter`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.lastEntriesFilter = async filter => {
|
||||
const conn = Self.dataSource.connector;
|
||||
const stmt = new ParameterizedSQL(
|
||||
`SELECT
|
||||
w.id AS warehouseFk,
|
||||
w.name AS warehouse,
|
||||
tr.landed,
|
||||
b.id AS buyFk,
|
||||
b.entryFk,
|
||||
b.isIgnored,
|
||||
b.price2,
|
||||
b.price3,
|
||||
b.stickers,
|
||||
b.packing,
|
||||
b.grouping,
|
||||
b.groupingMode,
|
||||
b.weight,
|
||||
i.stems,
|
||||
b.quantity,
|
||||
b.buyingValue,
|
||||
b.packageFk ,
|
||||
s.id AS supplierFk,
|
||||
s.name AS supplier
|
||||
FROM itemType it
|
||||
RIGHT JOIN (entry e
|
||||
LEFT JOIN supplier s ON s.id = e.supplierFk
|
||||
RIGHT JOIN buy b ON b.entryFk = e.id
|
||||
LEFT JOIN item i ON i.id = b.itemFk
|
||||
LEFT JOIN ink ON ink.id = i.inkFk
|
||||
LEFT JOIN travel tr ON tr.id = e.travelFk
|
||||
LEFT JOIN warehouse w ON w.id = tr.warehouseInFk
|
||||
LEFT JOIN origin o ON o.id = i.originFk
|
||||
) ON it.id = i.typeFk
|
||||
LEFT JOIN edi.ekt ek ON b.ektFk = ek.id`);
|
||||
stmt.merge(conn.makeSuffix(filter));
|
||||
|
||||
return conn.executeStmt(stmt);
|
||||
};
|
||||
};
|
|
@ -1,22 +0,0 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
describe('item getLastEntries()', () => {
|
||||
it('should return one entry for a given item', async() => {
|
||||
let date = new Date();
|
||||
let filter = {where: {itemFk: 1, date: date}};
|
||||
let result = await app.models.Item.getLastEntries(filter);
|
||||
|
||||
expect(result.length).toEqual(1);
|
||||
});
|
||||
|
||||
it('should return five entries for a given item', async() => {
|
||||
let date = new Date();
|
||||
|
||||
date.setMonth(date.getMonth() - 2, 1);
|
||||
|
||||
let filter = {where: {itemFk: 1, date: date}};
|
||||
let result = await app.models.Item.getLastEntries(filter);
|
||||
|
||||
expect(result.length).toEqual(5);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,24 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
describe('item lastEntriesFilter()', () => {
|
||||
const minDate = new Date(value);
|
||||
minHour.setHours(0, 0, 0, 0);
|
||||
const maxDate = new Date(value);
|
||||
maxHour.setHours(23, 59, 59, 59);
|
||||
|
||||
it('should return one entry for a given item', async() => {
|
||||
const filter = {where: {itemFk: 1, landed: {between: [minDate, maxDate]}}};
|
||||
const result = await app.models.Item.lastEntriesFilter(filter);
|
||||
|
||||
expect(result.length).toEqual(1);
|
||||
});
|
||||
|
||||
it('should return five entries for a given item', async() => {
|
||||
minDate.setMonth(minDate.getMonth() - 2, 1);
|
||||
|
||||
const filter = {where: {itemFk: 1, landed: {between: [minDate, maxDate]}}};
|
||||
const result = await app.models.Item.lastEntriesFilter(filter);
|
||||
|
||||
expect(result.length).toEqual(5);
|
||||
});
|
||||
});
|
|
@ -16,6 +16,10 @@
|
|||
"url": {
|
||||
"type": "String",
|
||||
"required": true
|
||||
},
|
||||
"error": {
|
||||
"type": "String",
|
||||
"required": true
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
|
|
|
@ -5,7 +5,7 @@ module.exports = Self => {
|
|||
require('../methods/item/clone')(Self);
|
||||
require('../methods/item/updateTaxes')(Self);
|
||||
require('../methods/item/getBalance')(Self);
|
||||
require('../methods/item/getLastEntries')(Self);
|
||||
require('../methods/item/lastEntriesFilter')(Self);
|
||||
require('../methods/item/getSummary')(Self);
|
||||
require('../methods/item/getCard')(Self);
|
||||
require('../methods/item/regularize')(Self);
|
||||
|
|
|
@ -122,6 +122,9 @@
|
|||
"mysql": {
|
||||
"columnName": "expenceFk"
|
||||
}
|
||||
},
|
||||
"minPrice": {
|
||||
"type": "number"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
|
|
|
@ -33,13 +33,13 @@
|
|||
"retAccount": {
|
||||
"type": "Number"
|
||||
},
|
||||
"commision": {
|
||||
"commission": {
|
||||
"type": "Boolean"
|
||||
},
|
||||
"created": {
|
||||
"type": "Date"
|
||||
},
|
||||
"poscodeFk": {
|
||||
"postcodeFk": {
|
||||
"type": "Number"
|
||||
},
|
||||
"isActive": {
|
||||
|
|
|
@ -109,6 +109,14 @@
|
|||
ng-model="$ctrl.item.density"
|
||||
rule>
|
||||
</vn-input-number>
|
||||
<vn-input-number
|
||||
vn-one
|
||||
min="0"
|
||||
step="0.01"
|
||||
label="Compression"
|
||||
ng-model="$ctrl.item.compression"
|
||||
rule>
|
||||
</vn-input-number>
|
||||
<vn-input-number
|
||||
vn-one
|
||||
min="0"
|
||||
|
|
|
@ -8,24 +8,24 @@
|
|||
<vn-table
|
||||
model="model"
|
||||
show-fields="$ctrl.showFields"
|
||||
vn-uvc="itemIndex">
|
||||
vn-smart-table="itemIndex">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th th-id="picture" shrink></vn-th>
|
||||
<vn-th shrink></vn-th>
|
||||
<vn-th field="id" shrink>Id</vn-th>
|
||||
<vn-th th-id="grouping" shrink>Grouping</vn-th>
|
||||
<vn-th th-id="packing" shrink>Packing</vn-th>
|
||||
<vn-th th-id="description" style="text-align: center">Description</vn-th>
|
||||
<vn-th th-id="stems" shrink>Stems</vn-th>
|
||||
<vn-th th-id="size" shrink>Size</vn-th>
|
||||
<vn-th th-id="niche" shrink>Niche</vn-th>
|
||||
<vn-th th-id="type" shrink>Type</vn-th>
|
||||
<vn-th th-id="category" shrink>Category</vn-th>
|
||||
<vn-th th-id="intrastat" shrink>Intrastat</vn-th>
|
||||
<vn-th th-id="origin" shrink>Origin</vn-th>
|
||||
<vn-th th-id="salesperson" shrink>Buyer</vn-th>
|
||||
<vn-th th-id="density" shrink>Density</vn-th>
|
||||
<vn-th th-id="active" shrink>Active</vn-th>
|
||||
<vn-th field="grouping" shrink>Grouping</vn-th>
|
||||
<vn-th field="packing" shrink>Packing</vn-th>
|
||||
<vn-th field="description" style="text-align: center">Description</vn-th>
|
||||
<vn-th field="stems" shrink>Stems</vn-th>
|
||||
<vn-th field="size" shrink>Size</vn-th>
|
||||
<vn-th field="niche" shrink>Niche</vn-th>
|
||||
<vn-th field="type" shrink>Type</vn-th>
|
||||
<vn-th field="category" shrink>Category</vn-th>
|
||||
<vn-th field="intrastat" shrink>Intrastat</vn-th>
|
||||
<vn-th field="origin" shrink>Origin</vn-th>
|
||||
<vn-th field="salesperson" shrink>Buyer</vn-th>
|
||||
<vn-th field="density" shrink>Density</vn-th>
|
||||
<vn-th field="active" shrink>Active</vn-th>
|
||||
<vn-th></vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="Items/getLastEntries"
|
||||
url="Items/lastEntriesFilter"
|
||||
filter="::$ctrl.filter"
|
||||
data="entries"
|
||||
auto-load="false">
|
||||
auto-load="true"
|
||||
order="landed DESC, buyFk DESC"
|
||||
limit="20">
|
||||
</vn-crud-model>
|
||||
<vn-vertical>
|
||||
<vn-data-viewer
|
||||
model="model"
|
||||
class="vn-mb-xl vn-w-xl">
|
||||
<vn-card class="vn-pa-lg">
|
||||
<vn-vertical>
|
||||
<vn-horizontal>
|
||||
|
@ -20,8 +24,8 @@
|
|||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th vn-tooltip="Ignored" center>Ig</vn-th>
|
||||
<vn-th>Warehouse</vn-th>
|
||||
<vn-th>Landed</vn-th>
|
||||
<vn-th field="warehouseFk">Warehouse</vn-th>
|
||||
<vn-th field="landed">Landed</vn-th>
|
||||
<vn-th number>Entry</vn-th>
|
||||
<vn-th number vn-tooltip="Price Per Unit">P.P.U</vn-th>
|
||||
<vn-th number vn-tooltip="Price Per Package">P.P.P</vn-th>
|
||||
|
@ -29,11 +33,11 @@
|
|||
<vn-th number>Packing</vn-th>
|
||||
<vn-th number>Grouping</vn-th>
|
||||
<vn-th number class="expendable">Stems</vn-th>
|
||||
<vn-th number>Quantity</vn-th>
|
||||
<vn-th field="quantity" number>Quantity</vn-th>
|
||||
<vn-th number class="expendable">Cost</vn-th>
|
||||
<vn-th number>Kg.</vn-th>
|
||||
<vn-th number>Cube</vn-th>
|
||||
<vn-th class="expendable">Provider</vn-th>
|
||||
<vn-th field="packageFk" number>Cube</vn-th>
|
||||
<vn-th field="supplierFk" class="expendable">Provider</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
|
@ -70,6 +74,30 @@
|
|||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-vertical>
|
||||
<vn-pagination model="model"></vn-pagination>
|
||||
</vn-card>
|
||||
</vn-vertical>
|
||||
</vn-data-viewer>
|
||||
|
||||
<vn-contextmenu vn-id="contextmenu" targets="['vn-data-viewer']" 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>
|
||||
</slot-menu>
|
||||
</vn-contextmenu>
|
|
@ -6,17 +6,23 @@ class Controller extends Section {
|
|||
constructor($element, $) {
|
||||
super($element, $);
|
||||
|
||||
let defaultDate = new Date();
|
||||
defaultDate.setDate(defaultDate.getDate() - 75);
|
||||
defaultDate.setHours(0, 0, 0, 0);
|
||||
const from = new Date();
|
||||
from.setDate(from.getDate() - 75);
|
||||
from.setHours(0, 0, 0, 0);
|
||||
|
||||
const to = new Date();
|
||||
to.setDate(to.getDate() + 10);
|
||||
to.setHours(23, 59, 59, 59);
|
||||
|
||||
this.filter = {
|
||||
where: {
|
||||
itemFk: this.$params.id,
|
||||
date: defaultDate
|
||||
shipped: {
|
||||
between: [from, to]
|
||||
}
|
||||
}
|
||||
};
|
||||
this._date = defaultDate;
|
||||
this._date = from;
|
||||
}
|
||||
|
||||
set date(value) {
|
||||
|
@ -31,6 +37,32 @@ class Controller extends Section {
|
|||
get date() {
|
||||
return this._date;
|
||||
}
|
||||
|
||||
exprBuilder(param, value) {
|
||||
switch (param) {
|
||||
case 'id':
|
||||
case 'quantity':
|
||||
case 'packageFk':
|
||||
return {[`b.${param}`]: value};
|
||||
case 'supplierFk':
|
||||
return {[`s.id`]: value};
|
||||
case 'warehouseFk':
|
||||
return {'tr.warehouseInFk': value};
|
||||
case 'landed':
|
||||
return {'tr.landed': {
|
||||
between: this.dateRange(value)}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
dateRange(value) {
|
||||
const minHour = new Date(value);
|
||||
minHour.setHours(0, 0, 0, 0);
|
||||
const maxHour = new Date(value);
|
||||
maxHour.setHours(23, 59, 59, 59);
|
||||
|
||||
return [minHour, maxHour];
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope'];
|
||||
|
|
|
@ -56,12 +56,14 @@
|
|||
label="For me"
|
||||
ng-model="filter.mine">
|
||||
</vn-check>
|
||||
<vn-check
|
||||
vn-one
|
||||
triple-state="true"
|
||||
label="Confirmed"
|
||||
ng-model="filter.isOk">
|
||||
</vn-check>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
ng-model="filter.state"
|
||||
data="$ctrl.states"
|
||||
value-field="code"
|
||||
label="State">
|
||||
<tpl-item>{{name}}</tpl-item>
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal class="vn-mt-lg">
|
||||
<vn-submit label="Search"></vn-submit>
|
||||
|
|
|
@ -1,7 +1,19 @@
|
|||
import ngModule from '../module';
|
||||
import SearchPanel from 'core/components/searchbar/search-panel';
|
||||
|
||||
class Controller extends SearchPanel {
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
|
||||
this.states = [
|
||||
{code: 'pending', name: this.$t('Pending')},
|
||||
{code: 'accepted', name: this.$t('Accepted')},
|
||||
{code: 'denied', name: this.$t('Denied')}
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnRequestSearchPanel', {
|
||||
template: require('./index.html'),
|
||||
controller: SearchPanel
|
||||
controller: Controller
|
||||
});
|
||||
|
|
|
@ -24,14 +24,15 @@
|
|||
<vn-tr>
|
||||
<vn-th field="ticketFk" number>Ticket ID</vn-th>
|
||||
<vn-th field="shipped" expand>Shipped</vn-th>
|
||||
<vn-th field="description" expand>Description</vn-th>
|
||||
<vn-th field="description" filter-enabled="false" expand>Description</vn-th>
|
||||
<vn-th field="quantity" number editable>Requested</vn-th>
|
||||
<vn-th field="price" number>Price</vn-th>
|
||||
<vn-th field="atenderNickname">Atender</vn-th>
|
||||
<vn-th field="itemFk">Item</vn-th>
|
||||
<vn-th field="attenderName">Atender</vn-th>
|
||||
<vn-th>Item</vn-th>
|
||||
<vn-th field="saleQuantity">Achieved</vn-th>
|
||||
<vn-th field="description">Concept</vn-th>
|
||||
<vn-th field="description" filter-enabled="false">Concept</vn-th>
|
||||
<vn-th field="isOk">State</vn-th>
|
||||
<vn-th></vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
|
@ -83,7 +84,7 @@
|
|||
{{request.itemDescription}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td>{{$ctrl.getState(request.isOk)}}</vn-td>
|
||||
<vn-td translate>{{$ctrl.getState(request.isOk)}}</vn-td>
|
||||
<vn-td>
|
||||
<vn-icon
|
||||
ng-if="request.response.length"
|
||||
|
@ -128,4 +129,29 @@
|
|||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
||||
<button response="accept" translate>Save</button>
|
||||
</tpl-buttons>
|
||||
</vn-dialog>
|
||||
</vn-dialog>
|
||||
|
||||
<vn-contextmenu vn-id="contextmenu" targets="['vn-data-viewer']" 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>
|
||||
</slot-menu>
|
||||
</vn-contextmenu>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue