8179-testToMaster #3176
|
@ -1544,7 +1544,7 @@ INSERT INTO `bs`.`waste`(`buyerFk`, `year`, `week`, `itemFk`, `itemTypeFk`, `sal
|
||||||
('103', YEAR(DATE_ADD(util.VN_CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(util.VN_CURDATE(), INTERVAL -1 WEEK), 1), 6, 1, '186', '0', '51', '53.12', '56.20', '56.20', '56.20'),
|
('103', YEAR(DATE_ADD(util.VN_CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(util.VN_CURDATE(), INTERVAL -1 WEEK), 1), 6, 1, '186', '0', '51', '53.12', '56.20', '56.20', '56.20'),
|
||||||
('103', YEAR(DATE_ADD(util.VN_CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(util.VN_CURDATE(), INTERVAL -1 WEEK), 1), 7, 1, '277', '0', '53.12', '56.20', '56.20', '56.20', '56.20');
|
('103', YEAR(DATE_ADD(util.VN_CURDATE(), INTERVAL -1 WEEK)), WEEK(DATE_ADD(util.VN_CURDATE(), INTERVAL -1 WEEK), 1), 7, 1, '277', '0', '53.12', '56.20', '56.20', '56.20', '56.20');
|
||||||
|
|
||||||
INSERT INTO `vn`.`buy`(`id`,`entryFk`,`itemFk`,`buyingValue`,`quantity`,`packagingFk`,`stickers`,`freightValue`,`packageValue`,`comissionValue`,`packing`,`grouping`,`groupingMode`,`location`,`price1`,`price2`,`price3`, `printedStickers`,`isChecked`,`isIgnored`,`weight`, `created`)
|
INSERT INTO vn.buy(id,entryFk,itemFk,buyingValue,quantity,packagingFk,stickers,freightValue,packageValue,comissionValue,packing,grouping,groupingMode,location,price1,price2,price3,printedStickers,isChecked,isIgnored,weight,created)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 1, 1, 50, 5000, 4, 1, 1.500, 1.500, 0.000, 1, 1, 'packing', NULL, 0.00, 99.6, 99.4, 0, 1, 0, 1, util.VN_CURDATE() - INTERVAL 2 MONTH),
|
(1, 1, 1, 50, 5000, 4, 1, 1.500, 1.500, 0.000, 1, 1, 'packing', NULL, 0.00, 99.6, 99.4, 0, 1, 0, 1, util.VN_CURDATE() - INTERVAL 2 MONTH),
|
||||||
(2, 2, 1, 50, 100, 4, 1, 1.500, 1.500, 0.000, 1, 1, 'packing', NULL, 0.00, 99.6, 99.4, 0, 1, 0, 1, util.VN_CURDATE() - INTERVAL 1 MONTH),
|
(2, 2, 1, 50, 100, 4, 1, 1.500, 1.500, 0.000, 1, 1, 'packing', NULL, 0.00, 99.6, 99.4, 0, 1, 0, 1, util.VN_CURDATE() - INTERVAL 1 MONTH),
|
||||||
|
@ -1560,7 +1560,8 @@ INSERT INTO `vn`.`buy`(`id`,`entryFk`,`itemFk`,`buyingValue`,`quantity`,`packagi
|
||||||
(12, 6, 4, 1.25, 0, 3, 1, 2.500, 2.500, 0.000, 10, 10, 'grouping', NULL, 0.00, 1.75, 1.67, 0, 1, 0, 4, util.VN_CURDATE()),
|
(12, 6, 4, 1.25, 0, 3, 1, 2.500, 2.500, 0.000, 10, 10, 'grouping', NULL, 0.00, 1.75, 1.67, 0, 1, 0, 4, util.VN_CURDATE()),
|
||||||
(13, 7, 1, 50, 0, 3, 1, 2.000, 2.000, 0.000, 1, 1, 'packing', NULL, 0.00, 99.6, 99.4, 0, 1, 0, 4, util.VN_CURDATE()),
|
(13, 7, 1, 50, 0, 3, 1, 2.000, 2.000, 0.000, 1, 1, 'packing', NULL, 0.00, 99.6, 99.4, 0, 1, 0, 4, util.VN_CURDATE()),
|
||||||
(14, 7, 2, 5, 0, 3, 1, 2.000, 2.000, 0.000, 10, 10, 'grouping', NULL, 0.00, 7.30, 7.00, 0, 1, 0, 4, util.VN_CURDATE()),
|
(14, 7, 2, 5, 0, 3, 1, 2.000, 2.000, 0.000, 10, 10, 'grouping', NULL, 0.00, 7.30, 7.00, 0, 1, 0, 4, util.VN_CURDATE()),
|
||||||
(15, 7, 4, 1.25, 0, 3, 1, 2.000, 2.000, 0.000, 10, 10, 'grouping', NULL, 0.00, 1.75, 1.67, 0, 1, 0, 4, util.VN_CURDATE());
|
(15, 7, 4, 1.25, 0, 3, 1, 2.000, 2.000, 0.000, 10, 10, 'grouping', NULL, 0.00, 1.75, 1.67, 0, 1, 0, 4, util.VN_CURDATE()),
|
||||||
|
(16, 99,1,50.0000, 5000, 4, 1, 1.500, 1.500, 0.000, 1, 1, 'packing', NULL, 0.00, 99.60, 99.40, 0, 1, 0, 1.00, '2024-07-30 08:13:51.000');
|
||||||
|
|
||||||
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`)
|
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
|
VALUES
|
||||||
|
@ -2441,7 +2442,8 @@ INSERT INTO `vn`.`workerTimeControl`(`userFk`, `timed`, `manual`, `direction`, `
|
||||||
(1107, CONCAT(util.VN_CURDATE(), ' 10:20'), TRUE, 'middle', 1),
|
(1107, CONCAT(util.VN_CURDATE(), ' 10:20'), TRUE, 'middle', 1),
|
||||||
(1107, CONCAT(util.VN_CURDATE(), ' 14:50'), TRUE, 'out', 1);
|
(1107, CONCAT(util.VN_CURDATE(), ' 14:50'), TRUE, 'out', 1);
|
||||||
|
|
||||||
INSERT INTO `vn`.`dmsType`(`id`, `name`, `readRoleFk`, `writeRoleFk`, `code`)
|
INSERT INTO `vn`.`dmsType`
|
||||||
|
(`id`, `name`, `readRoleFk`, `writeRoleFk`, `code`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 'Facturas Recibidas', NULL, NULL, 'invoiceIn'),
|
(1, 'Facturas Recibidas', NULL, NULL, 'invoiceIn'),
|
||||||
(2, 'Doc oficial', NULL, NULL, 'officialDoc'),
|
(2, 'Doc oficial', NULL, NULL, 'officialDoc'),
|
||||||
|
@ -2464,7 +2466,8 @@ INSERT INTO `vn`.`dmsType`(`id`, `name`, `readRoleFk`, `writeRoleFk`, `code`)
|
||||||
(19, 'inmovilizado', NULL, NULL, 'fixedAssets'),
|
(19, 'inmovilizado', NULL, NULL, 'fixedAssets'),
|
||||||
(20, 'Reclamación', 1, 1, 'claim'),
|
(20, 'Reclamación', 1, 1, 'claim'),
|
||||||
(21, 'Entrada', 1, 1, 'entry'),
|
(21, 'Entrada', 1, 1, 'entry'),
|
||||||
(22, 'Proveedor', 1, 1, 'supplier');
|
(22, 'Proveedor', 1, 1, 'supplier'),
|
||||||
|
(23, 'Termografos', 35, 35, 'thermograph');
|
||||||
|
|
||||||
INSERT INTO `vn`.`dms`(`id`, `dmsTypeFk`, `file`, `contentType`, `workerFk`, `warehouseFk`, `companyFk`, `hardCopyNumber`, `hasFile`, `reference`, `description`, `created`)
|
INSERT INTO `vn`.`dms`(`id`, `dmsTypeFk`, `file`, `contentType`, `workerFk`, `warehouseFk`, `companyFk`, `hardCopyNumber`, `hasFile`, `reference`, `description`, `created`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -2472,7 +2475,7 @@ INSERT INTO `vn`.`dms`(`id`, `dmsTypeFk`, `file`, `contentType`, `workerFk`, `wa
|
||||||
(2, 5, '2.txt', 'text/plain', 5, 1, 442, 1, TRUE, 'Client:104', 'Client:104 dms for the client', util.VN_CURDATE()),
|
(2, 5, '2.txt', 'text/plain', 5, 1, 442, 1, TRUE, 'Client:104', 'Client:104 dms for the client', util.VN_CURDATE()),
|
||||||
(3, 5, '3.txt', 'text/plain', 5, 1, 442, NULL, TRUE, 'Client: 104', 'Client:104 readme', util.VN_CURDATE()),
|
(3, 5, '3.txt', 'text/plain', 5, 1, 442, NULL, TRUE, 'Client: 104', 'Client:104 readme', util.VN_CURDATE()),
|
||||||
(4, 3, '4.txt', 'text/plain', 5, 1, 442, NULL, TRUE, 'Worker: 106', 'Worker:106 readme', util.VN_CURDATE()),
|
(4, 3, '4.txt', 'text/plain', 5, 1, 442, NULL, TRUE, 'Worker: 106', 'Worker:106 readme', util.VN_CURDATE()),
|
||||||
(5, 5, '5.txt', 'text/plain', 5, 1, 442, NULL, TRUE, 'travel: 1', 'dmsForThermograph', util.VN_CURDATE()),
|
(5, 23, '5.txt', 'text/plain', 5, 1, 442, NULL, TRUE, 'travel: 1', 'dmsForThermograph', util.VN_CURDATE()),
|
||||||
(6, 5, '6.txt', 'text/plain', 5, 1, 442, NULL, TRUE, 'NotExists', 'DoesNotExists', util.VN_CURDATE()),
|
(6, 5, '6.txt', 'text/plain', 5, 1, 442, NULL, TRUE, 'NotExists', 'DoesNotExists', util.VN_CURDATE()),
|
||||||
(7, 20, '7.jpg', 'image/jpeg', 9, 1, 442, NULL, FALSE, '1', 'TICKET ID DEL CLIENTE BRUCE WAYNE ID 1101', util.VN_CURDATE()),
|
(7, 20, '7.jpg', 'image/jpeg', 9, 1, 442, NULL, FALSE, '1', 'TICKET ID DEL CLIENTE BRUCE WAYNE ID 1101', util.VN_CURDATE()),
|
||||||
(8, 20, '8.mp4', 'video/mp4', 9, 1, 442, NULL, FALSE, '1', 'TICKET ID DEL CLIENTE BRUCE WAYNE ID 1101', util.VN_CURDATE()),
|
(8, 20, '8.mp4', 'video/mp4', 9, 1, 442, NULL, FALSE, '1', 'TICKET ID DEL CLIENTE BRUCE WAYNE ID 1101', util.VN_CURDATE()),
|
||||||
|
|
|
@ -52,13 +52,13 @@ BEGIN
|
||||||
FROM vn.sale s
|
FROM vn.sale s
|
||||||
JOIN vn.ticket t ON t.id = s.ticketFk
|
JOIN vn.ticket t ON t.id = s.ticketFk
|
||||||
LEFT JOIN vn.itemShelvingSale iss ON iss.saleFk = s.id
|
LEFT JOIN vn.itemShelvingSale iss ON iss.saleFk = s.id
|
||||||
WHERE t.shipped BETWEEN CURDATE() AND CURDATE() + INTERVAL vDaysInForward DAY
|
WHERE t.shipped >= CURDATE() + INTERVAL vDaysInForward DAY
|
||||||
AND iss.saleFk IS NULL
|
AND iss.saleFk IS NULL
|
||||||
AND t.warehouseFk = vWarehouseFk
|
AND t.warehouseFk = vWarehouseFk
|
||||||
GROUP BY s.itemFk
|
GROUP BY s.itemFk
|
||||||
)
|
)
|
||||||
SELECT i.id itemFk,
|
SELECT i.id itemFk,
|
||||||
CAST(sd.quantity AS INT) advanceable,
|
LEAST(CAST(sd.quantity AS INT), sk.stock) advanceable,
|
||||||
i.longName,
|
i.longName,
|
||||||
i.subName,
|
i.subName,
|
||||||
i.tag5,
|
i.tag5,
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`stockBought_calculate`(
|
||||||
|
vDated DATE
|
||||||
|
)
|
||||||
|
proc: BEGIN
|
||||||
|
/**
|
||||||
|
* Calculate the stock of the auction warehouse from the inventory date to vDated
|
||||||
|
* without taking into account the outputs of the same day vDated
|
||||||
|
*
|
||||||
|
* @param vDated Date to calculate the stock.
|
||||||
|
*/
|
||||||
|
IF vDated < util.VN_CURDATE() THEN
|
||||||
|
LEAVE proc;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
CREATE OR REPLACE TEMPORARY TABLE tStockBought
|
||||||
|
SELECT workerFk, reserve
|
||||||
|
FROM stockBought
|
||||||
|
WHERE dated = vDated
|
||||||
|
AND reserve;
|
||||||
|
|
||||||
|
DELETE FROM stockBought WHERE dated = vDated;
|
||||||
|
|
||||||
|
CALL item_calculateStock(vDated);
|
||||||
|
|
||||||
|
INSERT INTO stockBought(workerFk, bought, dated)
|
||||||
|
SELECT it.workerFk,
|
||||||
|
ROUND(SUM(
|
||||||
|
(ti.quantity / b.packing) *
|
||||||
|
buy_getVolume(b.id)
|
||||||
|
) / vc.palletM3 / 1000000, 1) bought,
|
||||||
|
vDated
|
||||||
|
FROM itemType it
|
||||||
|
JOIN item i ON i.typeFk = it.id
|
||||||
|
LEFT JOIN tmp.item ti ON ti.itemFk = i.id
|
||||||
|
JOIN itemCategory ic ON ic.id = it.categoryFk
|
||||||
|
JOIN warehouse wh ON wh.code = 'VNH'
|
||||||
|
JOIN tmp.buyUltimate bu ON bu.itemFk = i.id
|
||||||
|
AND bu.warehouseFk = wh.id
|
||||||
|
JOIN buy b ON b.id = bu.buyFk
|
||||||
|
JOIN volumeConfig vc
|
||||||
|
WHERE ic.display
|
||||||
|
GROUP BY it.workerFk
|
||||||
|
HAVING bought;
|
||||||
|
|
||||||
|
UPDATE stockBought s
|
||||||
|
JOIN tStockBought ts ON ts.workerFk = s.workerFk
|
||||||
|
SET s.reserve = ts.reserve
|
||||||
|
WHERE s.dated = vDated;
|
||||||
|
|
||||||
|
INSERT INTO stockBought (workerFk, reserve, dated)
|
||||||
|
SELECT ts.workerFk, ts.reserve, vDated
|
||||||
|
FROM tStockBought ts
|
||||||
|
WHERE ts.workerFk NOT IN (
|
||||||
|
SELECT workerFk
|
||||||
|
FROM stockBought
|
||||||
|
WHERE dated = vDated
|
||||||
|
);
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE tStockBought, tmp.item, tmp.buyUltimate;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -4,5 +4,14 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`travelThermograph_befor
|
||||||
FOR EACH ROW
|
FOR EACH ROW
|
||||||
BEGIN
|
BEGIN
|
||||||
SET NEW.editorFk = account.myUser_getId();
|
SET NEW.editorFk = account.myUser_getId();
|
||||||
|
|
||||||
|
IF NEW.travelFk IS NULL AND
|
||||||
|
(SELECT COUNT(*) FROM travelThermograph
|
||||||
|
WHERE thermographFk = NEW.thermographFk
|
||||||
|
AND travelFk IS NULL
|
||||||
|
AND id <> NEW.id) > 0
|
||||||
|
THEN
|
||||||
|
CALL util.throw('Duplicate thermographFk without travelFk not allowed.');
|
||||||
|
END IF;
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
|
@ -4,5 +4,14 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`travelThermograph_befor
|
||||||
FOR EACH ROW
|
FOR EACH ROW
|
||||||
BEGIN
|
BEGIN
|
||||||
SET NEW.editorFk = account.myUser_getId();
|
SET NEW.editorFk = account.myUser_getId();
|
||||||
|
|
||||||
|
IF NEW.travelFk IS NULL AND
|
||||||
|
(SELECT COUNT(*) FROM travelThermograph
|
||||||
|
WHERE thermographFk = NEW.thermographFk
|
||||||
|
AND travelFk IS NULL
|
||||||
|
AND id <> NEW.id) > 0
|
||||||
|
THEN
|
||||||
|
CALL util.throw('Duplicate thermographFk without travelFk not allowed.');
|
||||||
|
END IF;
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
-- Place your SQL code here
|
||||||
|
-- vn.stockBought definition
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS vn.stockBought (
|
||||||
|
id INT UNSIGNED auto_increment NOT NULL,
|
||||||
|
workerFk int(10) unsigned NOT NULL,
|
||||||
|
bought decimal(10,2) NOT NULL COMMENT 'purchase volume in m3 for the day',
|
||||||
|
reserve decimal(10,2) NULL COMMENT 'reserved volume in m3 for the day',
|
||||||
|
dated DATE NOT NULL DEFAULT current_timestamp(),
|
||||||
|
CONSTRAINT stockBought_pk PRIMARY KEY (id),
|
||||||
|
CONSTRAINT stockBought_unique UNIQUE KEY (workerFk,dated),
|
||||||
|
CONSTRAINT stockBought_worker_FK FOREIGN KEY (workerFk) REFERENCES vn.worker(id)
|
||||||
|
)
|
||||||
|
ENGINE=InnoDB
|
||||||
|
DEFAULT CHARSET=utf8mb3
|
||||||
|
COLLATE=utf8mb3_unicode_ci;
|
||||||
|
|
||||||
|
|
||||||
|
INSERT IGNORE vn.stockBought (workerFk, bought, reserve, dated)
|
||||||
|
SELECT userFk, SUM(buyed), SUM(IFNULL(reserved,0)), dated
|
||||||
|
FROM vn.stockBuyed
|
||||||
|
WHERE userFk IS NOT NULL
|
||||||
|
AND buyed IS NOT NULL
|
||||||
|
GROUP BY userFk, dated;
|
||||||
|
|
||||||
|
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
|
||||||
|
VALUES ('StockBought','*','READ','ALLOW','ROLE','buyer'),
|
||||||
|
('StockBought','*','WRITE','ALLOW','ROLE','buyer'),
|
||||||
|
('Buyer','*','READ','ALLOW','ROLE','buyer');
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('SmartTable SearchBar integration', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('salesPerson', 'item');
|
|
||||||
await page.waitToClick(selectors.globalItems.searchButton);
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should search by type in searchBar, reload page and have same results', async() => {
|
|
||||||
await page.waitToClick(selectors.itemsIndex.openAdvancedSearchButton);
|
|
||||||
await page.autocompleteSearch(selectors.itemsIndex.advancedSearchItemType, 'Anthurium');
|
|
||||||
await page.waitToClick(selectors.itemsIndex.advancedSearchButton);
|
|
||||||
await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 4);
|
|
||||||
|
|
||||||
await page.reload({
|
|
||||||
waitUntil: 'networkidle2'
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 4);
|
|
||||||
|
|
||||||
await page.write(selectors.itemsIndex.advancedSmartTableGrouping, '1');
|
|
||||||
await page.keyboard.press('Enter');
|
|
||||||
await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 2);
|
|
||||||
|
|
||||||
await page.reload({
|
|
||||||
waitUntil: 'networkidle2'
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should filter in section without smart-table and search in searchBar go to zone section', async() => {
|
|
||||||
await page.loginAndModule('salesPerson', 'zone');
|
|
||||||
await page.waitToClick(selectors.globalItems.searchButton);
|
|
||||||
|
|
||||||
await page.doSearch('A');
|
|
||||||
const firstCount = await page.countElement(selectors.zoneIndex.searchResult);
|
|
||||||
|
|
||||||
await page.doSearch('A');
|
|
||||||
const secondCount = await page.countElement(selectors.zoneIndex.searchResult);
|
|
||||||
|
|
||||||
expect(firstCount).toEqual(7);
|
|
||||||
expect(secondCount).toEqual(7);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should order orders by first id and order by last id, reload page and have same order', async() => {
|
|
||||||
await page.loginAndModule('developer', 'item');
|
|
||||||
await page.accessToSection('item.fixedPrice');
|
|
||||||
await page.keyboard.press('Enter');
|
|
||||||
|
|
||||||
await page.waitForTextInField(selectors.itemFixedPrice.firstItemID, '1');
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.itemFixedPrice.orderColumnId);
|
|
||||||
await page.reload({
|
|
||||||
waitUntil: 'networkidle2'
|
|
||||||
});
|
|
||||||
await page.waitForTextInField(selectors.itemFixedPrice.firstItemID, '3');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,104 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('Zone basic data path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
|
|
||||||
await page.loginAndModule('deliveryAssistant',
|
|
||||||
'zone'); // turns up the zone module name and route aint the same lol
|
|
||||||
await page.accessToSearchResult('10');
|
|
||||||
await page.accessToSection('zone.card.basicData');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reach the basic data section', async() => {
|
|
||||||
await page.waitForState('zone.card.basicData');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should edit de form and then save', async() => {
|
|
||||||
await page.clearInput(selectors.zoneBasicData.name);
|
|
||||||
await page.write(selectors.zoneBasicData.name, 'Brimstone teleportation');
|
|
||||||
await page.autocompleteSearch(selectors.zoneBasicData.agency, 'Quantum break device');
|
|
||||||
await page.clearInput(selectors.zoneBasicData.maxVolume);
|
|
||||||
await page.write(selectors.zoneBasicData.maxVolume, '10');
|
|
||||||
await page.clearInput(selectors.zoneBasicData.travelingDays);
|
|
||||||
await page.write(selectors.zoneBasicData.travelingDays, '1');
|
|
||||||
await page.clearInput(selectors.zoneBasicData.closing);
|
|
||||||
await page.pickTime(selectors.zoneBasicData.closing, '21:00');
|
|
||||||
await page.clearInput(selectors.zoneBasicData.price);
|
|
||||||
await page.write(selectors.zoneBasicData.price, '999');
|
|
||||||
await page.clearInput(selectors.zoneBasicData.bonus);
|
|
||||||
await page.write(selectors.zoneBasicData.bonus, '100');
|
|
||||||
await page.clearInput(selectors.zoneBasicData.inflation);
|
|
||||||
await page.write(selectors.zoneBasicData.inflation, '200');
|
|
||||||
await page.waitToClick(selectors.zoneBasicData.volumetric);
|
|
||||||
await page.waitToClick(selectors.zoneBasicData.saveButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should now reload the section', async() => {
|
|
||||||
await page.reloadSection('zone.card.basicData');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should confirm the name was updated', async() => {
|
|
||||||
const result = await page.waitToGetProperty(selectors.zoneBasicData.name, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('Brimstone teleportation');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should confirm the agency was updated', async() => {
|
|
||||||
const result = await page.waitToGetProperty(selectors.zoneBasicData.agency, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('Quantum break device');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should confirm the max volume was updated', async() => {
|
|
||||||
const result = await page.waitToGetProperty(selectors.zoneBasicData.maxVolume, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('10');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should confirm the traveling days were updated', async() => {
|
|
||||||
const result = await page.waitToGetProperty(selectors.zoneBasicData.travelingDays, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('1');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should confirm the closing hour was updated', async() => {
|
|
||||||
const result = await page.waitToGetProperty(selectors.zoneBasicData.closing, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('21:00');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should confirm the price was updated', async() => {
|
|
||||||
const result = await page.waitToGetProperty(selectors.zoneBasicData.price, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('999');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should confirm the bonus was updated', async() => {
|
|
||||||
const result = await page.waitToGetProperty(selectors.zoneBasicData.bonus, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('100');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should confirm the inflation was updated', async() => {
|
|
||||||
const result = await page.waitToGetProperty(selectors.zoneBasicData.inflation, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('200');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should confirm the volumetric checkbox was checked', async() => {
|
|
||||||
await page.waitForClassPresent(selectors.zoneBasicData.volumetric, 'checked');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,32 +0,0 @@
|
||||||
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('deliveryAssistant', '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);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('getStockBought', {
|
||||||
|
description: 'Returns the stock bought for a given date',
|
||||||
|
accessType: 'READ',
|
||||||
|
accepts: [{
|
||||||
|
arg: 'workerFk',
|
||||||
|
type: 'number',
|
||||||
|
description: 'The id for a buyer',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'dated',
|
||||||
|
type: 'date',
|
||||||
|
description: 'The date to filter',
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: ['object'],
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/getStockBought`,
|
||||||
|
verb: 'GET'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.getStockBought = async(workerFk, dated = Date.vnNew()) => {
|
||||||
|
const models = Self.app.models;
|
||||||
|
const today = Date.vnNew();
|
||||||
|
dated.setHours(0, 0, 0, 0);
|
||||||
|
today.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
|
await models.StockBought.rawSql(`CALL vn.stockBought_calculate(?)`, [dated]);
|
||||||
|
|
||||||
|
const filter = {
|
||||||
|
where: {dated},
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
fields: ['workerFk', 'reserve', 'bought'],
|
||||||
|
relation: 'worker',
|
||||||
|
scope: {
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
relation: 'user',
|
||||||
|
scope: {
|
||||||
|
fields: ['id', 'name']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
if (workerFk) filter.where.workerFk = workerFk;
|
||||||
|
|
||||||
|
return models.StockBought.find(filter);
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,74 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('getStockBoughtDetail', {
|
||||||
|
description: 'Returns the detail of stock bought for a given date and a worker',
|
||||||
|
accessType: 'READ',
|
||||||
|
accepts: [{
|
||||||
|
arg: 'workerFk',
|
||||||
|
type: 'number',
|
||||||
|
description: 'The worker to filter',
|
||||||
|
required: true,
|
||||||
|
}, {
|
||||||
|
arg: 'dated',
|
||||||
|
type: 'string',
|
||||||
|
description: 'The date to filter',
|
||||||
|
required: true,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: ['object'],
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/getStockBoughtDetail`,
|
||||||
|
verb: 'GET'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.getStockBoughtDetail = async(workerFk, dated) => {
|
||||||
|
const models = Self.app.models;
|
||||||
|
const myOptions = {};
|
||||||
|
let tx;
|
||||||
|
let result;
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
|
if (!myOptions.transaction) {
|
||||||
|
tx = await Self.beginTransaction({});
|
||||||
|
myOptions.transaction = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await models.StockBought.rawSql(`CALL vn.item_calculateStock(?)`, [dated], myOptions);
|
||||||
|
result = await Self.rawSql(
|
||||||
|
`SELECT b.entryFk entryFk,
|
||||||
|
i.id itemFk,
|
||||||
|
i.name itemName,
|
||||||
|
ti.quantity,
|
||||||
|
(ac.conversionCoefficient * (ti.quantity / b.packing) * buy_getVolume(b.id))
|
||||||
|
/ (vc.trolleyM3 * 1000000) volume,
|
||||||
|
b.packagingFk packagingFk,
|
||||||
|
b.packing
|
||||||
|
FROM tmp.item ti
|
||||||
|
JOIN item i ON i.id = ti.itemFk
|
||||||
|
JOIN itemType it ON i.typeFk = it.id
|
||||||
|
JOIN itemCategory ic ON ic.id = it.categoryFk
|
||||||
|
JOIN worker w ON w.id = it.workerFk
|
||||||
|
JOIN auctionConfig ac
|
||||||
|
JOIN tmp.buyUltimate bu ON bu.itemFk = i.id
|
||||||
|
AND bu.warehouseFk = ac.warehouseFk
|
||||||
|
JOIN buy b ON b.id = bu.buyFk
|
||||||
|
JOIN volumeConfig vc
|
||||||
|
WHERE ic.display
|
||||||
|
AND w.id = ?`,
|
||||||
|
[workerFk], myOptions
|
||||||
|
);
|
||||||
|
await Self.rawSql(`DROP TEMPORARY TABLE tmp.item, tmp.buyUltimate;`, [], myOptions);
|
||||||
|
if (tx) await tx.commit();
|
||||||
|
return result;
|
||||||
|
} catch (e) {
|
||||||
|
await tx.rollback();
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -25,5 +25,8 @@
|
||||||
},
|
},
|
||||||
"EntryType": {
|
"EntryType": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
|
"StockBought": {
|
||||||
|
"dataSource": "vn"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
module.exports = Self => {
|
||||||
|
require('../methods/stock-bought/getStockBought')(Self);
|
||||||
|
require('../methods/stock-bought/getStockBoughtDetail')(Self);
|
||||||
|
Self.rewriteDbError(function(err) {
|
||||||
|
if (err.code === 'ER_DUP_ENTRY')
|
||||||
|
return new UserError(`This buyer has already made a reservation for this date`);
|
||||||
|
return err;
|
||||||
|
});
|
||||||
|
};
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"name": "StockBought",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "stockBought"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "number",
|
||||||
|
"id": true
|
||||||
|
},
|
||||||
|
"workerFk": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"bought": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"reserve": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"dated": {
|
||||||
|
"type": "date"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"worker": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Worker",
|
||||||
|
"foreignKey": "workerFk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -117,7 +117,8 @@ module.exports = Self => {
|
||||||
result: state,
|
result: state,
|
||||||
maxTemperature,
|
maxTemperature,
|
||||||
minTemperature,
|
minTemperature,
|
||||||
temperatureFk
|
temperatureFk,
|
||||||
|
warehouseFk: warehouseId,
|
||||||
}, myOptions);
|
}, myOptions);
|
||||||
|
|
||||||
if (tx) await tx.commit();
|
if (tx) await tx.commit();
|
||||||
|
|
|
@ -4,7 +4,7 @@ describe('Thermograph saveThermograph()', () => {
|
||||||
const ctx = beforeAll.getCtx();
|
const ctx = beforeAll.getCtx();
|
||||||
const travelFk = 1;
|
const travelFk = 1;
|
||||||
const thermographId = '138350-0';
|
const thermographId = '138350-0';
|
||||||
const warehouseFk = '1';
|
const warehouseFk = 1;
|
||||||
const state = 'COMPLETED';
|
const state = 'COMPLETED';
|
||||||
const maxTemperature = 30;
|
const maxTemperature = 30;
|
||||||
const minTemperature = 10;
|
const minTemperature = 10;
|
||||||
|
@ -41,7 +41,7 @@ describe('Thermograph saveThermograph()', () => {
|
||||||
maxTemperature,
|
maxTemperature,
|
||||||
minTemperature,
|
minTemperature,
|
||||||
temperatureFk,
|
temperatureFk,
|
||||||
null,
|
warehouseFk,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
|
|
|
@ -1,114 +0,0 @@
|
||||||
<mg-ajax path="Zones/{{patch.params.id}}" options="vnPatch"></mg-ajax>
|
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
data="$ctrl.zone"
|
|
||||||
form="form"
|
|
||||||
save="patch">
|
|
||||||
</vn-watcher>
|
|
||||||
<form
|
|
||||||
name="form"
|
|
||||||
ng-submit="$ctrl.onSubmit()"
|
|
||||||
class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
label="Name"
|
|
||||||
ng-model="$ctrl.zone.name"
|
|
||||||
vn-acl="deliveryAssistant"
|
|
||||||
rule>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
ng-model="$ctrl.zone.agencyModeFk"
|
|
||||||
url="AgencyModes"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
label="Agency"
|
|
||||||
vn-acl="deliveryAssistant"
|
|
||||||
rule>
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-input-number
|
|
||||||
vn-one
|
|
||||||
label="Max m³"
|
|
||||||
ng-model="$ctrl.zone.itemMaxSize"
|
|
||||||
min="0"
|
|
||||||
vn-acl="deliveryAssistant"
|
|
||||||
rule>
|
|
||||||
</vn-input-number>
|
|
||||||
<vn-input-number
|
|
||||||
vn-one
|
|
||||||
label="Maximum m³"
|
|
||||||
ng-model="$ctrl.zone.m3Max"
|
|
||||||
min="0"
|
|
||||||
vn-acl="deliveryAssistant"
|
|
||||||
rule>
|
|
||||||
</vn-input-number>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-input-number
|
|
||||||
label="Traveling days"
|
|
||||||
ng-model="$ctrl.zone.travelingDays"
|
|
||||||
min="0"
|
|
||||||
step="1"
|
|
||||||
vn-acl="deliveryAssistant"
|
|
||||||
rule>
|
|
||||||
</vn-input-number>
|
|
||||||
<vn-input-time
|
|
||||||
label="Closing"
|
|
||||||
ng-model="$ctrl.zone.hour"
|
|
||||||
vn-acl="deliveryAssistant"
|
|
||||||
rule>
|
|
||||||
</vn-input-time>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-input-number
|
|
||||||
label="Price"
|
|
||||||
ng-model="$ctrl.zone.price"
|
|
||||||
min="0"
|
|
||||||
step="0.01"
|
|
||||||
vn-acl="deliveryAssistant"
|
|
||||||
rule>
|
|
||||||
</vn-input-number>
|
|
||||||
<vn-input-number
|
|
||||||
label="Bonus"
|
|
||||||
ng-model="$ctrl.zone.bonus"
|
|
||||||
step="0.01"
|
|
||||||
vn-acl="deliveryAssistant"
|
|
||||||
rule>
|
|
||||||
</vn-input-number>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-input-number
|
|
||||||
vn-one
|
|
||||||
label="Inflation"
|
|
||||||
ng-model="$ctrl.zone.inflation"
|
|
||||||
min="0"
|
|
||||||
step="0.01"
|
|
||||||
vn-acl="deliveryAssistant"
|
|
||||||
rule>
|
|
||||||
</vn-input-number>
|
|
||||||
<vn-check
|
|
||||||
vn-one
|
|
||||||
label="Volumetric"
|
|
||||||
ng-model="$ctrl.zone.isVolumetric"
|
|
||||||
vn-acl="deliveryAssistant"
|
|
||||||
rule>
|
|
||||||
</vn-check>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
vn-acl="deliveryAssistant"
|
|
||||||
label="Save">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Undo changes"
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
ng-click="watcher.loadOriginalData()">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
|
@ -1,21 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
|
||||||
onSubmit() {
|
|
||||||
this.$.watcher.submit().then(() =>
|
|
||||||
this.card.reload()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnZoneBasicData', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
zone: '<'
|
|
||||||
},
|
|
||||||
require: {
|
|
||||||
card: '^vnZoneCard'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,33 +0,0 @@
|
||||||
<vn-card>
|
|
||||||
<div class="header">
|
|
||||||
<vn-button
|
|
||||||
icon="navigate_before"
|
|
||||||
ng-click="$ctrl.step(-1)"
|
|
||||||
class="flat">
|
|
||||||
</vn-button>
|
|
||||||
<div>
|
|
||||||
<span translate>{{$ctrl.firstDay | date:'MMMM'}}</span>
|
|
||||||
<span>{{$ctrl.firstDay | date:'yyyy'}} -</span>
|
|
||||||
<span translate>{{$ctrl.lastDay | date:'MMMM'}}</span>
|
|
||||||
<span>{{$ctrl.lastDay | date:'yyyy'}}</span>
|
|
||||||
</div>
|
|
||||||
<vn-button
|
|
||||||
icon="navigate_next"
|
|
||||||
ng-click="$ctrl.step(1)"
|
|
||||||
class="flat">
|
|
||||||
</vn-button>
|
|
||||||
</div>
|
|
||||||
<div class="calendars vn-pa-md">
|
|
||||||
<vn-calendar
|
|
||||||
ng-repeat="date in $ctrl.months track by date.getTime()"
|
|
||||||
default-date="date"
|
|
||||||
display-controls="false"
|
|
||||||
hide-contiguous="true"
|
|
||||||
has-events="$ctrl.hasEvents($day)"
|
|
||||||
get-class="$ctrl.getClass($day)"
|
|
||||||
on-selection="$ctrl.onSelection($event, $days, $type, $weekday)"
|
|
||||||
class="vn-pa-md"
|
|
||||||
style="min-width: 250px; flex: 1;">
|
|
||||||
</vn-calendar>
|
|
||||||
</div>
|
|
||||||
</vn-card>
|
|
|
@ -1,191 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Component from 'core/lib/component';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
class Controller extends Component {
|
|
||||||
constructor($element, $, vnWeekDays) {
|
|
||||||
super($element, $);
|
|
||||||
this.vnWeekDays = vnWeekDays;
|
|
||||||
this.nMonths = 4;
|
|
||||||
|
|
||||||
let date = Date.vnNew();
|
|
||||||
date.setDate(1);
|
|
||||||
date.setHours(0, 0, 0, 0);
|
|
||||||
this.date = date;
|
|
||||||
}
|
|
||||||
|
|
||||||
get date() {
|
|
||||||
return this._date;
|
|
||||||
}
|
|
||||||
|
|
||||||
set date(value) {
|
|
||||||
this._date = value;
|
|
||||||
let stamp = value.getTime();
|
|
||||||
|
|
||||||
let firstDay = new Date(stamp);
|
|
||||||
firstDay.setDate(1);
|
|
||||||
this.firstDay = firstDay;
|
|
||||||
|
|
||||||
let lastDay = new Date(stamp);
|
|
||||||
lastDay.setMonth(lastDay.getMonth() + this.nMonths);
|
|
||||||
lastDay.setDate(0);
|
|
||||||
this.lastDay = lastDay;
|
|
||||||
|
|
||||||
this.months = [];
|
|
||||||
for (let i = 0; i < this.nMonths; i++) {
|
|
||||||
let monthDate = new Date(stamp);
|
|
||||||
monthDate.setMonth(value.getMonth() + i);
|
|
||||||
this.months.push(monthDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.refreshEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
step(direction) {
|
|
||||||
let date = new Date(this.date.getTime());
|
|
||||||
date.setMonth(date.getMonth() + (this.nMonths * direction));
|
|
||||||
this.date = date;
|
|
||||||
|
|
||||||
this.emit('step');
|
|
||||||
}
|
|
||||||
|
|
||||||
get data() {
|
|
||||||
return this._data;
|
|
||||||
}
|
|
||||||
|
|
||||||
set data(value) {
|
|
||||||
this._data = value;
|
|
||||||
|
|
||||||
value = value || {};
|
|
||||||
|
|
||||||
this.events = value.events;
|
|
||||||
|
|
||||||
function toStamp(date) {
|
|
||||||
return date && new Date(date).setHours(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.exclusions = {};
|
|
||||||
let exclusions = value.exclusions;
|
|
||||||
|
|
||||||
if (exclusions) {
|
|
||||||
for (let exclusion of exclusions) {
|
|
||||||
let stamp = toStamp(exclusion.dated);
|
|
||||||
if (!this.exclusions[stamp]) this.exclusions[stamp] = [];
|
|
||||||
this.exclusions[stamp].push(exclusion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.geoExclusions = {};
|
|
||||||
let geoExclusions = value.geoExclusions;
|
|
||||||
|
|
||||||
if (geoExclusions) {
|
|
||||||
for (let geoExclusion of geoExclusions) {
|
|
||||||
let stamp = toStamp(geoExclusion.dated);
|
|
||||||
if (!this.geoExclusions[stamp]) this.geoExclusions[stamp] = [];
|
|
||||||
this.geoExclusions[stamp].push(geoExclusion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let events = value.events;
|
|
||||||
|
|
||||||
if (events) {
|
|
||||||
for (let event of events) {
|
|
||||||
event.dated = toStamp(event.dated);
|
|
||||||
event.ended = toStamp(event.ended);
|
|
||||||
event.started = toStamp(event.started);
|
|
||||||
event.wdays = this.vnWeekDays.fromSet(event.weekDays);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.refreshEvents();
|
|
||||||
|
|
||||||
let calendars = this.element.querySelectorAll('vn-calendar');
|
|
||||||
for (let calendar of calendars)
|
|
||||||
calendar.$ctrl.repaint();
|
|
||||||
}
|
|
||||||
|
|
||||||
refreshEvents() {
|
|
||||||
this.days = {};
|
|
||||||
if (!this.data) return;
|
|
||||||
|
|
||||||
let day = new Date(this.firstDay.getTime());
|
|
||||||
|
|
||||||
while (day <= this.lastDay) {
|
|
||||||
let stamp = day.getTime();
|
|
||||||
let wday = day.getDay();
|
|
||||||
let dayEvents = [];
|
|
||||||
let exclusions = this.exclusions[stamp] || [];
|
|
||||||
|
|
||||||
if (this.events) {
|
|
||||||
for (let event of this.events) {
|
|
||||||
let match;
|
|
||||||
|
|
||||||
switch (event.type) {
|
|
||||||
case 'day':
|
|
||||||
match = event.dated == stamp;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
match = event.wdays[wday]
|
|
||||||
&& (!event.started || stamp >= event.started)
|
|
||||||
&& (!event.ended || stamp <= event.ended);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (match && !exclusions.find(e => e.zoneFk == event.zoneFk))
|
|
||||||
dayEvents.push(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dayEvents.length)
|
|
||||||
this.days[stamp] = dayEvents;
|
|
||||||
|
|
||||||
day.setDate(day.getDate() + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onSelection($event, $days, $type, $weekday) {
|
|
||||||
let $events = [];
|
|
||||||
let $exclusions = [];
|
|
||||||
let $geoExclusions = [];
|
|
||||||
|
|
||||||
for (let day of $days) {
|
|
||||||
let stamp = day.getTime();
|
|
||||||
$events = $events.concat(this.days[stamp] || []);
|
|
||||||
$exclusions = $exclusions.concat(this.exclusions[stamp] || []);
|
|
||||||
$geoExclusions = $geoExclusions.concat(this.geoExclusions[stamp] || []);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.emit('selection', {
|
|
||||||
$event,
|
|
||||||
$days,
|
|
||||||
$type,
|
|
||||||
$weekday,
|
|
||||||
$events,
|
|
||||||
$exclusions,
|
|
||||||
$geoExclusions
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
hasEvents(day) {
|
|
||||||
let stamp = day.getTime();
|
|
||||||
return this.days[stamp] || this.exclusions[stamp] || this.geoExclusions[stamp];
|
|
||||||
}
|
|
||||||
|
|
||||||
getClass(day) {
|
|
||||||
let stamp = day.getTime();
|
|
||||||
if (this.geoExclusions[stamp])
|
|
||||||
return 'geoExcluded';
|
|
||||||
else if (this.exclusions[stamp])
|
|
||||||
return 'excluded';
|
|
||||||
else return '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Controller.$inject = ['$element', '$scope', 'vnWeekDays'];
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnZoneCalendar', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
data: '<?'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,172 +0,0 @@
|
||||||
import './index';
|
|
||||||
import crudModel from 'core/mocks/crud-model';
|
|
||||||
|
|
||||||
describe('component vnZoneCalendar', () => {
|
|
||||||
let $scope;
|
|
||||||
let controller;
|
|
||||||
|
|
||||||
beforeEach(ngModule('zone'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, $rootScope) => {
|
|
||||||
$scope = $rootScope.$new();
|
|
||||||
const $element = angular.element(`<vn-zone-calendar></vn-zone-calendar>`);
|
|
||||||
controller = $componentController('vnZoneCalendar', {$element, $scope});
|
|
||||||
controller.$.model = crudModel;
|
|
||||||
controller.zone = {id: 1};
|
|
||||||
controller.days = [];
|
|
||||||
controller.exclusions = [];
|
|
||||||
controller.geoExclusions = [];
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('date() setter', () => {
|
|
||||||
it('should set the month property and then call the refreshEvents() method', () => {
|
|
||||||
jest.spyOn(controller, 'refreshEvents').mockReturnThis();
|
|
||||||
|
|
||||||
controller.date = Date.vnNew();
|
|
||||||
|
|
||||||
expect(controller.refreshEvents).toHaveBeenCalledWith();
|
|
||||||
expect(controller.months.length).toEqual(4);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('step()', () => {
|
|
||||||
it('should set the date month to 4 months backwards', () => {
|
|
||||||
const now = Date.vnNew();
|
|
||||||
now.setDate(15);
|
|
||||||
now.setMonth(now.getMonth() - 4);
|
|
||||||
|
|
||||||
controller.step(-1);
|
|
||||||
|
|
||||||
const expectedMonth = now.getMonth();
|
|
||||||
const currentMonth = controller.date.getMonth();
|
|
||||||
|
|
||||||
expect(currentMonth).toEqual(expectedMonth);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set the date month to 4 months forwards', () => {
|
|
||||||
const now = Date.vnNew();
|
|
||||||
now.setDate(15);
|
|
||||||
now.setMonth(now.getMonth() + 4);
|
|
||||||
|
|
||||||
controller.step(1);
|
|
||||||
|
|
||||||
const expectedMonth = now.getMonth();
|
|
||||||
const currentMonth = controller.date.getMonth();
|
|
||||||
|
|
||||||
expect(currentMonth).toEqual(expectedMonth);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('data() setter', () => {
|
|
||||||
it('should set the events, exclusions and geoExclusions and then call the refreshEvents() method', () => {
|
|
||||||
jest.spyOn(controller, 'refreshEvents').mockReturnThis();
|
|
||||||
|
|
||||||
controller.data = {
|
|
||||||
exclusions: [{
|
|
||||||
dated: Date.vnNew()
|
|
||||||
}],
|
|
||||||
events: [{
|
|
||||||
dated: Date.vnNew()
|
|
||||||
}],
|
|
||||||
geoExclusions: [{
|
|
||||||
dated: Date.vnNew()
|
|
||||||
}],
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(controller.refreshEvents).toHaveBeenCalledWith();
|
|
||||||
expect(controller.events).toBeDefined();
|
|
||||||
expect(controller.events.length).toEqual(1);
|
|
||||||
expect(controller.exclusions).toBeDefined();
|
|
||||||
expect(controller.geoExclusions).toBeDefined();
|
|
||||||
expect(Object.keys(controller.exclusions).length).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('refreshEvents()', () => {
|
|
||||||
it('should fill the days property with the events.', () => {
|
|
||||||
controller.data = [];
|
|
||||||
controller.firstDay = Date.vnNew();
|
|
||||||
|
|
||||||
const lastDay = Date.vnNew();
|
|
||||||
lastDay.setDate(lastDay.getDate() + 10);
|
|
||||||
controller.lastDay = lastDay;
|
|
||||||
|
|
||||||
const firstEventStamp = controller.firstDay.getTime();
|
|
||||||
const lastEventStamp = controller.lastDay.getTime();
|
|
||||||
controller.events = [{
|
|
||||||
type: 'day',
|
|
||||||
dated: firstEventStamp
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'day',
|
|
||||||
dated: lastEventStamp
|
|
||||||
}];
|
|
||||||
|
|
||||||
controller.refreshEvents();
|
|
||||||
const expectedDays = Object.keys(controller.days);
|
|
||||||
|
|
||||||
expect(expectedDays.length).toEqual(2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onSelection()', () => {
|
|
||||||
it('should call the emit() method', () => {
|
|
||||||
jest.spyOn(controller, 'emit');
|
|
||||||
|
|
||||||
const $event = {};
|
|
||||||
const $days = [Date.vnNew()];
|
|
||||||
const $type = 'day';
|
|
||||||
const $weekday = 1;
|
|
||||||
|
|
||||||
controller.onSelection($event, $days, $type, $weekday);
|
|
||||||
|
|
||||||
expect(controller.emit).toHaveBeenCalledWith('selection',
|
|
||||||
{
|
|
||||||
$days: $days,
|
|
||||||
$event: {},
|
|
||||||
$events: [],
|
|
||||||
$exclusions: [],
|
|
||||||
$type: 'day',
|
|
||||||
$weekday: 1,
|
|
||||||
$geoExclusions: [],
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('hasEvents()', () => {
|
|
||||||
it('should return true for an existing event on a date', () => {
|
|
||||||
const dated = Date.vnNew();
|
|
||||||
|
|
||||||
controller.days[dated.getTime()] = true;
|
|
||||||
|
|
||||||
const result = controller.hasEvents(dated);
|
|
||||||
|
|
||||||
expect(result).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('getClass()', () => {
|
|
||||||
it('should return the className "excluded" for an excluded date', () => {
|
|
||||||
const dated = Date.vnNew();
|
|
||||||
|
|
||||||
controller.exclusions = [];
|
|
||||||
controller.exclusions[dated.getTime()] = true;
|
|
||||||
|
|
||||||
const result = controller.getClass(dated);
|
|
||||||
|
|
||||||
expect(result).toEqual('excluded');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return the className "geoExcluded" for a date with geo excluded', () => {
|
|
||||||
const dated = Date.vnNew();
|
|
||||||
|
|
||||||
controller.geoExclusions = [];
|
|
||||||
controller.geoExclusions[dated.getTime()] = true;
|
|
||||||
|
|
||||||
const result = controller.getClass(dated);
|
|
||||||
|
|
||||||
expect(result).toEqual('geoExcluded');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,43 +0,0 @@
|
||||||
@import "variables";
|
|
||||||
|
|
||||||
vn-zone-calendar {
|
|
||||||
display: block;
|
|
||||||
|
|
||||||
& > vn-card {
|
|
||||||
& > .header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
background-color: $color-main;
|
|
||||||
color: white;
|
|
||||||
font-weight: bold;
|
|
||||||
height: 45px;
|
|
||||||
|
|
||||||
& > .vn-button {
|
|
||||||
color: inherit;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
& > .calendars {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: space-evenly;
|
|
||||||
|
|
||||||
& > .vn-calendar {
|
|
||||||
max-width: 288px;
|
|
||||||
|
|
||||||
#days-container .day {
|
|
||||||
&.event .day-number {
|
|
||||||
background-color: $color-success;
|
|
||||||
}
|
|
||||||
&.excluded .day-number {
|
|
||||||
background-color: $color-alert;
|
|
||||||
}
|
|
||||||
&.geoExcluded .day-number {
|
|
||||||
background-color: $color-main;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
<vn-portal slot="menu">
|
|
||||||
<vn-zone-descriptor zone="$ctrl.zone"></vn-zone-descriptor>
|
|
||||||
<vn-left-menu source="card"></vn-left-menu>
|
|
||||||
</vn-portal>
|
|
||||||
<ui-view></ui-view>
|
|
|
@ -1,21 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import ModuleCard from 'salix/components/module-card';
|
|
||||||
|
|
||||||
class Controller extends ModuleCard {
|
|
||||||
reload() {
|
|
||||||
let filter = {
|
|
||||||
include: {
|
|
||||||
relation: 'agencyMode',
|
|
||||||
scope: {fields: ['name']}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.$http.get(`Zones/${this.$params.id}`, {filter})
|
|
||||||
.then(res => this.zone = res.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnZoneCard', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,26 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
|
|
||||||
describe('Zone Component vnZoneCard', () => {
|
|
||||||
let controller;
|
|
||||||
let $httpBackend;
|
|
||||||
let data = {id: 1, name: 'fooName'};
|
|
||||||
|
|
||||||
beforeEach(ngModule('zone'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, _$httpBackend_, $stateParams) => {
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
|
|
||||||
let $element = angular.element('<div></div>');
|
|
||||||
controller = $componentController('vnZoneCard', {$element});
|
|
||||||
|
|
||||||
$stateParams.id = data.id;
|
|
||||||
$httpBackend.whenRoute('GET', 'Zones/:id').respond(data);
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should request data and set it on the controller', () => {
|
|
||||||
controller.reload();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.zone).toEqual(data);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,98 +0,0 @@
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
url="Zones"
|
|
||||||
data="$ctrl.zone"
|
|
||||||
insert-mode="true"
|
|
||||||
form="form">
|
|
||||||
</vn-watcher>
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="Warehouses"
|
|
||||||
data="warehouses"
|
|
||||||
order="name">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="AgencyModes/isActive"
|
|
||||||
data="activeAgencyModes"
|
|
||||||
order="name">
|
|
||||||
</vn-crud-model>
|
|
||||||
<form
|
|
||||||
name="form"
|
|
||||||
vn-http-submit="$ctrl.onSubmit()"
|
|
||||||
class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
label="Name"
|
|
||||||
ng-model="$ctrl.zone.name"
|
|
||||||
rule
|
|
||||||
vn-focus>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Warehouse"
|
|
||||||
ng-model="$ctrl.zone.warehouseFk"
|
|
||||||
data="warehouses"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
label="Warehouse"
|
|
||||||
rule>
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Agency"
|
|
||||||
ng-model="$ctrl.zone.agencyModeFk"
|
|
||||||
data="activeAgencyModes"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
label="Agency"
|
|
||||||
rule>
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-input-number
|
|
||||||
label="Traveling days"
|
|
||||||
ng-model="$ctrl.zone.travelingDays"
|
|
||||||
min="0"
|
|
||||||
step="1"
|
|
||||||
rule>
|
|
||||||
</vn-input-number>
|
|
||||||
<vn-input-time
|
|
||||||
label="Closing hour"
|
|
||||||
ng-model="$ctrl.zone.hour"
|
|
||||||
rule>
|
|
||||||
</vn-input-time>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-input-number
|
|
||||||
label="Price"
|
|
||||||
ng-model="$ctrl.zone.price"
|
|
||||||
min="0"
|
|
||||||
step="0.01"
|
|
||||||
rule>
|
|
||||||
</vn-input-number>
|
|
||||||
<vn-input-number
|
|
||||||
label="Bonus"
|
|
||||||
ng-model="$ctrl.zone.bonus"
|
|
||||||
min="0"
|
|
||||||
step="0.01"
|
|
||||||
rule>
|
|
||||||
</vn-input-number>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-check ng-model="$ctrl.zone.isVolumetric" label="Volumetric"></vn-check>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Create">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Cancel"
|
|
||||||
ui-sref="zone.index">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
|
@ -1,24 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
$onInit() {
|
|
||||||
this.zone = {
|
|
||||||
travelingDays: 0,
|
|
||||||
price: 0.20,
|
|
||||||
bonus: 0.20,
|
|
||||||
hour: Date.vnNew()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
onSubmit() {
|
|
||||||
return this.$.watcher.submit().then(res =>
|
|
||||||
this.$state.go('zone.card.location', {id: res.data.id})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnZoneCreate', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,40 +0,0 @@
|
||||||
import './index';
|
|
||||||
import watcher from 'core/mocks/watcher';
|
|
||||||
|
|
||||||
describe('Zone Component vnZoneCreate', () => {
|
|
||||||
let $scope;
|
|
||||||
let $state;
|
|
||||||
let controller;
|
|
||||||
|
|
||||||
beforeEach(ngModule('zone'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, $rootScope, _$state_) => {
|
|
||||||
$scope = $rootScope.$new();
|
|
||||||
$state = _$state_;
|
|
||||||
$scope.watcher = watcher;
|
|
||||||
$scope.watcher.submit = () => {
|
|
||||||
return {
|
|
||||||
then: callback => {
|
|
||||||
callback({data: {id: 1234}});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
const $element = angular.element('<vn-zone-create></vn-zone-create>');
|
|
||||||
controller = $componentController('vnZoneCreate', {$element, $scope});
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('onSubmit()', () => {
|
|
||||||
it(`should call submit() on the watcher then expect a callback`, () => {
|
|
||||||
jest.spyOn($state, 'go');
|
|
||||||
|
|
||||||
controller.zone = {
|
|
||||||
name: 'Zone One'
|
|
||||||
};
|
|
||||||
|
|
||||||
controller.onSubmit();
|
|
||||||
|
|
||||||
expect(controller.$state.go).toHaveBeenCalledWith('zone.card.location', Object({id: 1234}));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
Traveling days: Días de viaje
|
|
||||||
Closing hour: Hora de cierre
|
|
||||||
Bonus: Bonificación
|
|
|
@ -1,102 +0,0 @@
|
||||||
<div class="vn-w-md">
|
|
||||||
<vn-zone-calendar
|
|
||||||
data="data"
|
|
||||||
on-selection="$ctrl.onSelection($event, $events, $days)">
|
|
||||||
</vn-zone-calendar>
|
|
||||||
</div>
|
|
||||||
<vn-side-menu side="right">
|
|
||||||
<form ng-submit="$ctrl.fetchData()" class="vn-pa-md">
|
|
||||||
<vn-radio
|
|
||||||
label="Pick up"
|
|
||||||
val="pickUp"
|
|
||||||
ng-model="$ctrl.deliveryMethodFk"
|
|
||||||
on-change="$ctrl.agencyModeFk = null"
|
|
||||||
tabindex="-1">
|
|
||||||
</vn-radio>
|
|
||||||
<vn-radio
|
|
||||||
label="Delivery"
|
|
||||||
val="delivery"
|
|
||||||
ng-model="$ctrl.deliveryMethodFk"
|
|
||||||
on-change="$ctrl.agencyModeFk = null"
|
|
||||||
class="vn-mb-sm"
|
|
||||||
tabindex="-1">
|
|
||||||
</vn-radio>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
ng-if="$ctrl.deliveryMethodFk === 'delivery'"
|
|
||||||
vn-focus
|
|
||||||
label="Postcode"
|
|
||||||
ng-model="$ctrl.geoFk"
|
|
||||||
url="Postcodes/location"
|
|
||||||
fields="['code','townFk']"
|
|
||||||
order="code, townFk"
|
|
||||||
value-field="geoFk"
|
|
||||||
show-field="code">
|
|
||||||
<tpl-item>
|
|
||||||
<div>
|
|
||||||
{{code}} {{town.name}}
|
|
||||||
</div>
|
|
||||||
<div class="text-caption text-secondary">
|
|
||||||
{{town.province.name}}, {{town.province.country.name}}
|
|
||||||
</div>
|
|
||||||
</tpl-item>
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="{{$ctrl.deliveryMethodFk == 'delivery' ? 'Agency' : 'Warehouse'}}"
|
|
||||||
ng-model="$ctrl.agencyModeFk"
|
|
||||||
url="AgencyModes/isActive"
|
|
||||||
where="$ctrl.agencyFilter"
|
|
||||||
vn-id="agencymode">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-submit label="Query" class="vn-mt-sm"></vn-submit>
|
|
||||||
</form>
|
|
||||||
</vn-side-menu>
|
|
||||||
|
|
||||||
<!-- Zone Popover -->
|
|
||||||
<vn-popover vn-id="zoneEvents">
|
|
||||||
<div class="zoneEvents">
|
|
||||||
<div class="header vn-pa-sm" translate>Zones</div>
|
|
||||||
<vn-data-viewer
|
|
||||||
data="::$ctrl.zoneClosing"
|
|
||||||
class="vn-w-md vn-mb-xl">
|
|
||||||
<vn-card>
|
|
||||||
<vn-table>
|
|
||||||
<vn-thead>
|
|
||||||
<vn-tr>
|
|
||||||
<vn-th field="id" number>Id</vn-th>
|
|
||||||
<vn-th field="name" expand>Name</vn-th>
|
|
||||||
<vn-th field="agencyModeFk">Agency</vn-th>
|
|
||||||
<vn-th field="hour" shrink>Closing</vn-th>
|
|
||||||
<vn-th field="price" number>Price</vn-th>
|
|
||||||
<vn-th shrink></vn-th>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-thead>
|
|
||||||
<vn-tbody>
|
|
||||||
<vn-tr
|
|
||||||
ng-repeat="zone in $ctrl.zoneClosing"
|
|
||||||
ui-sref="zone.card.summary({id: zone.id})"
|
|
||||||
class="clickable search-result">
|
|
||||||
<vn-td number>{{::zone.id}}</vn-td>
|
|
||||||
<vn-td expand>{{::zone.name}}</vn-td>
|
|
||||||
<vn-td>{{::zone.agencyModeName}}</vn-td>
|
|
||||||
<vn-td shrink>{{::zone.hour | date: 'HH:mm'}}</vn-td>
|
|
||||||
<vn-td number>{{::zone.price | currency: 'EUR':2}}</vn-td>
|
|
||||||
<vn-td shrink>
|
|
||||||
<vn-horizontal class="buttons">
|
|
||||||
<vn-icon-button
|
|
||||||
vn-click-stop="$ctrl.preview(zone)"
|
|
||||||
vn-tooltip="Preview"
|
|
||||||
icon="preview">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-td>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-tbody>
|
|
||||||
</vn-table>
|
|
||||||
</vn-card>
|
|
||||||
</vn-data-viewer>
|
|
||||||
</div>
|
|
||||||
</vn-popover>
|
|
||||||
<vn-popup vn-id="summary">
|
|
||||||
<vn-zone-summary zone="$ctrl.selectedZone"></vn-zone-summary>
|
|
||||||
</vn-popup>
|
|
|
@ -1,95 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
|
||||||
$onInit() {
|
|
||||||
this.setParams();
|
|
||||||
}
|
|
||||||
|
|
||||||
$postLink() {
|
|
||||||
this.deliveryMethodFk = 'delivery';
|
|
||||||
}
|
|
||||||
|
|
||||||
setParams() {
|
|
||||||
const hasParams = this.$params.deliveryMethodFk || this.$params.geoFk || this.$params.agencyModeFk;
|
|
||||||
if (hasParams) {
|
|
||||||
if (this.$params.deliveryMethodFk)
|
|
||||||
this.deliveryMethodFk = this.$params.deliveryMethodFk;
|
|
||||||
|
|
||||||
if (this.$params.geoFk)
|
|
||||||
this.geoFk = this.$params.geoFk;
|
|
||||||
|
|
||||||
if (this.$params.agencyModeFk)
|
|
||||||
this.agencyModeFk = this.$params.agencyModeFk;
|
|
||||||
|
|
||||||
this.fetchData();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchData() {
|
|
||||||
const params = {
|
|
||||||
deliveryMethodFk: this.deliveryMethodFk,
|
|
||||||
geoFk: this.geoFk,
|
|
||||||
agencyModeFk: this.agencyModeFk
|
|
||||||
};
|
|
||||||
this.$.data = null;
|
|
||||||
this.$http.get(`Zones/getEvents`, {params})
|
|
||||||
.then(res => {
|
|
||||||
let data = res.data;
|
|
||||||
this.$.data = data;
|
|
||||||
if (!data.events.length)
|
|
||||||
this.vnApp.showMessage(this.$t('No service for the specified zone'));
|
|
||||||
|
|
||||||
this.$state.go(this.$state.current.name, params);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
get deliveryMethodFk() {
|
|
||||||
return this._deliveryMethodFk;
|
|
||||||
}
|
|
||||||
|
|
||||||
set deliveryMethodFk(value) {
|
|
||||||
this._deliveryMethodFk = value;
|
|
||||||
|
|
||||||
let filter;
|
|
||||||
|
|
||||||
if (value === 'pickUp')
|
|
||||||
filter = {where: {code: 'PICKUP'}};
|
|
||||||
else
|
|
||||||
filter = {where: {code: {inq: ['DELIVERY', 'AGENCY']}}};
|
|
||||||
|
|
||||||
this.$http.get(`DeliveryMethods`, {filter}).then(res => {
|
|
||||||
const deliveryMethods = res.data.map(deliveryMethod => deliveryMethod.id);
|
|
||||||
this.agencyFilter = {deliveryMethodFk: {inq: deliveryMethods}};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onSelection($event, $events, $days) {
|
|
||||||
if (!$events.length) return;
|
|
||||||
|
|
||||||
const day = $days[0];
|
|
||||||
const zoneIds = [];
|
|
||||||
for (let event of $events)
|
|
||||||
zoneIds.push(event.zoneFk);
|
|
||||||
|
|
||||||
const params = {
|
|
||||||
zoneIds: zoneIds,
|
|
||||||
date: day
|
|
||||||
};
|
|
||||||
|
|
||||||
this.$http.post(`Zones/getZoneClosing`, params)
|
|
||||||
.then(res => this.zoneClosing = res.data)
|
|
||||||
.then(() => this.$.zoneEvents.show($event.target));
|
|
||||||
}
|
|
||||||
|
|
||||||
preview(zone) {
|
|
||||||
this.selectedZone = zone;
|
|
||||||
this.$.summary.show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnZoneDeliveryDays', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,126 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
import popover from 'core/mocks/popover';
|
|
||||||
import crudModel from 'core/mocks/crud-model';
|
|
||||||
|
|
||||||
describe('Zone Component vnZoneDeliveryDays', () => {
|
|
||||||
let $httpBackend;
|
|
||||||
let controller;
|
|
||||||
let $element;
|
|
||||||
|
|
||||||
beforeEach(ngModule('zone'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, _$httpBackend_) => {
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
$element = angular.element('<vn-zone-delivery-days></vn-zone-delivery-days');
|
|
||||||
controller = $componentController('vnZoneDeliveryDays', {$element});
|
|
||||||
controller.$.zoneEvents = popover;
|
|
||||||
controller.$.params = {};
|
|
||||||
controller.$.zoneModel = crudModel;
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('deliveryMethodFk() setter', () => {
|
|
||||||
it('should set the deliveryMethodFk property as pickup and then perform a query that sets the filter', () => {
|
|
||||||
$httpBackend.expect('GET', 'DeliveryMethods').respond([{id: 999}]);
|
|
||||||
controller.deliveryMethodFk = 'pickUp';
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.agencyFilter).toEqual({deliveryMethodFk: {inq: [999]}});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('setParams()', () => {
|
|
||||||
it('should do nothing when no params are received', () => {
|
|
||||||
controller.setParams();
|
|
||||||
|
|
||||||
expect(controller.deliveryMethodFk).toBeUndefined();
|
|
||||||
expect(controller.geoFk).toBeUndefined();
|
|
||||||
expect(controller.agencyModeFk).toBeUndefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set the controller properties when the params are provided', () => {
|
|
||||||
controller.$params = {
|
|
||||||
deliveryMethodFk: 3,
|
|
||||||
geoFk: 2,
|
|
||||||
agencyModeFk: 1
|
|
||||||
};
|
|
||||||
controller.setParams();
|
|
||||||
|
|
||||||
expect(controller.deliveryMethodFk).toEqual(controller.$params.deliveryMethodFk);
|
|
||||||
expect(controller.geoFk).toEqual(controller.$params.geoFk);
|
|
||||||
expect(controller.agencyModeFk).toEqual(controller.$params.agencyModeFk);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('fetchData()', () => {
|
|
||||||
it('should make an HTTP GET query and then call the showMessage() method', () => {
|
|
||||||
jest.spyOn(controller.vnApp, 'showMessage');
|
|
||||||
jest.spyOn(controller.$state, 'go');
|
|
||||||
|
|
||||||
controller.agencyModeFk = 1;
|
|
||||||
controller.deliveryMethodFk = 2;
|
|
||||||
controller.geoFk = 3;
|
|
||||||
controller.$state.current.name = 'myState';
|
|
||||||
|
|
||||||
const expectedData = {events: []};
|
|
||||||
|
|
||||||
const url = 'Zones/getEvents?agencyModeFk=1&deliveryMethodFk=2&geoFk=3';
|
|
||||||
|
|
||||||
$httpBackend.when('GET', 'DeliveryMethods').respond([]);
|
|
||||||
$httpBackend.expect('GET', url).respond({events: []});
|
|
||||||
controller.fetchData();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.$.data).toEqual(expectedData);
|
|
||||||
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('No service for the specified zone');
|
|
||||||
expect(controller.$state.go).toHaveBeenCalledWith(
|
|
||||||
controller.$state.current.name,
|
|
||||||
{
|
|
||||||
agencyModeFk: 1,
|
|
||||||
deliveryMethodFk: 2,
|
|
||||||
geoFk: 3
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onSelection()', () => {
|
|
||||||
it('should not call the show popover method if events array is empty', () => {
|
|
||||||
jest.spyOn(controller.$.zoneEvents, 'show');
|
|
||||||
|
|
||||||
const event = new Event('click');
|
|
||||||
const target = document.createElement('div');
|
|
||||||
target.dispatchEvent(event);
|
|
||||||
const events = [];
|
|
||||||
controller.onSelection(event, events);
|
|
||||||
|
|
||||||
expect(controller.$.zoneEvents.show).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call the show() method and call getZoneClosing() with the expected ids', () => {
|
|
||||||
jest.spyOn(controller.$.zoneEvents, 'show');
|
|
||||||
|
|
||||||
const event = new Event('click');
|
|
||||||
const target = document.createElement('div');
|
|
||||||
target.dispatchEvent(event);
|
|
||||||
|
|
||||||
const day = Date.vnNew();
|
|
||||||
const events = [
|
|
||||||
{zoneFk: 1},
|
|
||||||
{zoneFk: 2},
|
|
||||||
{zoneFk: 8}
|
|
||||||
];
|
|
||||||
const params = {
|
|
||||||
zoneIds: [1, 2, 8],
|
|
||||||
date: [day][0]
|
|
||||||
};
|
|
||||||
const response = [{id: 1, hour: ''}];
|
|
||||||
|
|
||||||
$httpBackend.when('POST', 'Zones/getZoneClosing', params).respond({response});
|
|
||||||
controller.onSelection(event, events, [day]);
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.$.zoneEvents.show).toHaveBeenCalledWith(target);
|
|
||||||
expect(controller.zoneClosing.id).toEqual(response.id);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,36 +0,0 @@
|
||||||
@import "variables";
|
|
||||||
|
|
||||||
vn-zone-delivery-days {
|
|
||||||
vn-zone-calendar {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
|
|
||||||
& > vn-calendar {
|
|
||||||
min-width: 264px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
form {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.zoneEvents {
|
|
||||||
width: 700px;
|
|
||||||
max-height: 450px;
|
|
||||||
|
|
||||||
vn-data-viewer {
|
|
||||||
margin-bottom: 0;
|
|
||||||
vn-pagination {
|
|
||||||
padding: 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& > .header {
|
|
||||||
background-color: $color-main;
|
|
||||||
color: white;
|
|
||||||
font-weight: bold;
|
|
||||||
text-align: center
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
<slot-descriptor>
|
|
||||||
<vn-zone-descriptor>
|
|
||||||
</vn-zone-descriptor>
|
|
||||||
</slot-descriptor>
|
|
|
@ -1,9 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import DescriptorPopover from 'salix/components/descriptor-popover';
|
|
||||||
|
|
||||||
class Controller extends DescriptorPopover {}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnZoneDescriptorPopover', {
|
|
||||||
slotTemplate: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,57 +0,0 @@
|
||||||
<vn-descriptor-content
|
|
||||||
module="zone"
|
|
||||||
description="$ctrl.zone.name"
|
|
||||||
summary="$ctrl.$.summary">
|
|
||||||
<slot-menu>
|
|
||||||
<vn-item class="vn-item"
|
|
||||||
ng-click="$ctrl.onDelete()"
|
|
||||||
translate>
|
|
||||||
Delete
|
|
||||||
</vn-item>
|
|
||||||
<vn-item
|
|
||||||
ng-click="clone.show()"
|
|
||||||
name="cloneZone"
|
|
||||||
translate>
|
|
||||||
Clone
|
|
||||||
</vn-item>
|
|
||||||
</slot-menu>
|
|
||||||
<slot-body>
|
|
||||||
<div class="attributes">
|
|
||||||
<vn-label-value
|
|
||||||
label="Agency"
|
|
||||||
value="{{$ctrl.zone.agencyMode.name}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="Closing hour"
|
|
||||||
value="{{$ctrl.zone.hour | date: 'HH:mm'}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="Traveling days"
|
|
||||||
value="{{$ctrl.zone.travelingDays}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="Price"
|
|
||||||
value="{{$ctrl.zone.price | currency: 'EUR': 2}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="Bonus"
|
|
||||||
value="{{$ctrl.zone.bonus | currency: 'EUR': 2}}">
|
|
||||||
</vn-label-value>
|
|
||||||
</div>
|
|
||||||
</slot-body>
|
|
||||||
</vn-descriptor-content>
|
|
||||||
<vn-popup vn-id="summary">
|
|
||||||
<vn-zone-summary zone="$ctrl.zone"></vn-zone-summary>
|
|
||||||
</vn-popup>
|
|
||||||
|
|
||||||
<vn-confirm
|
|
||||||
vn-id="deleteZone"
|
|
||||||
on-accept="$ctrl.deleteZone()"
|
|
||||||
message="This zone will be removed">
|
|
||||||
</vn-confirm>
|
|
||||||
<vn-confirm
|
|
||||||
vn-id="clone"
|
|
||||||
on-accept="$ctrl.onCloneAccept()"
|
|
||||||
question="Do you want to clone this zone?"
|
|
||||||
message="All it's properties will be copied">
|
|
||||||
</vn-confirm>
|
|
|
@ -1,65 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Descriptor from 'salix/components/descriptor';
|
|
||||||
|
|
||||||
class Controller extends Descriptor {
|
|
||||||
get zone() {
|
|
||||||
return this.entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
set zone(value) {
|
|
||||||
this.entity = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
loadData() {
|
|
||||||
const filter = {
|
|
||||||
include: [
|
|
||||||
{
|
|
||||||
relation: 'agencyMode',
|
|
||||||
scope: {
|
|
||||||
fields: ['name'],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
return this.getData(`Zones/${this.id}`, {filter})
|
|
||||||
.then(res => this.entity = res.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
onDelete() {
|
|
||||||
const $t = this.$translate.instant;
|
|
||||||
const today = Date.vnNew();
|
|
||||||
today.setHours(0, 0, 0, 0);
|
|
||||||
const filter = {where: {zoneFk: this.id, shipped: {gte: today}}};
|
|
||||||
this.$http.get(`Tickets`, {filter}).then(res => {
|
|
||||||
const ticketsAmount = res.data.length;
|
|
||||||
if (ticketsAmount) {
|
|
||||||
const params = {ticketsAmount};
|
|
||||||
const question = $t('This zone contains tickets', params, null, null, 'sanitizeParameters');
|
|
||||||
this.$.deleteZone.question = question;
|
|
||||||
this.$.deleteZone.show();
|
|
||||||
} else
|
|
||||||
this.deleteZone();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteZone() {
|
|
||||||
return this.$http.post(`Zones/${this.id}/deleteZone`).then(() => {
|
|
||||||
this.$state.go('zone.index');
|
|
||||||
this.vnApp.showSuccess(this.$t('Zone deleted'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onCloneAccept() {
|
|
||||||
return this.$http.post(`Zones/${this.id}/clone`).
|
|
||||||
then(res => this.$state.go('zone.card.basicData', {id: res.data.id}));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnZoneDescriptor', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
zone: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,74 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
|
|
||||||
describe('Zone descriptor', () => {
|
|
||||||
let $httpBackend;
|
|
||||||
let controller;
|
|
||||||
let $element;
|
|
||||||
|
|
||||||
beforeEach(ngModule('zone'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, _$httpBackend_) => {
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
$element = angular.element('<vn-zone-descriptor></vn-zone-descriptor');
|
|
||||||
controller = $componentController('vnZoneDescriptor', {$element});
|
|
||||||
controller.zone = {id: 1};
|
|
||||||
controller.id = 1;
|
|
||||||
controller.$.deleteZone = {
|
|
||||||
hide: () => {},
|
|
||||||
show: () => {}
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('onDelete()', () => {
|
|
||||||
it('should make an HTTP POST query and then call the deleteZone show() method', () => {
|
|
||||||
jest.spyOn(controller.$.deleteZone, 'show');
|
|
||||||
|
|
||||||
const expectedData = [{id: 16}];
|
|
||||||
$httpBackend.when('GET', 'Tickets').respond(expectedData);
|
|
||||||
controller.onDelete();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.$.deleteZone.show).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should make an HTTP POST query and then call the deleteZone() method', () => {
|
|
||||||
jest.spyOn(controller, 'deleteZone').mockReturnThis();
|
|
||||||
|
|
||||||
const expectedData = [];
|
|
||||||
$httpBackend.when('GET', 'Tickets').respond(expectedData);
|
|
||||||
controller.onDelete();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.deleteZone).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('deleteZone()', () => {
|
|
||||||
it('should make an HTTP POST query and then call the showMessage() method', () => {
|
|
||||||
jest.spyOn(controller.$state, 'go').mockReturnThis();
|
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
|
||||||
|
|
||||||
const stateName = 'zone.index';
|
|
||||||
$httpBackend.when('POST', 'Zones/1/deleteZone').respond(200);
|
|
||||||
controller.deleteZone();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.$state.go).toHaveBeenCalledWith(stateName);
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Zone deleted');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onCloneAccept()', () => {
|
|
||||||
it('should make an HTTP POST query and then call the state go() method', () => {
|
|
||||||
jest.spyOn(controller.$state, 'go').mockReturnThis();
|
|
||||||
|
|
||||||
const stateName = 'zone.card.basicData';
|
|
||||||
const expectedData = {id: 1};
|
|
||||||
$httpBackend.when('POST', 'Zones/1/clone').respond(expectedData);
|
|
||||||
controller.onCloneAccept();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.$state.go).toHaveBeenCalledWith(stateName, expectedData);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,4 +0,0 @@
|
||||||
This zone contains tickets: Esta zona contiene {{ticketsAmount}} tickets por servir. ¿Seguro que quieres eliminar esta zona?
|
|
||||||
Do you want to clone this zone?: ¿Quieres clonar esta zona?
|
|
||||||
All it's properties will be copied: Todas sus propiedades serán copiadas
|
|
||||||
Zone deleted: Zona eliminada
|
|
|
@ -1,277 +0,0 @@
|
||||||
<vn-zone-calendar
|
|
||||||
id="calendar"
|
|
||||||
vn-id="calendar"
|
|
||||||
data="data"
|
|
||||||
on-selection="$ctrl.onSelection($days, $type, $weekday, $events, $exclusions, $geoExclusions)"
|
|
||||||
on-step="$ctrl.refresh()"
|
|
||||||
class="vn-w-md">
|
|
||||||
</vn-zone-calendar>
|
|
||||||
<vn-side-menu side="right">
|
|
||||||
<div class="vn-pa-md">
|
|
||||||
<h6
|
|
||||||
class="text-secondary"
|
|
||||||
style="font-weight: normal;"
|
|
||||||
translate>
|
|
||||||
Edit mode
|
|
||||||
</h6>
|
|
||||||
<vn-vertical>
|
|
||||||
<vn-radio
|
|
||||||
label="Include"
|
|
||||||
val="include"
|
|
||||||
ng-model="$ctrl.editMode">
|
|
||||||
</vn-radio>
|
|
||||||
<vn-radio
|
|
||||||
label="Exclude"
|
|
||||||
val="exclude"
|
|
||||||
ng-model="$ctrl.editMode">
|
|
||||||
</vn-radio>
|
|
||||||
</vn-vertical>
|
|
||||||
</div>
|
|
||||||
<h6
|
|
||||||
class="text-secondary vn-px-md"
|
|
||||||
style="font-weight: normal;"
|
|
||||||
translate>
|
|
||||||
Events
|
|
||||||
</h6>
|
|
||||||
<vn-data-viewer
|
|
||||||
data="data.events"
|
|
||||||
is-loading="!data.events">
|
|
||||||
<div class="vn-list separated">
|
|
||||||
<a
|
|
||||||
ng-repeat="row in data.events"
|
|
||||||
translate-attr="{title: 'Edit'}"
|
|
||||||
ng-click="$ctrl.onEditClick(row, $event)"
|
|
||||||
class="vn-item">
|
|
||||||
<vn-item-section>
|
|
||||||
<div
|
|
||||||
ng-if="::row.type == 'day'"
|
|
||||||
class="vn-mb-sm">
|
|
||||||
{{::row.dated | date:'dd/MM/yy'}}
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
ng-if="::row.type != 'day'"
|
|
||||||
class="vn-mb-sm ellipsize">
|
|
||||||
<span ng-if="row.weekDays">
|
|
||||||
{{::$ctrl.formatWdays(row.weekDays)}}
|
|
||||||
</span>
|
|
||||||
<span ng-if="row.type == 'range'">
|
|
||||||
({{::row.started | date:'dd/MM/yy'}} - {{::row.ended | date:'dd/MM/yy'}})
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<vn-label-value
|
|
||||||
label="Closing"
|
|
||||||
value="{{::row.hour | date:'HH:mm'}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="Traveling days"
|
|
||||||
value="{{::row.travelingDays}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="Price"
|
|
||||||
value="{{::row.price | currency:'EUR':2}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="Bonus"
|
|
||||||
value="{{::row.bonus | currency:'EUR':2}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value
|
|
||||||
label="Max m³"
|
|
||||||
value="{{::row.m3Max}}">
|
|
||||||
</vn-label-value>
|
|
||||||
</vn-item-section>
|
|
||||||
<vn-item-section side>
|
|
||||||
<vn-icon-button
|
|
||||||
icon="delete"
|
|
||||||
translate-attr="{title: 'Delete'}"
|
|
||||||
ng-click="$ctrl.onDeleteClick(row.id, $event)">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-item-section>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</vn-data-viewer>
|
|
||||||
</vn-side-menu>
|
|
||||||
<vn-float-button
|
|
||||||
ng-click="$ctrl.createInclusion('weekday')"
|
|
||||||
icon="add"
|
|
||||||
vn-tooltip="Add event"
|
|
||||||
vn-bind="+"
|
|
||||||
fixed-bottom-right>
|
|
||||||
</vn-float-button>
|
|
||||||
<vn-dialog
|
|
||||||
vn-id="includeDialog"
|
|
||||||
on-response="$ctrl.onIncludeResponse($response)"
|
|
||||||
message="{{$ctrl.isNew ? 'Add event' : 'Edit event'}}">
|
|
||||||
<tpl-body>
|
|
||||||
<vn-vertical>
|
|
||||||
<vn-vertical class="vn-pb-md">
|
|
||||||
<vn-radio
|
|
||||||
ng-model="$ctrl.selected.type"
|
|
||||||
label="One day"
|
|
||||||
val="day">
|
|
||||||
</vn-radio>
|
|
||||||
<vn-radio
|
|
||||||
ng-model="$ctrl.selected.type"
|
|
||||||
label="Indefinitely"
|
|
||||||
val="indefinitely">
|
|
||||||
</vn-radio>
|
|
||||||
<vn-radio
|
|
||||||
ng-model="$ctrl.selected.type"
|
|
||||||
label="Range of dates"
|
|
||||||
val="range">
|
|
||||||
</vn-radio>
|
|
||||||
</vn-vertical>
|
|
||||||
<vn-wday-picker
|
|
||||||
ng-if="$ctrl.selected.type != 'day'"
|
|
||||||
ng-model="$ctrl.selected.wdays"
|
|
||||||
class="vn-mt-sm vn-mb-md">
|
|
||||||
</vn-wday-picker>
|
|
||||||
<vn-date-picker
|
|
||||||
ng-if="$ctrl.selected.type == 'day'"
|
|
||||||
label="Day"
|
|
||||||
ng-model="$ctrl.selected.dated">
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-horizontal
|
|
||||||
ng-if="$ctrl.selected.type == 'range'">
|
|
||||||
<vn-date-picker
|
|
||||||
label="From"
|
|
||||||
ng-model="$ctrl.selected.started">
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-date-picker
|
|
||||||
label="To"
|
|
||||||
ng-model="$ctrl.selected.ended">
|
|
||||||
</vn-date-picker>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-input-time
|
|
||||||
label="Closing"
|
|
||||||
ng-model="$ctrl.selected.hour">
|
|
||||||
</vn-input-time>
|
|
||||||
<vn-input-number
|
|
||||||
label="Traveling days"
|
|
||||||
ng-model="$ctrl.selected.travelingDays"
|
|
||||||
min="0"
|
|
||||||
step="1">
|
|
||||||
</vn-input-number>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-input-number
|
|
||||||
label="Price"
|
|
||||||
ng-model="$ctrl.selected.price"
|
|
||||||
min="0"
|
|
||||||
step="0.01">
|
|
||||||
</vn-input-number>
|
|
||||||
<vn-input-number
|
|
||||||
label="Bonus"
|
|
||||||
ng-model="$ctrl.selected.bonus"
|
|
||||||
min="0"
|
|
||||||
step="0.01">
|
|
||||||
</vn-input-number>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-input-number
|
|
||||||
label="Max m³"
|
|
||||||
ng-model="$ctrl.selected.m3Max"
|
|
||||||
min="0"
|
|
||||||
step="0.01">
|
|
||||||
</vn-input-number>
|
|
||||||
</vn-vertical>
|
|
||||||
</tpl-body>
|
|
||||||
<tpl-buttons>
|
|
||||||
<input
|
|
||||||
type="button"
|
|
||||||
response="cancel"
|
|
||||||
translate-attr="{value: 'Cancel'}">
|
|
||||||
</input>
|
|
||||||
<input
|
|
||||||
type="button"
|
|
||||||
ng-if="!$ctrl.isNew"
|
|
||||||
response="delete"
|
|
||||||
translate-attr="{value: 'Delete'}">
|
|
||||||
</input>
|
|
||||||
<button response="accept">
|
|
||||||
<span ng-if="$ctrl.isNew" translate>Add</span>
|
|
||||||
<span ng-if="!$ctrl.isNew" translate>Save</span>
|
|
||||||
</button>
|
|
||||||
</tpl-buttons>
|
|
||||||
</vn-dialog>
|
|
||||||
<vn-confirm
|
|
||||||
vn-id="confirm"
|
|
||||||
message="This item will be deleted"
|
|
||||||
question="Are you sure you want to continue?">
|
|
||||||
</vn-confirm>
|
|
||||||
<vn-dialog
|
|
||||||
vn-id="excludeDialog"
|
|
||||||
on-response="$ctrl.onExcludeResponse($response)"
|
|
||||||
message="{{$ctrl.isNew ? 'Add exclusion' : 'Edit exclusion'}}"
|
|
||||||
on-open="$ctrl.onSearch($params)"
|
|
||||||
on-close="$ctrl.resetExclusions()">
|
|
||||||
<tpl-body>
|
|
||||||
<vn-date-picker
|
|
||||||
label="Day"
|
|
||||||
ng-model="$ctrl.excludeSelected.dated">
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-vertical class="width">
|
|
||||||
<vn-vertical class="vn-pb-md">
|
|
||||||
<vn-radio
|
|
||||||
ng-model="$ctrl.excludeSelected.type"
|
|
||||||
label="All"
|
|
||||||
on-change="$ctrl.test()"
|
|
||||||
val="all">
|
|
||||||
</vn-radio>
|
|
||||||
<vn-radio
|
|
||||||
ng-model="$ctrl.excludeSelected.type"
|
|
||||||
label="Specific locations"
|
|
||||||
on-change="$ctrl.onSearch($params)"
|
|
||||||
val="specificLocations">
|
|
||||||
</vn-radio>
|
|
||||||
</vn-vertical>
|
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="Zones/{{$ctrl.$params.id}}/getLeaves"
|
|
||||||
filter="$ctrl.filter">
|
|
||||||
</vn-crud-model>
|
|
||||||
<div ng-if="$ctrl.excludeSelected.type == 'specificLocations'">
|
|
||||||
<vn-textfield
|
|
||||||
label="Search"
|
|
||||||
ng-keydown="$ctrl.onKeyDown($event)"
|
|
||||||
ng-model="$ctrl.excludeSearch">
|
|
||||||
<prepend>
|
|
||||||
<vn-icon icon="search"></vn-icon>
|
|
||||||
</prepend>
|
|
||||||
</vn-textfield>
|
|
||||||
<div class="treeview">
|
|
||||||
<vn-treeview
|
|
||||||
vn-id="treeview"
|
|
||||||
root-label="Locations where it is not distributed"
|
|
||||||
fetch-func="$ctrl.onFetch($item)"
|
|
||||||
sort-func="$ctrl.onSort($a, $b)">
|
|
||||||
<vn-check
|
|
||||||
ng-model="item.checked"
|
|
||||||
ng-click="$event.preventDefault()"
|
|
||||||
on-change="$ctrl.onItemCheck(item.id, value)"
|
|
||||||
label="{{::item.name}}">
|
|
||||||
</vn-check>
|
|
||||||
</vn-treeview>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</vn-vertical>
|
|
||||||
</tpl-body>
|
|
||||||
<tpl-buttons>
|
|
||||||
<input
|
|
||||||
type="button"
|
|
||||||
response="cancel"
|
|
||||||
translate-attr="{value: 'Cancel'}"
|
|
||||||
tabindex="0">
|
|
||||||
</input>
|
|
||||||
<input
|
|
||||||
type="button"
|
|
||||||
ng-if="!$ctrl.isNew"
|
|
||||||
response="delete"
|
|
||||||
translate-attr="{value: 'Delete'}"
|
|
||||||
tabindex="0">
|
|
||||||
</input>
|
|
||||||
<button response="accept">
|
|
||||||
<span ng-if="$ctrl.isNew" translate>Add</span>
|
|
||||||
<span ng-if="!$ctrl.isNew" translate>Save</span>
|
|
||||||
</button>
|
|
||||||
</tpl-buttons>
|
|
||||||
</vn-dialog>
|
|
|
@ -1,316 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
|
||||||
constructor($element, $, vnWeekDays) {
|
|
||||||
super($element, $);
|
|
||||||
this.vnWeekDays = vnWeekDays;
|
|
||||||
this.editMode = 'include';
|
|
||||||
}
|
|
||||||
|
|
||||||
$onInit() {
|
|
||||||
this.refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
get path() {
|
|
||||||
return `Zones/${this.$params.id}/events`;
|
|
||||||
}
|
|
||||||
|
|
||||||
get exclusionsPath() {
|
|
||||||
return `Zones/${this.$params.id}/exclusions`;
|
|
||||||
}
|
|
||||||
|
|
||||||
get checked() {
|
|
||||||
const geos = this.$.model.data || [];
|
|
||||||
const checkedLines = [];
|
|
||||||
for (let geo of geos) {
|
|
||||||
if (geo.checked)
|
|
||||||
checkedLines.push(geo);
|
|
||||||
}
|
|
||||||
return checkedLines;
|
|
||||||
}
|
|
||||||
|
|
||||||
refresh() {
|
|
||||||
this.$.data = null;
|
|
||||||
this.$.$applyAsync(() => {
|
|
||||||
const params = {
|
|
||||||
zoneFk: this.$params.id,
|
|
||||||
started: this.$.calendar.firstDay,
|
|
||||||
ended: this.$.calendar.lastDay
|
|
||||||
};
|
|
||||||
|
|
||||||
this.$http.get(`Zones/getEventsFiltered`, {params}).then(res => {
|
|
||||||
const data = res.data;
|
|
||||||
this.$.data = data;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
formatWdays(weekDays) {
|
|
||||||
if (!weekDays) return;
|
|
||||||
|
|
||||||
let abrWdays = weekDays
|
|
||||||
.split(',')
|
|
||||||
.map(wday => this.vnWeekDays.map[wday].localeAbr);
|
|
||||||
|
|
||||||
return abrWdays.length < 7
|
|
||||||
? abrWdays.join(', ')
|
|
||||||
: this.$t('Everyday');
|
|
||||||
}
|
|
||||||
|
|
||||||
onSelection(days, type, weekday, events, exclusions, exclusionGeos) {
|
|
||||||
if (this.editMode == 'include') {
|
|
||||||
if (events.length)
|
|
||||||
return this.editInclusion(events[0]);
|
|
||||||
return this.createInclusion(type, days, weekday);
|
|
||||||
} else if (this.editMode == 'exclude') {
|
|
||||||
if (exclusions.length || exclusionGeos.length)
|
|
||||||
return this.editExclusion(exclusions[0] || {}, exclusionGeos);
|
|
||||||
return this.createExclusion(days);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
editExclusion(exclusion, exclusionGeos) {
|
|
||||||
this.isNew = false;
|
|
||||||
this.excludeSelected = angular.copy(exclusion);
|
|
||||||
this.excludeSelected.type = exclusionGeos.length ?
|
|
||||||
'specificLocations' : 'all';
|
|
||||||
|
|
||||||
this.exclusionGeos = new Set();
|
|
||||||
if (exclusionGeos.length) {
|
|
||||||
this.excludeSelected.id = exclusionGeos[0].zoneExclusionFk;
|
|
||||||
exclusionGeos.forEach(x => this.exclusionGeos.add(x.geoFk));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$.excludeDialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
createExclusion(days) {
|
|
||||||
this.isNew = true;
|
|
||||||
this.excludeSelected = {
|
|
||||||
type: 'all',
|
|
||||||
dated: days[0]
|
|
||||||
};
|
|
||||||
this.exclusionGeos = new Set();
|
|
||||||
this.$.excludeDialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
onEditClick(row, event) {
|
|
||||||
if (event.defaultPrevented) return;
|
|
||||||
this.editInclusion(row);
|
|
||||||
}
|
|
||||||
|
|
||||||
editInclusion(row) {
|
|
||||||
this.isNew = false;
|
|
||||||
this.selected = angular.copy(row);
|
|
||||||
this.selected.wdays = this.vnWeekDays.fromSet(row.weekDays);
|
|
||||||
this.$.includeDialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
createInclusion(type, days, weekday) {
|
|
||||||
this.isNew = true;
|
|
||||||
|
|
||||||
if (type == 'weekday') {
|
|
||||||
let wdays = [];
|
|
||||||
if (weekday) wdays[weekday] = true;
|
|
||||||
|
|
||||||
this.selected = {
|
|
||||||
type: 'indefinitely',
|
|
||||||
wdays
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
this.selected = {
|
|
||||||
type: 'day',
|
|
||||||
dated: days[0]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$.includeDialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
onIncludeResponse(response) {
|
|
||||||
switch (response) {
|
|
||||||
case 'accept': {
|
|
||||||
let selected = this.selected;
|
|
||||||
let type = selected.type;
|
|
||||||
|
|
||||||
selected.weekDays = this.vnWeekDays.toSet(selected.wdays);
|
|
||||||
|
|
||||||
if (type == 'day')
|
|
||||||
selected.weekDays = '';
|
|
||||||
else
|
|
||||||
selected.dated = null;
|
|
||||||
|
|
||||||
if (type != 'range') {
|
|
||||||
selected.started = null;
|
|
||||||
selected.ended = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let req;
|
|
||||||
|
|
||||||
if (this.isNew)
|
|
||||||
req = this.$http.post(this.path, selected);
|
|
||||||
else
|
|
||||||
req = this.$http.put(`${this.path}/${selected.id}`, selected);
|
|
||||||
|
|
||||||
return req.then(() => {
|
|
||||||
this.selected = null;
|
|
||||||
this.isNew = null;
|
|
||||||
this.refresh();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
case 'delete':
|
|
||||||
return this.onDelete(this.selected.id)
|
|
||||||
.then(response => response == 'accept');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onExcludeResponse(response) {
|
|
||||||
const type = this.excludeSelected.type;
|
|
||||||
switch (response) {
|
|
||||||
case 'accept': {
|
|
||||||
if (type == 'all')
|
|
||||||
return this.exclusionCreate();
|
|
||||||
return this.exclusionGeoCreate();
|
|
||||||
}
|
|
||||||
case 'delete':
|
|
||||||
return this.exclusionDelete(this.excludeSelected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onDeleteClick(id, event) {
|
|
||||||
if (event.defaultPrevented) return;
|
|
||||||
event.preventDefault();
|
|
||||||
this.onDelete(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
onDelete(id) {
|
|
||||||
return this.$.confirm.show(
|
|
||||||
response => this.onDeleteResponse(response, id));
|
|
||||||
}
|
|
||||||
|
|
||||||
onDeleteResponse(response, id) {
|
|
||||||
if (response != 'accept' || !id) return;
|
|
||||||
return this.$http.delete(`${this.path}/${id}`)
|
|
||||||
.then(() => this.refresh());
|
|
||||||
}
|
|
||||||
|
|
||||||
exclusionCreate() {
|
|
||||||
const excludeSelected = this.excludeSelected;
|
|
||||||
const dated = excludeSelected.dated;
|
|
||||||
let req;
|
|
||||||
|
|
||||||
if (this.isNew)
|
|
||||||
req = this.$http.post(this.exclusionsPath, [{dated}]);
|
|
||||||
if (!this.isNew)
|
|
||||||
req = this.$http.put(`${this.exclusionsPath}/${excludeSelected.id}`, {dated});
|
|
||||||
|
|
||||||
return req.then(() => {
|
|
||||||
this.refresh();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
exclusionGeoCreate() {
|
|
||||||
const excludeSelected = this.excludeSelected;
|
|
||||||
let req;
|
|
||||||
const geoIds = [];
|
|
||||||
this.exclusionGeos.forEach(id => geoIds.push(id));
|
|
||||||
|
|
||||||
if (this.isNew) {
|
|
||||||
const params = {
|
|
||||||
zoneFk: parseInt(this.$params.id),
|
|
||||||
date: excludeSelected.dated,
|
|
||||||
geoIds
|
|
||||||
};
|
|
||||||
req = this.$http.post(`Zones/exclusionGeo`, params);
|
|
||||||
} else {
|
|
||||||
const params = {
|
|
||||||
zoneExclusionFk: this.excludeSelected.id,
|
|
||||||
geoIds
|
|
||||||
};
|
|
||||||
req = this.$http.post(`Zones/updateExclusionGeo`, params);
|
|
||||||
}
|
|
||||||
return req.then(() => this.refresh());
|
|
||||||
}
|
|
||||||
|
|
||||||
exclusionDelete(exclusion) {
|
|
||||||
const path = `${this.exclusionsPath}/${exclusion.id}`;
|
|
||||||
return this.$http.delete(path)
|
|
||||||
.then(() => this.refresh());
|
|
||||||
}
|
|
||||||
|
|
||||||
set excludeSearch(value) {
|
|
||||||
this._excludeSearch = value;
|
|
||||||
if (!value) this.onSearch();
|
|
||||||
}
|
|
||||||
|
|
||||||
get excludeSearch() {
|
|
||||||
return this._excludeSearch;
|
|
||||||
}
|
|
||||||
|
|
||||||
onKeyDown(event) {
|
|
||||||
if (event.key == 'Enter') {
|
|
||||||
event.preventDefault();
|
|
||||||
this.onSearch();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onSearch() {
|
|
||||||
const params = {search: this._excludeSearch};
|
|
||||||
if (this.excludeSelected.type == 'specificLocations') {
|
|
||||||
this.$.model.applyFilter({}, params).then(() => {
|
|
||||||
const data = this.$.model.data;
|
|
||||||
this.getChecked(data);
|
|
||||||
this.$.treeview.data = data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onFetch(item) {
|
|
||||||
const params = item ? {parentId: item.id} : null;
|
|
||||||
return this.$.model.applyFilter({}, params).then(() => {
|
|
||||||
const data = this.$.model.data;
|
|
||||||
this.getChecked(data);
|
|
||||||
return data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onSort(a, b) {
|
|
||||||
if (b.selected !== a.selected) {
|
|
||||||
if (a.selected == null)
|
|
||||||
return 1;
|
|
||||||
if (b.selected == null)
|
|
||||||
return -1;
|
|
||||||
return b.selected - a.selected;
|
|
||||||
}
|
|
||||||
|
|
||||||
return a.name.localeCompare(b.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
getChecked(data) {
|
|
||||||
for (let geo of data) {
|
|
||||||
geo.checked = this.exclusionGeos.has(geo.id);
|
|
||||||
if (geo.childs) this.getChecked(geo.childs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onItemCheck(geoId, checked) {
|
|
||||||
if (checked)
|
|
||||||
this.exclusionGeos.add(geoId);
|
|
||||||
else
|
|
||||||
this.exclusionGeos.delete(geoId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Controller.$inject = ['$element', '$scope', 'vnWeekDays'];
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnZoneEvents', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
zone: '<'
|
|
||||||
},
|
|
||||||
require: {
|
|
||||||
card: '^vnZoneCard'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,340 +0,0 @@
|
||||||
import './index';
|
|
||||||
import crudModel from 'core/mocks/crud-model';
|
|
||||||
|
|
||||||
describe('component vnZoneEvents', () => {
|
|
||||||
let $scope;
|
|
||||||
let controller;
|
|
||||||
let $httpBackend;
|
|
||||||
|
|
||||||
beforeEach(ngModule('zone'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => {
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
$scope = $rootScope.$new();
|
|
||||||
const $element = angular.element(`<vn-zone-events></vn-zone-events>`);
|
|
||||||
controller = $componentController('vnZoneEvents', {$element, $scope});
|
|
||||||
controller.$params = {id: 1};
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('refresh()', () => {
|
|
||||||
it('should set the zone and then call both getSummary() and getWarehouses()', () => {
|
|
||||||
const date = '2021-10-01';
|
|
||||||
|
|
||||||
controller.$params.id = 999;
|
|
||||||
controller.$.calendar = {
|
|
||||||
firstDay: date,
|
|
||||||
lastDay: date
|
|
||||||
};
|
|
||||||
|
|
||||||
const params = {
|
|
||||||
zoneFk: controller.$params.id,
|
|
||||||
started: date,
|
|
||||||
ended: date
|
|
||||||
};
|
|
||||||
|
|
||||||
const query = `Zones/getEventsFiltered?ended=${date}&started=${date}&zoneFk=${params.zoneFk}`;
|
|
||||||
const response = {
|
|
||||||
events: 'myEvents',
|
|
||||||
exclusions: 'myExclusions',
|
|
||||||
geoExclusions: 'myGeoExclusions',
|
|
||||||
};
|
|
||||||
$httpBackend.whenGET(query).respond(response);
|
|
||||||
controller.refresh();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
const data = controller.$.data;
|
|
||||||
|
|
||||||
expect(data.events).toBeDefined();
|
|
||||||
expect(data.exclusions).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onSelection()', () => {
|
|
||||||
it('should call the editInclusion() method', () => {
|
|
||||||
jest.spyOn(controller, 'editInclusion').mockReturnThis();
|
|
||||||
|
|
||||||
const weekday = {};
|
|
||||||
const days = [];
|
|
||||||
const type = 'EventType';
|
|
||||||
const events = [{name: 'Event'}];
|
|
||||||
const exclusions = [];
|
|
||||||
const exclusionsGeo = [];
|
|
||||||
controller.editMode = 'include';
|
|
||||||
controller.onSelection(days, type, weekday, events, exclusions, exclusionsGeo);
|
|
||||||
|
|
||||||
expect(controller.editInclusion).toHaveBeenCalledWith({name: 'Event'});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call the createInclusion() method', () => {
|
|
||||||
jest.spyOn(controller, 'createInclusion').mockReturnThis();
|
|
||||||
|
|
||||||
const weekday = {dated: Date.vnNew()};
|
|
||||||
const days = [weekday];
|
|
||||||
const type = 'EventType';
|
|
||||||
const events = [];
|
|
||||||
const exclusions = [];
|
|
||||||
const exclusionsGeo = [];
|
|
||||||
controller.editMode = 'include';
|
|
||||||
controller.onSelection(days, type, weekday, events, exclusions, exclusionsGeo);
|
|
||||||
|
|
||||||
expect(controller.createInclusion).toHaveBeenCalledWith(type, days, weekday);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call the editExclusion() method with exclusions', () => {
|
|
||||||
jest.spyOn(controller, 'editExclusion').mockReturnThis();
|
|
||||||
|
|
||||||
const weekday = {};
|
|
||||||
const days = [];
|
|
||||||
const type = 'EventType';
|
|
||||||
const events = [];
|
|
||||||
const exclusions = [{name: 'Exclusion'}];
|
|
||||||
const exclusionsGeo = [];
|
|
||||||
controller.editMode = 'exclude';
|
|
||||||
controller.onSelection(days, type, weekday, events, exclusions, exclusionsGeo);
|
|
||||||
|
|
||||||
expect(controller.editExclusion).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call the editExclusion() method with exclusionsGeo', () => {
|
|
||||||
jest.spyOn(controller, 'editExclusion').mockReturnThis();
|
|
||||||
|
|
||||||
const weekday = {};
|
|
||||||
const days = [];
|
|
||||||
const type = 'EventType';
|
|
||||||
const events = [];
|
|
||||||
const exclusions = [];
|
|
||||||
const exclusionsGeo = [{name: 'GeoExclusion'}];
|
|
||||||
controller.editMode = 'exclude';
|
|
||||||
controller.onSelection(days, type, weekday, events, exclusions, exclusionsGeo);
|
|
||||||
|
|
||||||
expect(controller.editExclusion).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call the createExclusion() method', () => {
|
|
||||||
jest.spyOn(controller, 'createExclusion').mockReturnThis();
|
|
||||||
|
|
||||||
const weekday = {};
|
|
||||||
const days = [{dated: Date.vnNew()}];
|
|
||||||
const type = 'EventType';
|
|
||||||
const events = [];
|
|
||||||
const exclusions = [];
|
|
||||||
const exclusionsGeo = [];
|
|
||||||
controller.editMode = 'exclude';
|
|
||||||
controller.onSelection(days, type, weekday, events, exclusions, exclusionsGeo);
|
|
||||||
|
|
||||||
expect(controller.createExclusion).toHaveBeenCalledWith(days);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('editExclusion()', () => {
|
|
||||||
it('shoud set the excludeSelected.type = "specificLocations" and then call the excludeDialog show() method', () => {
|
|
||||||
controller.$.excludeDialog = {show: jest.fn()};
|
|
||||||
|
|
||||||
const exclusionGeos = [{id: 1}];
|
|
||||||
const exclusions = [];
|
|
||||||
|
|
||||||
controller.editExclusion(exclusions, exclusionGeos);
|
|
||||||
|
|
||||||
expect(controller.excludeSelected.type).toEqual('specificLocations');
|
|
||||||
expect(controller.$.excludeDialog.show).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('shoud set the excludeSelected.type = "all" and then call the excludeDialog show() method', () => {
|
|
||||||
controller.$.excludeDialog = {show: jest.fn()};
|
|
||||||
|
|
||||||
const exclusionGeos = [];
|
|
||||||
const exclusions = [{id: 1}];
|
|
||||||
|
|
||||||
controller.editExclusion(exclusions, exclusionGeos);
|
|
||||||
|
|
||||||
expect(controller.excludeSelected.type).toEqual('all');
|
|
||||||
expect(controller.$.excludeDialog.show).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('createExclusion()', () => {
|
|
||||||
it('shoud set the excludeSelected property and then call the excludeDialog show() method', () => {
|
|
||||||
controller.$.excludeDialog = {show: jest.fn()};
|
|
||||||
|
|
||||||
const days = [Date.vnNew()];
|
|
||||||
controller.createExclusion(days);
|
|
||||||
|
|
||||||
expect(controller.excludeSelected).toBeDefined();
|
|
||||||
expect(controller.isNew).toBeTruthy();
|
|
||||||
expect(controller.$.excludeDialog.show).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('createInclusion()', () => {
|
|
||||||
it('shoud set the selected property and then call the includeDialog show() method', () => {
|
|
||||||
controller.$.includeDialog = {show: jest.fn()};
|
|
||||||
|
|
||||||
const type = 'weekday';
|
|
||||||
const days = [Date.vnNew()];
|
|
||||||
const weekday = 1;
|
|
||||||
controller.createInclusion(type, days, weekday);
|
|
||||||
|
|
||||||
const selection = controller.selected;
|
|
||||||
const firstWeekday = selection.wdays[weekday];
|
|
||||||
|
|
||||||
expect(selection.type).toEqual('indefinitely');
|
|
||||||
expect(firstWeekday).toBeTruthy();
|
|
||||||
expect(controller.isNew).toBeTruthy();
|
|
||||||
expect(controller.$.includeDialog.show).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('shoud set the selected property with the first day and then call the includeDialog show() method', () => {
|
|
||||||
controller.$.includeDialog = {show: jest.fn()};
|
|
||||||
|
|
||||||
const type = 'nonListedType';
|
|
||||||
const days = [Date.vnNew()];
|
|
||||||
const weekday = 1;
|
|
||||||
controller.createInclusion(type, days, weekday);
|
|
||||||
|
|
||||||
const selection = controller.selected;
|
|
||||||
|
|
||||||
expect(selection.type).toEqual('day');
|
|
||||||
expect(selection.dated).toEqual(days[0]);
|
|
||||||
expect(controller.isNew).toBeTruthy();
|
|
||||||
expect(controller.$.includeDialog.show).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onIncludeResponse()', () => {
|
|
||||||
it('shoud call the onDelete() method', () => {
|
|
||||||
jest.spyOn(controller, 'onDelete').mockReturnValue(
|
|
||||||
new Promise(accept => accept())
|
|
||||||
);
|
|
||||||
|
|
||||||
controller.selected = {id: 1};
|
|
||||||
controller.onIncludeResponse('delete');
|
|
||||||
|
|
||||||
expect(controller.onDelete).toHaveBeenCalledWith(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('shoud make an HTTP POST query to create a new one and then call the refresh() method', () => {
|
|
||||||
jest.spyOn(controller, 'refresh').mockReturnThis();
|
|
||||||
|
|
||||||
controller.selected = {id: 1};
|
|
||||||
controller.isNew = true;
|
|
||||||
|
|
||||||
$httpBackend.when('POST', `Zones/1/events`).respond(200);
|
|
||||||
controller.onIncludeResponse('accept');
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.refresh).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('shoud make an HTTP PUT query and then call the refresh() method', () => {
|
|
||||||
jest.spyOn(controller, 'refresh').mockReturnThis();
|
|
||||||
|
|
||||||
controller.selected = {id: 1};
|
|
||||||
controller.isNew = false;
|
|
||||||
|
|
||||||
const eventId = 1;
|
|
||||||
$httpBackend.when('PUT', `Zones/1/events/${eventId}`).respond(200);
|
|
||||||
controller.onIncludeResponse('accept');
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.refresh).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onExcludeResponse()', () => {
|
|
||||||
it('should call the exclusionCreate() method', () => {
|
|
||||||
jest.spyOn(controller, 'exclusionCreate').mockReturnThis();
|
|
||||||
|
|
||||||
controller.excludeSelected = {type: 'all'};
|
|
||||||
controller.onExcludeResponse('accept');
|
|
||||||
|
|
||||||
expect(controller.exclusionCreate).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call the exclusionGeoCreate() method', () => {
|
|
||||||
jest.spyOn(controller, 'exclusionGeoCreate').mockReturnThis();
|
|
||||||
|
|
||||||
controller.excludeSelected = {type: 'specificLocations'};
|
|
||||||
controller.onExcludeResponse('accept');
|
|
||||||
|
|
||||||
expect(controller.exclusionGeoCreate).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should call the exclusionDelete() method', () => {
|
|
||||||
jest.spyOn(controller, 'exclusionDelete').mockReturnThis();
|
|
||||||
|
|
||||||
controller.excludeSelected = {id: 1, type: 'all'};
|
|
||||||
controller.onExcludeResponse('delete');
|
|
||||||
|
|
||||||
expect(controller.exclusionDelete).toHaveBeenCalledWith(controller.excludeSelected);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onDeleteResponse()', () => {
|
|
||||||
it('shoud make an HTTP DELETE query and then call the refresh() method', () => {
|
|
||||||
jest.spyOn(controller, 'refresh').mockReturnThis();
|
|
||||||
|
|
||||||
const eventId = 1;
|
|
||||||
$httpBackend.expect('DELETE', `Zones/1/events/1`).respond({id: 1});
|
|
||||||
controller.onDeleteResponse('accept', eventId);
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.refresh).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('exclusionCreate()', () => {
|
|
||||||
it('shoud make an HTTP POST query and then call the refresh() method', () => {
|
|
||||||
jest.spyOn(controller, 'refresh').mockReturnThis();
|
|
||||||
|
|
||||||
controller.excludeSelected = {};
|
|
||||||
controller.isNew = true;
|
|
||||||
$httpBackend.expect('POST', `Zones/1/exclusions`).respond({id: 1});
|
|
||||||
controller.exclusionCreate();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.refresh).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('exclusionDelete()', () => {
|
|
||||||
it('shoud make an HTTP DELETE query once and then call the refresh() method', () => {
|
|
||||||
jest.spyOn(controller, 'refresh').mockReturnThis();
|
|
||||||
|
|
||||||
const exclusions = {id: 1};
|
|
||||||
const firstExclusionId = 1;
|
|
||||||
$httpBackend.expectDELETE(`Zones/1/exclusions/${firstExclusionId}`).respond(200);
|
|
||||||
controller.exclusionDelete(exclusions);
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.refresh).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onSearch()', () => {
|
|
||||||
it('should call the applyFilter() method and then set the data', () => {
|
|
||||||
jest.spyOn(controller, 'getChecked').mockReturnValue([1, 2, 3]);
|
|
||||||
|
|
||||||
controller.$.treeview = {};
|
|
||||||
controller.$.model = crudModel;
|
|
||||||
controller.excludeSelected = {type: 'specificLocations'};
|
|
||||||
controller._excludeSearch = 'es';
|
|
||||||
|
|
||||||
controller.onSearch();
|
|
||||||
const treeviewData = controller.$.treeview.data;
|
|
||||||
|
|
||||||
expect(treeviewData).toBeDefined();
|
|
||||||
expect(treeviewData.length).toEqual(3);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onFetch()', () => {
|
|
||||||
it('should call the applyFilter() method and then return the model data', () => {
|
|
||||||
jest.spyOn(controller, 'getChecked').mockReturnValue([1, 2, 3]);
|
|
||||||
|
|
||||||
controller.$.model = crudModel;
|
|
||||||
const result = controller.onFetch();
|
|
||||||
|
|
||||||
expect(result.length).toEqual(3);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,12 +0,0 @@
|
||||||
Edit mode: Modo de edición
|
|
||||||
Include: Incluir
|
|
||||||
Exclude: Excluir
|
|
||||||
Events: Eventos
|
|
||||||
Add event: Añadir evento
|
|
||||||
Edit event: Editar evento
|
|
||||||
All: Todo
|
|
||||||
Specific locations: Localizaciones concretas
|
|
||||||
Locations where it is not distributed: Localizaciones en las que no se reparte
|
|
||||||
You must select a location: Debes seleccionar una localización
|
|
||||||
Add exclusion: Añadir exclusión
|
|
||||||
Edit exclusion: Editar exclusión
|
|
|
@ -1,11 +0,0 @@
|
||||||
@import "variables";
|
|
||||||
|
|
||||||
.width{
|
|
||||||
width: 600px
|
|
||||||
}
|
|
||||||
|
|
||||||
.treeview{
|
|
||||||
max-height: 300px;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,19 +1,3 @@
|
||||||
export * from './module';
|
export * from './module';
|
||||||
|
|
||||||
import './main';
|
import './main';
|
||||||
import './index/';
|
|
||||||
import './delivery-days';
|
|
||||||
import './summary';
|
|
||||||
import './card';
|
|
||||||
import './descriptor';
|
|
||||||
import './descriptor-popover';
|
|
||||||
import './search-panel';
|
|
||||||
import './create';
|
|
||||||
import './basic-data';
|
|
||||||
import './warehouses';
|
|
||||||
import './events';
|
|
||||||
import './calendar';
|
|
||||||
import './location';
|
|
||||||
import './calendar';
|
|
||||||
import './upcoming-deliveries';
|
|
||||||
import './log';
|
|
||||||
|
|
|
@ -1,68 +0,0 @@
|
||||||
<vn-auto-search
|
|
||||||
model="model">
|
|
||||||
</vn-auto-search>
|
|
||||||
<vn-data-viewer
|
|
||||||
model="model"
|
|
||||||
class="vn-w-md vn-mb-xl">
|
|
||||||
<vn-card>
|
|
||||||
<vn-table model="model">
|
|
||||||
<vn-thead>
|
|
||||||
<vn-tr>
|
|
||||||
<vn-th field="id" number>Id</vn-th>
|
|
||||||
<vn-th field="name" expand>Name</vn-th>
|
|
||||||
<vn-th field="agencyModeFk">Agency</vn-th>
|
|
||||||
<vn-th field="hour" shrink>Closing</vn-th>
|
|
||||||
<vn-th field="price" number>Price</vn-th>
|
|
||||||
<vn-th shrink></vn-th>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-thead>
|
|
||||||
<vn-tbody>
|
|
||||||
<a
|
|
||||||
ng-repeat="zone in model.data"
|
|
||||||
ui-sref="zone.card.summary({id: zone.id})"
|
|
||||||
class="clickable vn-tr search-result">
|
|
||||||
<vn-td number>{{::zone.id}}</vn-td>
|
|
||||||
<vn-td expand>{{::zone.name}}</vn-td>
|
|
||||||
<vn-td expand>{{::zone.agencyMode.name}}</vn-td>
|
|
||||||
<vn-td shrink>{{::zone.hour | date: 'HH:mm'}}</vn-td>
|
|
||||||
<vn-td number>{{::zone.price | currency: 'EUR':2}}</vn-td>
|
|
||||||
<vn-td shrink>
|
|
||||||
<vn-horizontal class="buttons">
|
|
||||||
<vn-icon-button
|
|
||||||
vn-click-stop="clone.show(zone)"
|
|
||||||
vn-tooltip="Clone"
|
|
||||||
icon="icon-clone"
|
|
||||||
vn-acl="deliveryAssistant"
|
|
||||||
vn-acl-action="remove">
|
|
||||||
</vn-icon-button>
|
|
||||||
<vn-icon-button
|
|
||||||
vn-click-stop="$ctrl.preview(zone)"
|
|
||||||
vn-tooltip="Preview"
|
|
||||||
icon="preview">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-td>
|
|
||||||
</a>
|
|
||||||
</vn-tbody>
|
|
||||||
</vn-table>
|
|
||||||
</vn-card>
|
|
||||||
</vn-data-viewer>
|
|
||||||
<vn-popup vn-id="summary">
|
|
||||||
<vn-zone-summary zone="$ctrl.selectedZone"></vn-zone-summary>
|
|
||||||
</vn-popup>
|
|
||||||
<vn-confirm
|
|
||||||
vn-id="clone"
|
|
||||||
on-accept="$ctrl.onCloneAccept($data)"
|
|
||||||
question="Do you want to clone this zone?"
|
|
||||||
message="All it's properties will be copied">
|
|
||||||
</vn-confirm>
|
|
||||||
<a ui-sref="zone.create"
|
|
||||||
vn-tooltip="New zone"
|
|
||||||
vn-bind="+"
|
|
||||||
fixed-bottom-right>
|
|
||||||
<vn-float-button
|
|
||||||
icon="add"
|
|
||||||
vn-acl="deliveryAssistant"
|
|
||||||
vn-acl-action="remove">
|
|
||||||
</vn-float-button>
|
|
||||||
</a>
|
|
|
@ -1,21 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
preview(zone) {
|
|
||||||
this.selectedZone = zone;
|
|
||||||
this.$.summary.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
onCloneAccept(zone) {
|
|
||||||
return this.$http.post(`Zones/${zone.id}/clone`)
|
|
||||||
.then(res => {
|
|
||||||
this.$state.go('zone.card.basicData', {id: res.data.id});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnZoneIndex', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,2 +0,0 @@
|
||||||
Do you want to clone this zone?: ¿Seguro que quieres clonar esta zona?
|
|
||||||
All it's properties will be copied: Todas sus propiedades serán copiadas
|
|
|
@ -1,28 +0,0 @@
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="Zones/{{$ctrl.$params.id}}/getLeaves"
|
|
||||||
filter="$ctrl.filter">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-portal slot="topbar">
|
|
||||||
<vn-searchbar
|
|
||||||
on-search="$ctrl.onSearch($params)"
|
|
||||||
auto-state="false">
|
|
||||||
</vn-searchbar>
|
|
||||||
</vn-portal>
|
|
||||||
<div class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-treeview
|
|
||||||
vn-id="treeview"
|
|
||||||
root-label="Locations"
|
|
||||||
fetch-func="$ctrl.onFetch($item)"
|
|
||||||
sort-func="$ctrl.onSort($a, $b)">
|
|
||||||
<vn-check acl-role="deliveryAssistant"
|
|
||||||
ng-model="item.selected"
|
|
||||||
on-change="$ctrl.onSelection(value, item)"
|
|
||||||
triple-state="true"
|
|
||||||
ng-click="$event.preventDefault()"
|
|
||||||
label="{{::item.name}}">
|
|
||||||
</vn-check>
|
|
||||||
</vn-treeview>
|
|
||||||
</vn-card>
|
|
||||||
</div>
|
|
|
@ -1,56 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
|
||||||
onSearch(params) {
|
|
||||||
this.$.model.applyFilter({}, params).then(() => {
|
|
||||||
const data = this.$.model.data;
|
|
||||||
this.$.treeview.data = data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onFetch(item) {
|
|
||||||
const params = item ? {parentId: item.id} : null;
|
|
||||||
return this.$.model.applyFilter({}, params)
|
|
||||||
.then(() => this.$.model.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
onSort(a, b) {
|
|
||||||
if (b.selected !== a.selected) {
|
|
||||||
if (a.selected == null)
|
|
||||||
return 1;
|
|
||||||
if (b.selected == null)
|
|
||||||
return -1;
|
|
||||||
return b.selected - a.selected;
|
|
||||||
}
|
|
||||||
|
|
||||||
return a.name.localeCompare(b.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
exprBuilder(param, value) {
|
|
||||||
switch (param) {
|
|
||||||
case 'search':
|
|
||||||
return {name: {like: `%${value}%`}};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onSelection(value, item) {
|
|
||||||
if (value == null)
|
|
||||||
value = undefined;
|
|
||||||
const params = {geoId: item.id, isIncluded: value};
|
|
||||||
const path = `zones/${this.zone.id}/toggleIsIncluded`;
|
|
||||||
this.$http.post(path, params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnZoneLocation', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
zone: '<'
|
|
||||||
},
|
|
||||||
require: {
|
|
||||||
card: '^vnZoneCard'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,50 +0,0 @@
|
||||||
import './index';
|
|
||||||
import crudModel from 'core/mocks/crud-model';
|
|
||||||
|
|
||||||
describe('component vnZoneLocation', () => {
|
|
||||||
let $scope;
|
|
||||||
let controller;
|
|
||||||
let $httpBackend;
|
|
||||||
|
|
||||||
beforeEach(ngModule('zone'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => {
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
$scope = $rootScope.$new();
|
|
||||||
const $element = angular.element(`<vn-zone-location></vn-zone-location>`);
|
|
||||||
controller = $componentController('vnZoneLocation', {$element, $scope});
|
|
||||||
controller.$.model = crudModel;
|
|
||||||
controller.zone = {id: 1};
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('onSearch()', () => {
|
|
||||||
it('should call the applyFilter() method and then set the data', () => {
|
|
||||||
controller.$.treeview = {};
|
|
||||||
controller.onSearch({});
|
|
||||||
|
|
||||||
const treeviewData = controller.$.treeview.data;
|
|
||||||
|
|
||||||
expect(treeviewData).toBeDefined();
|
|
||||||
expect(treeviewData.length).toEqual(3);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onFetch()', () => {
|
|
||||||
it('should call the applyFilter() method and then return the model data', () => {
|
|
||||||
const result = controller.onFetch();
|
|
||||||
|
|
||||||
expect(result.length).toEqual(3);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onSelection()', () => {
|
|
||||||
it('should make an HTTP POST query', () => {
|
|
||||||
const item = {id: 123};
|
|
||||||
|
|
||||||
const expectedParams = {geoId: 123, isIncluded: true};
|
|
||||||
$httpBackend.expect('POST', `zones/1/toggleIsIncluded`, expectedParams).respond(200);
|
|
||||||
controller.onSelection(true, item);
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,21 +0,0 @@
|
||||||
@import "variables";
|
|
||||||
|
|
||||||
vn-zone-location {
|
|
||||||
vn-treeview-child {
|
|
||||||
.content > .vn-check:not(.indeterminate):not(.checked) {
|
|
||||||
color: $color-alert;
|
|
||||||
|
|
||||||
& > .btn {
|
|
||||||
border-color: $color-alert;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.content > .vn-check.checked {
|
|
||||||
color: $color-notice;
|
|
||||||
|
|
||||||
& > .btn {
|
|
||||||
background-color: $color-notice;
|
|
||||||
border-color: $color-notice
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
<vn-log url="ZoneLogs" origin-id="$ctrl.$params.id"></vn-log>
|
|
|
@ -1,7 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnZoneLog', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Section,
|
|
||||||
});
|
|
|
@ -1,19 +0,0 @@
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="Zones"
|
|
||||||
filter="::$ctrl.filter"
|
|
||||||
limit="20">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-portal slot="topbar">
|
|
||||||
<vn-searchbar
|
|
||||||
vn-focus
|
|
||||||
info="Search zone by id or name"
|
|
||||||
panel="vn-zone-search-panel"
|
|
||||||
model="model"
|
|
||||||
expr-builder="$ctrl.exprBuilder(param, value)">
|
|
||||||
</vn-searchbar>
|
|
||||||
</vn-portal>
|
|
||||||
<vn-portal slot="menu">
|
|
||||||
<vn-left-menu></vn-left-menu>
|
|
||||||
</vn-portal>
|
|
||||||
<ui-view></ui-view>
|
|
|
@ -4,25 +4,10 @@ import ModuleMain from 'salix/components/module-main';
|
||||||
export default class Zone extends ModuleMain {
|
export default class Zone extends ModuleMain {
|
||||||
constructor($element, $) {
|
constructor($element, $) {
|
||||||
super($element, $);
|
super($element, $);
|
||||||
this.filter = {
|
|
||||||
include: {
|
|
||||||
relation: 'agencyMode',
|
|
||||||
scope: {fields: ['name']}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
exprBuilder(param, value) {
|
|
||||||
switch (param) {
|
|
||||||
case 'search':
|
|
||||||
return /^\d+$/.test(value)
|
|
||||||
? {id: value}
|
|
||||||
: {name: {like: `%${value}%`}};
|
|
||||||
case 'name':
|
|
||||||
return {[param]: {like: `%${value}%`}};
|
|
||||||
case 'agencyModeFk':
|
|
||||||
return {[param]: value};
|
|
||||||
}
|
}
|
||||||
|
async $onInit() {
|
||||||
|
this.$state.go('home');
|
||||||
|
window.location.href = await this.vnApp.getUrl(`zone/`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
|
|
||||||
describe('Zone Component vnZone', () => {
|
|
||||||
let controller;
|
|
||||||
|
|
||||||
beforeEach(ngModule('zone'));
|
|
||||||
|
|
||||||
beforeEach(inject($componentController => {
|
|
||||||
const $element = angular.element('<vn-zone></vn-zone>');
|
|
||||||
controller = $componentController('vnZone', {$element});
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('exprBuilder()', () => {
|
|
||||||
it('should return a formated object with the id in case of search', () => {
|
|
||||||
let param = 'search';
|
|
||||||
let value = 1;
|
|
||||||
let result = controller.exprBuilder(param, value);
|
|
||||||
|
|
||||||
expect(result).toEqual({id: 1});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return a formated object with the agencyModeFk in case of agencyModeFk', () => {
|
|
||||||
let param = 'agencyModeFk';
|
|
||||||
let value = 'My Delivery';
|
|
||||||
let result = controller.exprBuilder(param, value);
|
|
||||||
|
|
||||||
expect(result).toEqual({agencyModeFk: 'My Delivery'});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -7,15 +7,6 @@
|
||||||
"menus": {
|
"menus": {
|
||||||
"main": [
|
"main": [
|
||||||
{"state": "zone.index", "icon": "icon-zone"},
|
{"state": "zone.index", "icon": "icon-zone"},
|
||||||
{"state": "zone.deliveryDays", "icon": "today"},
|
|
||||||
{"state": "zone.upcomingDeliveries", "icon": "today"}
|
|
||||||
],
|
|
||||||
"card": [
|
|
||||||
{"state": "zone.card.basicData", "icon": "settings"},
|
|
||||||
{"state": "zone.card.location", "icon": "my_location"},
|
|
||||||
{"state": "zone.card.warehouses", "icon": "home"},
|
|
||||||
{"state": "zone.card.log", "icon": "history"},
|
|
||||||
{"state": "zone.card.events", "icon": "today"}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"keybindings": [
|
"keybindings": [
|
||||||
|
@ -34,79 +25,6 @@
|
||||||
"state": "zone.index",
|
"state": "zone.index",
|
||||||
"component": "vn-zone-index",
|
"component": "vn-zone-index",
|
||||||
"description": "Zones"
|
"description": "Zones"
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "/delivery-days?q&deliveryMethodFk&geoFk&agencyModeFk",
|
|
||||||
"state": "zone.deliveryDays",
|
|
||||||
"component": "vn-zone-delivery-days",
|
|
||||||
"description": "Delivery days"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "/upcoming-deliveries",
|
|
||||||
"state": "zone.upcomingDeliveries",
|
|
||||||
"component": "vn-upcoming-deliveries",
|
|
||||||
"description": "Upcoming deliveries"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "/create",
|
|
||||||
"state": "zone.create",
|
|
||||||
"component": "vn-zone-create",
|
|
||||||
"description": "New zone"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "/:id",
|
|
||||||
"state": "zone.card",
|
|
||||||
"component": "vn-zone-card",
|
|
||||||
"abstract": true,
|
|
||||||
"description": "Detail"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "/summary",
|
|
||||||
"state": "zone.card.summary",
|
|
||||||
"component": "vn-zone-summary",
|
|
||||||
"description": "Summary",
|
|
||||||
"params": {
|
|
||||||
"zone": "$ctrl.zone"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "/basic-data",
|
|
||||||
"state": "zone.card.basicData",
|
|
||||||
"component": "vn-zone-basic-data",
|
|
||||||
"description": "Basic data",
|
|
||||||
"params": {
|
|
||||||
"zone": "$ctrl.zone"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "/warehouses",
|
|
||||||
"state": "zone.card.warehouses",
|
|
||||||
"component": "vn-zone-warehouses",
|
|
||||||
"description": "Warehouses"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "/events?q",
|
|
||||||
"state": "zone.card.events",
|
|
||||||
"component": "vn-zone-events",
|
|
||||||
"description": "Calendar",
|
|
||||||
"params": {
|
|
||||||
"zone": "$ctrl.zone"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "/location?q",
|
|
||||||
"state": "zone.card.location",
|
|
||||||
"component": "vn-zone-location",
|
|
||||||
"description": "Locations",
|
|
||||||
"params": {
|
|
||||||
"zone": "$ctrl.zone"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url" : "/log",
|
|
||||||
"state": "zone.card.log",
|
|
||||||
"component": "vn-zone-log",
|
|
||||||
"description": "Log"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -1,34 +0,0 @@
|
||||||
<div class="search-panel">
|
|
||||||
<form ng-submit="$ctrl.onSearch()">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="General search"
|
|
||||||
ng-model="filter.search"
|
|
||||||
info="Search zone by id or name"
|
|
||||||
vn-focus>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Name"
|
|
||||||
ng-model="filter.name">
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
label="Agency"
|
|
||||||
ng-model="filter.agencyModeFk"
|
|
||||||
url="AgencyModes/isActive"
|
|
||||||
where="{deliveryMethodFk: {neq: null}}"
|
|
||||||
value-field="id"
|
|
||||||
show-field="name">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-mt-lg">
|
|
||||||
<vn-submit label="Search"></vn-submit>
|
|
||||||
</vn-horizontal>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
|
@ -1,7 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import SearchPanel from 'core/components/searchbar/search-panel';
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnZoneSearchPanel', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: SearchPanel
|
|
||||||
});
|
|
|
@ -1,59 +0,0 @@
|
||||||
<vn-card class="summary">
|
|
||||||
<h5>
|
|
||||||
<a
|
|
||||||
ng-if="::$ctrl.summary.id"
|
|
||||||
vn-tooltip="Go to the zone"
|
|
||||||
ui-sref="zone.card.summary({id: {{::$ctrl.summary.id}}})"
|
|
||||||
name="goToSummary">
|
|
||||||
<vn-icon-button icon="launch"></vn-icon-button>
|
|
||||||
</a>
|
|
||||||
<span>#{{$ctrl.summary.id}} - {{$ctrl.summary.name}}</span>
|
|
||||||
</h5>
|
|
||||||
<vn-horizontal class="vn-pa-md">
|
|
||||||
<vn-one>
|
|
||||||
<vn-label-value label="Agency"
|
|
||||||
value="{{$ctrl.summary.agencyMode.name}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value label="Price"
|
|
||||||
value="{{$ctrl.summary.price | currency: 'EUR': 2}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value label="Bonus"
|
|
||||||
value="{{$ctrl.summary.bonus | currency: 'EUR': 2}}">
|
|
||||||
</vn-label-value>
|
|
||||||
</vn-one>
|
|
||||||
<vn-one>
|
|
||||||
<vn-label-value label="Closing hour"
|
|
||||||
value="{{$ctrl.summary.hour | date: 'HH:mm'}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-label-value label="Traveling days"
|
|
||||||
value="{{$ctrl.summary.travelingDays}}">
|
|
||||||
</vn-label-value>
|
|
||||||
<vn-vertical>
|
|
||||||
<vn-check label="Volumetric" disabled="true"
|
|
||||||
ng-model="$ctrl.summary.isVolumetric">
|
|
||||||
</vn-check>
|
|
||||||
</vn-vertical>
|
|
||||||
</vn-one>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-pa-md">
|
|
||||||
<vn-auto>
|
|
||||||
<h4>
|
|
||||||
<a ui-sref="zone.card.warehouses({id:$ctrl.zone.id})">
|
|
||||||
<span translate vn-tooltip="Go to">Warehouse</span>
|
|
||||||
</a>
|
|
||||||
</h4>
|
|
||||||
<vn-table model="model" auto-load="false">
|
|
||||||
<vn-thead>
|
|
||||||
<vn-tr>
|
|
||||||
<vn-th>Name</vn-th>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-thead>
|
|
||||||
<vn-tbody>
|
|
||||||
<vn-tr ng-repeat="zoneWarehouse in $ctrl.zoneWarehouses">
|
|
||||||
<vn-td>{{zoneWarehouse.warehouse.name}}</vn-td>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-tbody>
|
|
||||||
</vn-table>
|
|
||||||
</vn-auto>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-card>
|
|
|
@ -1,56 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Summary from 'salix/components/summary';
|
|
||||||
|
|
||||||
class Controller extends Summary {
|
|
||||||
get zone() {
|
|
||||||
return this._zone;
|
|
||||||
}
|
|
||||||
|
|
||||||
set zone(value) {
|
|
||||||
this._zone = value;
|
|
||||||
|
|
||||||
if (!value) return;
|
|
||||||
|
|
||||||
this.getSummary();
|
|
||||||
this.getWarehouses();
|
|
||||||
}
|
|
||||||
|
|
||||||
getSummary() {
|
|
||||||
const params = {
|
|
||||||
filter: {
|
|
||||||
include: {
|
|
||||||
relation: 'agencyMode',
|
|
||||||
fields: ['name']
|
|
||||||
},
|
|
||||||
where: {
|
|
||||||
id: this.zone.id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.$http.get(`Zones/findOne`, {params}).then(res => {
|
|
||||||
this.summary = res.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getWarehouses() {
|
|
||||||
const params = {
|
|
||||||
filter: {
|
|
||||||
include: {
|
|
||||||
relation: 'warehouse',
|
|
||||||
fields: ['name']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.$http.get(`Zones/${this.zone.id}/warehouses`, {params}).then(res => {
|
|
||||||
this.zoneWarehouses = res.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnZoneSummary', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
zone: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,76 +0,0 @@
|
||||||
import './index';
|
|
||||||
|
|
||||||
describe('component vnZoneSummary', () => {
|
|
||||||
let $scope;
|
|
||||||
let controller;
|
|
||||||
let $httpBackend;
|
|
||||||
let $httpParamSerializer;
|
|
||||||
|
|
||||||
beforeEach(ngModule('zone'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_, _$httpParamSerializer_) => {
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
$httpParamSerializer = _$httpParamSerializer_;
|
|
||||||
$scope = $rootScope.$new();
|
|
||||||
const $element = angular.element(`<vn-zone-summary></vn-zone-summary>`);
|
|
||||||
controller = $componentController('vnZoneSummary', {$element, $scope});
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('zone setter', () => {
|
|
||||||
it('should set the zone and then call both getSummary() and getWarehouses()', () => {
|
|
||||||
jest.spyOn(controller, 'getSummary');
|
|
||||||
jest.spyOn(controller, 'getWarehouses');
|
|
||||||
|
|
||||||
controller.zone = {id: 1};
|
|
||||||
|
|
||||||
expect(controller.getSummary).toHaveBeenCalledWith();
|
|
||||||
expect(controller.getWarehouses).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('getSummary()', () => {
|
|
||||||
it('should perform a get and then store data on the controller', () => {
|
|
||||||
controller._zone = {id: 1};
|
|
||||||
let params = {
|
|
||||||
filter: {
|
|
||||||
include: {
|
|
||||||
relation: 'agencyMode',
|
|
||||||
fields: ['name']
|
|
||||||
},
|
|
||||||
where: {
|
|
||||||
id: controller._zone.id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const serializedParams = $httpParamSerializer(params);
|
|
||||||
const query = `Zones/findOne?${serializedParams}`;
|
|
||||||
$httpBackend.expectGET(query).respond({id: 1});
|
|
||||||
controller.getSummary();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.summary).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('getWarehouses()', () => {
|
|
||||||
it('should make an HTTP get query and then store data on the controller', () => {
|
|
||||||
controller._zone = {id: 1};
|
|
||||||
const params = {
|
|
||||||
filter: {
|
|
||||||
include: {
|
|
||||||
relation: 'warehouse',
|
|
||||||
fields: ['name']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const serializedParams = $httpParamSerializer(params);
|
|
||||||
const query = `Zones/1/warehouses?${serializedParams}`;
|
|
||||||
$httpBackend.expect('GET', query).respond([{id: 1}]);
|
|
||||||
controller.getWarehouses();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.zoneWarehouses.length).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,31 +0,0 @@
|
||||||
<vn-crud-model
|
|
||||||
vn-id="model"
|
|
||||||
url="Zones/getUpcomingDeliveries"
|
|
||||||
data="details"
|
|
||||||
auto-load="true">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-data-viewer model="model">
|
|
||||||
<vn-card>
|
|
||||||
<section ng-repeat="detail in details" class="vn-pa-md">
|
|
||||||
<vn-horizontal class="header">
|
|
||||||
<h5>{{$ctrl.getWeekDay(detail.shipped)}} - {{detail.shipped | date: 'dd/MM/yyyy'}}</h5>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-table>
|
|
||||||
<vn-thead>
|
|
||||||
<vn-tr>
|
|
||||||
<vn-th class="waste-family">Province</vn-th>
|
|
||||||
<vn-th number>Closing</vn-th>
|
|
||||||
<vn-th number>Id</vn-th>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-thead>
|
|
||||||
<vn-tbody>
|
|
||||||
<vn-tr ng-repeat="zone in detail.lines">
|
|
||||||
<vn-td class="waste-family">{{::zone.name}}</vn-td>
|
|
||||||
<vn-td number>{{::zone.hour}}</vn-td>
|
|
||||||
<vn-td number>{{::zone.zoneFk}}</vn-td>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-tbody>
|
|
||||||
</vn-table>
|
|
||||||
</section>
|
|
||||||
</vn-card>
|
|
||||||
</vn-data-viewer>
|
|
|
@ -1,23 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
|
||||||
constructor($element, $, vnWeekDays) {
|
|
||||||
super($element, $);
|
|
||||||
this.days = vnWeekDays.days;
|
|
||||||
}
|
|
||||||
|
|
||||||
getWeekDay(jsonDate) {
|
|
||||||
const weekDay = new Date(jsonDate).getDay();
|
|
||||||
|
|
||||||
return this.days[weekDay].locale;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Controller.$inject = ['$element', '$scope', 'vnWeekDays'];
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnUpcomingDeliveries', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,22 +0,0 @@
|
||||||
import './index';
|
|
||||||
|
|
||||||
describe('component vnUpcomingDeliveries', () => {
|
|
||||||
let $scope;
|
|
||||||
let controller;
|
|
||||||
|
|
||||||
beforeEach(ngModule('zone'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, $rootScope) => {
|
|
||||||
$scope = $rootScope.$new();
|
|
||||||
const $element = angular.element(`<vn-upcoming-deliveries></vn-upcoming-deliveries>`);
|
|
||||||
controller = $componentController('vnUpcomingDeliveries', {$element, $scope});
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('getWeekDay()', () => {
|
|
||||||
it('should retrieve a weekday for a json passed', () => {
|
|
||||||
let jsonDate = '1970-01-01T22:00:00.000Z';
|
|
||||||
|
|
||||||
expect(controller.getWeekDay(jsonDate)).toEqual('Thursday');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,3 +0,0 @@
|
||||||
Family: Familia
|
|
||||||
Percentage: Porcentaje
|
|
||||||
Dwindle: Mermas
|
|
|
@ -1,26 +0,0 @@
|
||||||
@import "variables";
|
|
||||||
|
|
||||||
vn-upcoming-deliveries {
|
|
||||||
.header {
|
|
||||||
margin-bottom: 16px;
|
|
||||||
text-transform: uppercase;
|
|
||||||
font-size: 1.25rem;
|
|
||||||
line-height: 1;
|
|
||||||
padding: 7px;
|
|
||||||
padding-bottom: 7px;
|
|
||||||
padding-bottom: 4px;
|
|
||||||
font-weight: lighter;
|
|
||||||
background-color: $color-main-light;
|
|
||||||
border-bottom: 1px solid $color-primary;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
background-color: $color-bg;
|
|
||||||
}
|
|
||||||
|
|
||||||
vn-table vn-th.waste-family,
|
|
||||||
vn-table vn-td.waste-family {
|
|
||||||
max-width: 64px;
|
|
||||||
width: 64px
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
<vn-data-viewer
|
|
||||||
data="data"
|
|
||||||
is-loading="!data"
|
|
||||||
class="vn-w-xs">
|
|
||||||
<vn-card>
|
|
||||||
<vn-table>
|
|
||||||
<vn-tbody>
|
|
||||||
<vn-tr ng-repeat="row in data | orderBy:'warehouse.name'">
|
|
||||||
<vn-td>{{::row.warehouse.name}}</vn-td>
|
|
||||||
<vn-td shrink>
|
|
||||||
<vn-icon-button
|
|
||||||
icon="delete"
|
|
||||||
translate-attr="{title: 'Delete'}"
|
|
||||||
ng-click="$ctrl.onDelete(row)">
|
|
||||||
</vn-icon-button>
|
|
||||||
</vn-td>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-tbody>
|
|
||||||
</vn-table>
|
|
||||||
</vn-card>
|
|
||||||
</vn-data-viewer>
|
|
||||||
<vn-float-button
|
|
||||||
icon="add"
|
|
||||||
translate-attr="{title: 'Add'}"
|
|
||||||
vn-bind="+"
|
|
||||||
ng-click="$ctrl.onCreate()"
|
|
||||||
fixed-bottom-right>
|
|
||||||
</vn-float-button>
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="Warehouses"
|
|
||||||
data="warehouses"
|
|
||||||
order="name">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-dialog
|
|
||||||
vn-id="dialog"
|
|
||||||
on-accept="$ctrl.onSave()">
|
|
||||||
<tpl-body>
|
|
||||||
<vn-autocomplete
|
|
||||||
ng-model="$ctrl.selected.warehouseFk"
|
|
||||||
data="warehouses"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
label="Warehouse">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</tpl-body>
|
|
||||||
<tpl-buttons>
|
|
||||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
|
||||||
<button response="accept" translate>Save</button>
|
|
||||||
</tpl-buttons>
|
|
||||||
</vn-dialog>
|
|
||||||
<vn-confirm
|
|
||||||
vn-id="confirm"
|
|
||||||
message="This item will be deleted"
|
|
||||||
question="Are you sure you want to continue?"
|
|
||||||
on-accept="$ctrl.delete()">
|
|
||||||
</vn-confirm>
|
|
|
@ -1,56 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
|
||||||
$onInit() {
|
|
||||||
this.refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
get path() {
|
|
||||||
return `Zones/${this.$params.id}/warehouses`;
|
|
||||||
}
|
|
||||||
|
|
||||||
refresh() {
|
|
||||||
let filter = {include: 'warehouse'};
|
|
||||||
this.$http.get(this.path, {params: {filter}})
|
|
||||||
.then(res => this.$.data = res.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
onCreate() {
|
|
||||||
this.selected = {};
|
|
||||||
this.$.dialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
onSave() {
|
|
||||||
this.$http.post(this.path, this.selected)
|
|
||||||
.then(() => {
|
|
||||||
this.selected = null;
|
|
||||||
this.isNew = null;
|
|
||||||
this.$.dialog.hide();
|
|
||||||
this.refresh();
|
|
||||||
});
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
onDelete(row) {
|
|
||||||
this.$.confirm.show();
|
|
||||||
this.deleteRow = row;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete() {
|
|
||||||
let row = this.deleteRow;
|
|
||||||
if (!row) return;
|
|
||||||
return this.$http.delete(`${this.path}/${row.id}`)
|
|
||||||
.then(() => {
|
|
||||||
let index = this.$.data.indexOf(row);
|
|
||||||
if (index !== -1) this.$.data.splice(index, 1);
|
|
||||||
this.deleteRow = null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnZoneWarehouses', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,60 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
|
|
||||||
describe('Zone warehouses', () => {
|
|
||||||
let $httpBackend;
|
|
||||||
let $httpParamSerializer;
|
|
||||||
let controller;
|
|
||||||
let $element;
|
|
||||||
|
|
||||||
beforeEach(ngModule('zone'));
|
|
||||||
|
|
||||||
beforeEach(inject(($componentController, _$httpBackend_, _$httpParamSerializer_) => {
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
$httpParamSerializer = _$httpParamSerializer_;
|
|
||||||
$element = angular.element('<vn-zone-warehouses></vn-zone-warehouses');
|
|
||||||
controller = $componentController('vnZoneWarehouses', {$element});
|
|
||||||
controller.zone = {id: 1};
|
|
||||||
controller.$params = {id: 1};
|
|
||||||
controller.$.dialog = {hide: jest.fn()};
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('refresh()', () => {
|
|
||||||
it('should make an HTTP GET query and then set the data', () => {
|
|
||||||
const params = {filter: {include: 'warehouse'}};
|
|
||||||
const serializedParams = $httpParamSerializer(params);
|
|
||||||
const path = `Zones/1/warehouses?${serializedParams}`;
|
|
||||||
$httpBackend.expect('GET', path).respond([{id: 1, name: 'Warehouse one'}]);
|
|
||||||
controller.refresh();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.$.data).toBeDefined();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onSave()', () => {
|
|
||||||
it('should make an HTTP POST query and then call the refresh() method', () => {
|
|
||||||
jest.spyOn(controller, 'refresh').mockReturnThis();
|
|
||||||
|
|
||||||
$httpBackend.expect('POST', `Zones/1/warehouses`).respond(200);
|
|
||||||
controller.onSave();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.selected).toBeNull();
|
|
||||||
expect(controller.isNew).toBeNull();
|
|
||||||
expect(controller.$.dialog.hide).toHaveBeenCalledWith();
|
|
||||||
expect(controller.refresh).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('delete()', () => {
|
|
||||||
it('should make an HTTP DELETE query and then set deleteRow property to null value', () => {
|
|
||||||
controller.deleteRow = {id: 1};
|
|
||||||
controller.$.data = [{id: 1}];
|
|
||||||
$httpBackend.expect('DELETE', `Zones/1/warehouses/1`).respond(200);
|
|
||||||
controller.delete();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.deleteRow).toBeNull();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
Loading…
Reference in New Issue