Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 3256-order_transactions
This commit is contained in:
commit
6aa3101e42
|
@ -1,6 +1,7 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
|
||||
describe('newCollection()', () => {
|
||||
// #3400 analizar que hacer con rutas de back colletion
|
||||
xdescribe('newCollection()', () => {
|
||||
it('return a new collection', async() => {
|
||||
let ctx = {req: {accessToken: {userId: 1106}}};
|
||||
let response = await app.models.Collection.newCollection(ctx, 1, 1, 1);
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
UPDATE vn.absenceType
|
||||
SET code='halfPaidLeave'
|
||||
WHERE id=15 AND name='Permiso retribuido 1/2 día' AND rgb='#5151c0' AND code IS NULL AND permissionRate=NULL AND holidayEntitlementRate=0.50 AND discountRate=0.00;
|
|
@ -0,0 +1,27 @@
|
|||
INSERT INTO `salix`.`ACL`
|
||||
(model, property, accessType, permission, principalType, principalId)
|
||||
VALUES
|
||||
('EntryObservation', '*', '*', 'ALLOW', 'ROLE', 'buyer'),
|
||||
('LdapConfig', '*', '*', 'ALLOW', 'ROLE', 'sysadmin'),
|
||||
('SambaConfig', '*', '*', 'ALLOW', 'ROLE', 'sysadmin'),
|
||||
('ACL', '*', '*', 'ALLOW', 'ROLE', 'developer'),
|
||||
('AccessToken', '*', '*', 'ALLOW', 'ROLE', 'developer'),
|
||||
('MailAliasAccount', '*', '*', 'ALLOW', 'ROLE', 'marketing'),
|
||||
('MailAliasAccount', '*', '*', 'ALLOW', 'ROLE', 'hr'),
|
||||
('MailAlias', '*', '*', 'ALLOW', 'ROLE', 'hr'),
|
||||
('MailForward', '*', '*', 'ALLOW', 'ROLE', 'marketing'),
|
||||
('MailForward', '*', '*', 'ALLOW', 'ROLE', 'hr'),
|
||||
('RoleInherit', '*', '*', 'ALLOW', 'ROLE', 'it'),
|
||||
('RoleRole', '*', '*', 'ALLOW', 'ROLE', 'it'),
|
||||
('AccountConfig', '*', '*', 'ALLOW', 'ROLE', 'sysadmin');
|
||||
|
||||
UPDATE `salix`.`ACL`
|
||||
SET accessType='*', principalId='it'
|
||||
WHERE model = 'Role';
|
||||
|
||||
DELETE FROM `salix`.`ACL`
|
||||
WHERE id IN (280, 281);
|
||||
|
||||
UPDATE `salix`.`ACL`
|
||||
SET accessType='*', principalId='marketing'
|
||||
WHERE id=279;
|
|
@ -0,0 +1,33 @@
|
|||
UPDATE vn.department
|
||||
SET notificationEmail='direccioncomercial@verdnatura.es'
|
||||
WHERE id=96;
|
||||
UPDATE vn.department
|
||||
SET notificationEmail='direccioncomercial@verdnatura.es'
|
||||
WHERE id=95;
|
||||
UPDATE vn.department
|
||||
SET notificationEmail='direccioncomercial@verdnatura.es'
|
||||
WHERE id=115;
|
||||
UPDATE vn.department
|
||||
SET notificationEmail='direccioncomercial@verdnatura.es'
|
||||
WHERE id=123;
|
||||
UPDATE vn.department
|
||||
SET notificationEmail='direccioncomercial@verdnatura.es'
|
||||
WHERE id=94;
|
||||
UPDATE vn.department
|
||||
SET notificationEmail='direccioncomercial@verdnatura.es'
|
||||
WHERE id=101;
|
||||
UPDATE vn.department
|
||||
SET notificationEmail='direccioncomercial@verdnatura.es'
|
||||
WHERE id=80;
|
||||
UPDATE vn.department
|
||||
SET notificationEmail='direccioncomercial@verdnatura.es'
|
||||
WHERE id=125;
|
||||
UPDATE vn.department
|
||||
SET notificationEmail='direccioncomercial@verdnatura.es'
|
||||
WHERE id=98;
|
||||
UPDATE vn.department
|
||||
SET notificationEmail='direccioncomercial@verdnatura.es'
|
||||
WHERE id=92;
|
||||
UPDATE vn.department
|
||||
SET notificationEmail=''
|
||||
WHERE id=43;
|
|
@ -0,0 +1,120 @@
|
|||
DROP PROCEDURE IF EXISTS `vn`.`sale_recalcComponent`;
|
||||
|
||||
DELIMITER $$
|
||||
$$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`sale_recalcComponent`(vOption INT)
|
||||
proc: BEGIN
|
||||
/**
|
||||
* Actualiza los componentes
|
||||
*
|
||||
* @table tmp.recalculateSales
|
||||
*/
|
||||
DECLARE vShipped DATE;
|
||||
DECLARE vWarehouseFk SMALLINT;
|
||||
DECLARE vAgencyModeFk INT;
|
||||
DECLARE vAddressFk INT;
|
||||
DECLARE vTicketFk BIGINT;
|
||||
DECLARE vItemFk BIGINT;
|
||||
DECLARE vLanded DATE;
|
||||
DECLARE vIsEditable BOOLEAN;
|
||||
DECLARE vZoneFk INTEGER;
|
||||
DECLARE vOption INTEGER;
|
||||
|
||||
DECLARE vSale INTEGER;
|
||||
DECLARE vDone BOOL DEFAULT FALSE;
|
||||
|
||||
DECLARE vCur CURSOR FOR
|
||||
SELECT id from tmp.recalculateSales;
|
||||
|
||||
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
||||
|
||||
OPEN vCur;
|
||||
|
||||
l: LOOP
|
||||
SET vDone = FALSE;
|
||||
FETCH vCur INTO vSale;
|
||||
|
||||
IF vDone THEN
|
||||
LEAVE l;
|
||||
END IF;
|
||||
|
||||
SELECT t.refFk IS NULL AND (IFNULL(ts.alertLevel, 0) = 0 OR s.price = 0),
|
||||
s.ticketFk,
|
||||
s.itemFk ,
|
||||
t.zoneFk,
|
||||
t.warehouseFk,
|
||||
t.shipped,
|
||||
t.addressFk,
|
||||
t.agencyModeFk,
|
||||
t.landed
|
||||
INTO vIsEditable,
|
||||
vTicketFk,
|
||||
vItemFk,
|
||||
vZoneFk,
|
||||
vWarehouseFk,
|
||||
vShipped,
|
||||
vAddressFk,
|
||||
vAgencyModeFk,
|
||||
vLanded
|
||||
FROM ticket t
|
||||
JOIN sale s ON s.ticketFk = t.id
|
||||
LEFT JOIN ticketState ts ON ts.ticketFk = t.id
|
||||
WHERE s.id = vSale;
|
||||
|
||||
CALL zone_getLanded(vShipped, vAddressFk, vAgencyModeFk, vWarehouseFk, TRUE);
|
||||
|
||||
IF (SELECT COUNT(*) FROM tmp.zoneGetLanded LIMIT 1) = 0 THEN
|
||||
CALL util.throw('There is no zone for these parameters');
|
||||
END IF;
|
||||
|
||||
IF vLanded IS NULL OR vZoneFk IS NULL THEN
|
||||
|
||||
UPDATE ticket t
|
||||
SET t.landed = (SELECT landed FROM tmp.zoneGetLanded LIMIT 1)
|
||||
WHERE t.id = vTicketFk AND t.landed IS NULL;
|
||||
|
||||
IF vZoneFk IS NULL THEN
|
||||
SELECT zoneFk INTO vZoneFk FROM tmp.zoneGetLanded LIMIT 1;
|
||||
UPDATE ticket t
|
||||
SET t.zoneFk = vZoneFk
|
||||
WHERE t.id = vTicketFk AND t.zoneFk IS NULL;
|
||||
END IF;
|
||||
|
||||
END IF;
|
||||
|
||||
DROP TEMPORARY TABLE tmp.zoneGetLanded;
|
||||
|
||||
-- rellena la tabla buyUltimate con la ultima compra
|
||||
CALL buyUltimate (vWarehouseFk, vShipped);
|
||||
|
||||
DELETE FROM tmp.buyUltimate WHERE itemFk != vItemFk;
|
||||
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.ticketLot;
|
||||
CREATE TEMPORARY TABLE tmp.ticketLot
|
||||
SELECT vWarehouseFk warehouseFk, NULL available, vItemFk itemFk, buyFk, vZoneFk zoneFk
|
||||
FROM tmp.buyUltimate
|
||||
WHERE itemFk = vItemFk;
|
||||
|
||||
CALL catalog_componentPrepare();
|
||||
CALL catalog_componentCalculate(vZoneFk, vAddressFk, vShipped, vWarehouseFk);
|
||||
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.sale;
|
||||
CREATE TEMPORARY TABLE tmp.sale
|
||||
(PRIMARY KEY (saleFk)) ENGINE = MEMORY
|
||||
SELECT vSale saleFk,vWarehouseFk warehouseFk;
|
||||
|
||||
IF vOption IS NULL THEN
|
||||
SET vOption = IF(vIsEditable, 1, 6);
|
||||
END IF;
|
||||
|
||||
CALL ticketComponentUpdateSale(vOption);
|
||||
CALL catalog_componentPurge();
|
||||
|
||||
DROP TEMPORARY TABLE tmp.buyUltimate;
|
||||
DROP TEMPORARY TABLE tmp.sale;
|
||||
|
||||
END LOOP;
|
||||
CLOSE vCur;
|
||||
|
||||
END$$
|
||||
DELIMITER ;
|
|
@ -0,0 +1,23 @@
|
|||
DROP PROCEDURE IF EXISTS `vn`.`sale_calculateComponent`;
|
||||
|
||||
DELIMITER $$
|
||||
$$
|
||||
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`sale_calculateComponent`(vSale INT, vOption INT)
|
||||
proc: BEGIN
|
||||
/**
|
||||
* Crea tabla temporal para vn.sale_recalcComponent() para recalcular los componentes
|
||||
*
|
||||
* @param vSale Id de la venta
|
||||
* @param vOption indica en que componente pone el descuadre, NULL en casos habituales
|
||||
*/
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.recalculateSales;
|
||||
CREATE TEMPORARY TABLE tmp.recalculateSales
|
||||
SELECT s.id
|
||||
FROM sale s
|
||||
WHERE s.id = vSale;
|
||||
|
||||
CALL vn.sale_recalcComponent(vOption);
|
||||
|
||||
DROP TEMPORARY TABLE tmp.recalculateSales;
|
||||
END$$
|
||||
DELIMITER ;
|
File diff suppressed because one or more lines are too long
|
@ -796,25 +796,26 @@ INSERT INTO `vn`.`itemFamily`(`code`, `description`)
|
|||
('SER', 'Services'),
|
||||
('VT', 'Sales');
|
||||
|
||||
INSERT INTO `vn`.`item`(`id`, `typeFk`, `size`, `inkFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `expenceFk`, `comment`, `relevancy`, `image`, `subName`, `minPrice`, `stars`, `family`, `isFloramondo`)
|
||||
INSERT INTO `vn`.`item`(`id`, `typeFk`, `size`, `inkFk`, `stems`, `originFk`, `description`, `producerFk`, `intrastatFk`, `expenceFk`,
|
||||
`comment`, `relevancy`, `image`, `subName`, `minPrice`, `stars`, `family`, `isFloramondo`, `genericFk`)
|
||||
VALUES
|
||||
(1, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '1', NULL, 0, 1, 'VT', 0),
|
||||
(2, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '2', NULL, 0, 2, 'VT', 0),
|
||||
(3, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '3', NULL, 0, 5, 'VT', 0),
|
||||
(4, 1, 60, 'YEL', 1, 1, 'Increases block', 1, 05080000, 4751000000, NULL, 0, '4', NULL, 0, 3, 'VT', 0),
|
||||
(5, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '5', NULL, 0, 3, 'VT', 0),
|
||||
(6, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '6', NULL, 0, 4, 'VT', 0),
|
||||
(7, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '7', NULL, 0, 4, 'VT', 0),
|
||||
(8, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '8', NULL, 0, 5, 'VT', 0),
|
||||
(9, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '9', NULL, 0, 4, 'VT', 1),
|
||||
(10, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '10', NULL, 0, 4, 'VT', 0),
|
||||
(11, 1, 60, 'YEL', 1, 1, NULL, 1, 05080000, 4751000000, NULL, 0, '11', NULL, 0, 4, 'VT', 0),
|
||||
(12, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '12', NULL, 0, 3, 'VT', 0),
|
||||
(13, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '13', NULL, 0, 2, 'VT', 1),
|
||||
(14, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 4, 'VT', 1),
|
||||
(15, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'EMB', 0),
|
||||
(16, 6, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'EMB', 0),
|
||||
(71, 6, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'VT', 0);
|
||||
(1, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '1', NULL, 0, 1, 'VT', 0, NULL),
|
||||
(2, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '2', NULL, 0, 2, 'VT', 0, NULL),
|
||||
(3, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '3', NULL, 0, 5, 'VT', 0, NULL),
|
||||
(4, 1, 60, 'YEL', 1, 1, 'Increases block', 1, 05080000, 4751000000, NULL, 0, '4', NULL, 0, 3, 'VT', 0, NULL),
|
||||
(5, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '5', NULL, 0, 3, 'VT', 0, NULL),
|
||||
(6, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '6', NULL, 0, 4, 'VT', 0, NULL),
|
||||
(7, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '7', NULL, 0, 4, 'VT', 0, NULL),
|
||||
(8, 2, 70, 'YEL', 1, 1, NULL, 1, 06021010, 2000000000, NULL, 0, '8', NULL, 0, 5, 'VT', 0, NULL),
|
||||
(9, 2, 70, 'BLU', 1, 2, NULL, 1, 06021010, 2000000000, NULL, 0, '9', NULL, 0, 4, 'VT', 1, NULL),
|
||||
(10, 1, 60, 'YEL', 1, 3, NULL, 1, 05080000, 4751000000, NULL, 0, '10', NULL, 0, 4, 'VT', 0, NULL),
|
||||
(11, 1, 60, 'YEL', 1, 1, NULL, 1, 05080000, 4751000000, NULL, 0, '11', NULL, 0, 4, 'VT', 0, NULL),
|
||||
(12, 3, 30, 'RED', 1, 2, NULL, 2, 06021010, 4751000000, NULL, 0, '12', NULL, 0, 3, 'VT', 0, NULL),
|
||||
(13, 5, 30, 'RED', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '13', NULL, 0, 2, 'VT', 1, NULL),
|
||||
(14, 5, 90, 'BLU', 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 4, 'VT', 1, NULL),
|
||||
(15, 4, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'EMB', 0, NULL),
|
||||
(16, 6, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'EMB', 0, NULL),
|
||||
(71, 6, NULL, NULL, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 0, 'VT', 0, NULL);
|
||||
|
||||
-- Update the taxClass after insert of the items
|
||||
UPDATE `vn`.`itemTaxCountry` SET `taxClassFk` = 2
|
||||
|
@ -1877,6 +1878,7 @@ INSERT INTO `postgresql`.`calendar_state` (`calendar_state_id`, `type`, `rgb`, `
|
|||
(1, 'Holidays', '#FF4444', 'holiday', 0),
|
||||
(2, 'Leave of absence', '#C71585', 'absence', 0),
|
||||
(6, 'Half holiday', '#E65F00', 'halfHoliday', 0),
|
||||
(15, 'Half Paid Leave', '#5151c0', 'halfPaidLeave', 0),
|
||||
(20, 'Furlough', '#97B92F', 'furlough', 1),
|
||||
(21, 'Furlough half day', '#778899', 'halfFurlough', 0.5);
|
||||
|
||||
|
@ -2419,3 +2421,6 @@ INSERT INTO `vn`.`expeditionScan` (`id`, `expeditionFk`, `scanned`, `palletFk`)
|
|||
(10, 10, CURDATE(), 1);
|
||||
|
||||
CALL `cache`.`last_buy_refresh`(FALSE);
|
||||
|
||||
UPDATE `vn`.`item` SET `genericFk` = 9
|
||||
WHERE `id` = 2;
|
File diff suppressed because it is too large
Load Diff
|
@ -33,6 +33,7 @@ TABLES=(
|
|||
ACL
|
||||
fieldAcl
|
||||
module
|
||||
defaultViewConfig
|
||||
)
|
||||
dump_tables ${TABLES[@]}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ export async function getBrowser() {
|
|||
args,
|
||||
defaultViewport: null,
|
||||
headless: headless,
|
||||
slowMo: 5, // slow down by ms
|
||||
slowMo: 1, // slow down by ms
|
||||
// ignoreDefaultArgs: ['--disable-extensions'],
|
||||
// executablePath: '/usr/bin/google-chrome-stable',
|
||||
// executablePath: '/usr/bin/firefox-developer-edition',
|
||||
|
|
|
@ -382,6 +382,7 @@ export default {
|
|||
relevancy: 'vn-item-basic-data vn-input-number[ng-model="$ctrl.item.relevancy"]',
|
||||
origin: 'vn-autocomplete[ng-model="$ctrl.item.originFk"]',
|
||||
compression: 'vn-item-basic-data vn-input-number[ng-model="$ctrl.item.compression"]',
|
||||
generic: 'vn-autocomplete[ng-model="$ctrl.item.genericFk"]',
|
||||
isFragile: 'vn-check[ng-model="$ctrl.item.isFragile"]',
|
||||
longName: 'vn-textfield[ng-model="$ctrl.item.longName"]',
|
||||
isActiveCheckbox: 'vn-check[label="Active"]',
|
||||
|
@ -556,6 +557,7 @@ export default {
|
|||
moreMenuReserve: 'vn-item[name="reserve"]',
|
||||
moreMenuUnmarkReseved: 'vn-item[name="unreserve"]',
|
||||
moreMenuUpdateDiscount: 'vn-item[name="discount"]',
|
||||
moreMenuRecalculatePrice: 'vn-item[name="calculatePrice"]',
|
||||
moreMenuUpdateDiscountInput: 'vn-input-number[ng-model="$ctrl.edit.discount"] input',
|
||||
transferQuantityInput: '.vn-popover.shown vn-table > div > vn-tbody > vn-tr > vn-td-editable > span > text',
|
||||
transferQuantityCell: '.vn-popover.shown vn-table > div > vn-tbody > vn-tr > vn-td-editable',
|
||||
|
|
|
@ -23,15 +23,17 @@ describe('Item Edit basic data path', () => {
|
|||
it(`should edit the item basic data`, async() => {
|
||||
await page.clearInput(selectors.itemBasicData.name);
|
||||
await page.write(selectors.itemBasicData.name, 'Rose of Purity');
|
||||
await page.autocompleteSearch(selectors.itemBasicData.type, 'Anthurium');
|
||||
await page.autocompleteSearch(selectors.itemBasicData.intrastat, 'Coral y materiales similares');
|
||||
await page.clearInput(selectors.itemBasicData.relevancy);
|
||||
await page.write(selectors.itemBasicData.relevancy, '1');
|
||||
await page.autocompleteSearch(selectors.itemBasicData.origin, 'Spain');
|
||||
await page.clearInput(selectors.itemBasicData.compression);
|
||||
await page.write(selectors.itemBasicData.compression, '2');
|
||||
await page.clearInput(selectors.itemBasicData.longName);
|
||||
await page.write(selectors.itemBasicData.longName, 'RS Rose of Purity');
|
||||
await page.autocompleteSearch(selectors.itemBasicData.type, 'Anthurium');
|
||||
await page.autocompleteSearch(selectors.itemBasicData.intrastat, 'Coral y materiales similares');
|
||||
await page.autocompleteSearch(selectors.itemBasicData.origin, 'Spain');
|
||||
await page.clearInput(selectors.itemBasicData.relevancy);
|
||||
await page.write(selectors.itemBasicData.relevancy, '1');
|
||||
await page.clearInput(selectors.itemBasicData.compression);
|
||||
await page.write(selectors.itemBasicData.compression, '2');
|
||||
await page.clearInput(selectors.itemBasicData.generic);
|
||||
await page.autocompleteSearch(selectors.itemBasicData.generic, '16');
|
||||
await page.waitToClick(selectors.itemBasicData.isActiveCheckbox);
|
||||
await page.waitToClick(selectors.itemBasicData.priceInKgCheckbox);
|
||||
await page.waitToClick(selectors.itemBasicData.isFragile);
|
||||
|
@ -101,6 +103,13 @@ describe('Item Edit basic data path', () => {
|
|||
expect(result).toEqual('2');
|
||||
});
|
||||
|
||||
it(`should confirm the item generic was edited`, async() => {
|
||||
const result = await page
|
||||
.waitToGetProperty(selectors.itemBasicData.generic, 'value');
|
||||
|
||||
expect(result).toEqual('16 - Pallet');
|
||||
});
|
||||
|
||||
it(`should confirm the item long name was edited`, async() => {
|
||||
const result = await page
|
||||
.waitToGetProperty(selectors.itemBasicData.longName, 'value');
|
||||
|
|
|
@ -195,6 +195,17 @@ describe('Ticket Edit sale path', () => {
|
|||
expect(result).toContain('22.50');
|
||||
});
|
||||
|
||||
it('should recalculate price of sales', async() => {
|
||||
await page.waitToClick(selectors.ticketSales.firstSaleCheckbox);
|
||||
await page.waitToClick(selectors.ticketSales.secondSaleCheckbox);
|
||||
|
||||
await page.waitToClick(selectors.ticketSales.moreMenu);
|
||||
await page.waitToClick(selectors.ticketSales.moreMenuRecalculatePrice);
|
||||
const message = await page.waitForSnackbar();
|
||||
|
||||
expect(message.text).toContain('Data saved!');
|
||||
});
|
||||
|
||||
it('should select the third sale and create a claim of it', async() => {
|
||||
await page.waitToClick(selectors.ticketSales.thirdSaleCheckbox);
|
||||
await page.waitToClick(selectors.ticketSales.moreMenu);
|
||||
|
|
|
@ -8,7 +8,7 @@ describe('Entry observations path', () => {
|
|||
beforeAll(async() => {
|
||||
browser = await getBrowser();
|
||||
page = browser.page;
|
||||
await page.loginAndModule('developer', 'entry');
|
||||
await page.loginAndModule('buyer', 'entry');
|
||||
await page.accessToSearchResult('2');
|
||||
await page.accessToSection('entry.card.observation');
|
||||
});
|
||||
|
|
|
@ -59,13 +59,12 @@ describe('Account create and basic data path', () => {
|
|||
await page.accessToSection('account.card.roles');
|
||||
const rolesCount = await page.countElement(selectors.accountRoles.anyResult);
|
||||
|
||||
expect(rolesCount).toEqual(4);
|
||||
expect(rolesCount).toEqual(3);
|
||||
});
|
||||
|
||||
describe('Descriptor option', () => {
|
||||
describe('Edit role', () => {
|
||||
it('should edit the role using the descriptor menu', async() => {
|
||||
await page.waitForTimeout(1000); // sometimes descriptor fails to load it's functionalities without this timeout
|
||||
await page.waitToClick(selectors.accountDescriptor.menuButton);
|
||||
await page.waitToClick(selectors.accountDescriptor.changeRole);
|
||||
await page.autocompleteSearch(selectors.accountDescriptor.newRole, 'adminBoss');
|
||||
|
@ -76,7 +75,7 @@ describe('Account create and basic data path', () => {
|
|||
});
|
||||
|
||||
it('should reload the roles section to see now there are more roles', async() => {
|
||||
// when role updated the db takes a while to return the changes, without this timeout the result would have been 4
|
||||
// when role updates db takes time to return changes, without this timeout the result would have been 3
|
||||
await page.waitForTimeout(1000);
|
||||
await page.reloadSection('account.card.roles');
|
||||
const rolesCount = await page.countElement(selectors.accountRoles.anyResult);
|
||||
|
|
|
@ -8,7 +8,7 @@ describe('Account Role create and basic data path', () => {
|
|||
beforeAll(async() => {
|
||||
browser = await getBrowser();
|
||||
page = browser.page;
|
||||
await page.loginAndModule('developer', 'account');
|
||||
await page.loginAndModule('it', 'account');
|
||||
await page.accessToSection('account.role');
|
||||
});
|
||||
|
||||
|
@ -76,11 +76,11 @@ describe('Account Role create and basic data path', () => {
|
|||
expect(subrolesCount).toEqual(1);
|
||||
});
|
||||
|
||||
it('should search for the employee role group then access to the roles inheritance section then check the roles listed are the expected ones', async() => {
|
||||
it('should access the employee roles inheritance then check the roles listed are the expected ones', async() => {
|
||||
await page.accessToSearchResult('employee');
|
||||
await page.accessToSection('account.role.card.inherited');
|
||||
const rolesCount = await page.countElement(selectors.accountRoleInheritance.anyResult);
|
||||
|
||||
expect(rolesCount).toEqual(7);
|
||||
expect(rolesCount).toEqual(6);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -23,321 +23,371 @@
|
|||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-preserved:before {
|
||||
content: "\e963";
|
||||
}
|
||||
.icon-treatments:before {
|
||||
content: "\e964";
|
||||
}
|
||||
.icon-funeral:before {
|
||||
content: "\e965";
|
||||
}
|
||||
.icon-handmadeArtificial:before {
|
||||
content: "\e966";
|
||||
}
|
||||
.icon-fixedPrice:before {
|
||||
content: "\e962";
|
||||
}
|
||||
.icon-accounts:before {
|
||||
content: "\e95f";
|
||||
}
|
||||
.icon-clientConsumption:before {
|
||||
content: "\e960";
|
||||
}
|
||||
.icon-lastBuy:before {
|
||||
content: "\e961";
|
||||
}
|
||||
.icon-zone:before {
|
||||
content: "\e95d";
|
||||
}
|
||||
.icon-inventory:before {
|
||||
content: "\e95e";
|
||||
}
|
||||
.icon-wiki:before {
|
||||
content: "\e968";
|
||||
}
|
||||
.icon-attach:before {
|
||||
content: "\e96c";
|
||||
}
|
||||
.icon-zone2:before {
|
||||
content: "\e96d";
|
||||
}
|
||||
.icon-net:before {
|
||||
content: "\e95b";
|
||||
}
|
||||
.icon-anonymous:before {
|
||||
content: "\e95c";
|
||||
}
|
||||
.icon-buyrequest:before {
|
||||
content: "\e914";
|
||||
}
|
||||
.icon-entry:before {
|
||||
content: "\e959";
|
||||
}
|
||||
.icon-thermometer:before {
|
||||
content: "\e95a";
|
||||
}
|
||||
.icon-deletedTicket:before {
|
||||
content: "\e958";
|
||||
}
|
||||
.icon-fruit:before {
|
||||
content: "\e957";
|
||||
}
|
||||
.icon-deliveryprices:before {
|
||||
content: "\e956";
|
||||
}
|
||||
.icon-basketadd:before {
|
||||
content: "\e955";
|
||||
}
|
||||
.icon-catalog:before {
|
||||
content: "\e952";
|
||||
}
|
||||
.icon-agency:before {
|
||||
content: "\e910";
|
||||
}
|
||||
.icon-delivery:before {
|
||||
content: "\e94a";
|
||||
}
|
||||
.icon-wand:before {
|
||||
content: "\e954";
|
||||
}
|
||||
.icon-unavailable:before {
|
||||
content: "\e953";
|
||||
}
|
||||
.icon-buscaman:before {
|
||||
content: "\e951";
|
||||
}
|
||||
.icon-pbx:before {
|
||||
content: "\e950";
|
||||
}
|
||||
.icon-calendar:before {
|
||||
content: "\e94f";
|
||||
}
|
||||
.icon-linesplit:before {
|
||||
content: "\e945";
|
||||
}
|
||||
.icon-invoices:before {
|
||||
content: "\e91c";
|
||||
}
|
||||
.icon-pets:before {
|
||||
content: "\e94e";
|
||||
}
|
||||
.icon-100:before {
|
||||
content: "\e940";
|
||||
content: "\e976";
|
||||
}
|
||||
.icon-accessory:before {
|
||||
content: "\e90a";
|
||||
}
|
||||
.icon-actions:before {
|
||||
.icon-account:before {
|
||||
content: "\e900";
|
||||
}
|
||||
.icon-addperson:before {
|
||||
.icon-actions:before {
|
||||
content: "\e901";
|
||||
}
|
||||
.icon-albaran:before {
|
||||
.icon-addperson:before {
|
||||
content: "\e902";
|
||||
}
|
||||
.icon-apps:before {
|
||||
content: "\e948";
|
||||
}
|
||||
.icon-artificial:before {
|
||||
.icon-agency:before {
|
||||
content: "\e903";
|
||||
}
|
||||
.icon-barcode:before {
|
||||
.icon-albaran:before {
|
||||
content: "\e904";
|
||||
}
|
||||
.icon-basket:before {
|
||||
content: "\e942";
|
||||
}
|
||||
.icon-bin:before {
|
||||
.icon-anonymous:before {
|
||||
content: "\e905";
|
||||
}
|
||||
.icon-botanical:before {
|
||||
.icon-apps:before {
|
||||
content: "\e906";
|
||||
}
|
||||
.icon-bucket:before {
|
||||
.icon-artificial:before {
|
||||
content: "\e907";
|
||||
}
|
||||
.icon-claims:before {
|
||||
.icon-attach:before {
|
||||
content: "\e908";
|
||||
}
|
||||
.icon-clone:before {
|
||||
.icon-barcode:before {
|
||||
content: "\e909";
|
||||
}
|
||||
.icon-columnadd:before {
|
||||
content: "\e944";
|
||||
.icon-basket:before {
|
||||
content: "\e90a";
|
||||
}
|
||||
.icon-columndelete:before {
|
||||
content: "\e90f";
|
||||
}
|
||||
.icon-components:before {
|
||||
.icon-basketadd:before {
|
||||
content: "\e90b";
|
||||
}
|
||||
.icon-consignatarios:before {
|
||||
content: "\e90d";
|
||||
}
|
||||
.icon-control:before {
|
||||
content: "\e93f";
|
||||
}
|
||||
.icon-credit:before {
|
||||
content: "\e90e";
|
||||
}
|
||||
.icon-details:before {
|
||||
content: "\e911";
|
||||
}
|
||||
.icon-disabled:before {
|
||||
content: "\e91b";
|
||||
}
|
||||
.icon-doc:before {
|
||||
content: "\e913";
|
||||
}
|
||||
.icon-exit:before {
|
||||
content: "\e947";
|
||||
}
|
||||
.icon-eye:before {
|
||||
content: "\e915";
|
||||
}
|
||||
.icon-fiscal:before {
|
||||
content: "\e912";
|
||||
}
|
||||
.icon-flower:before {
|
||||
content: "\e916";
|
||||
}
|
||||
.icon-frozen:before {
|
||||
content: "\e917";
|
||||
}
|
||||
.icon-greenery:before {
|
||||
content: "\e93c";
|
||||
}
|
||||
.icon-greuge:before {
|
||||
content: "\e918";
|
||||
}
|
||||
.icon-grid:before {
|
||||
content: "\e919";
|
||||
}
|
||||
.icon-handmade:before {
|
||||
.icon-bin:before {
|
||||
content: "\e90c";
|
||||
}
|
||||
.icon-history:before {
|
||||
.icon-botanical:before {
|
||||
content: "\e90d";
|
||||
}
|
||||
.icon-bucket:before {
|
||||
content: "\e90e";
|
||||
}
|
||||
.icon-buscaman:before {
|
||||
content: "\e90f";
|
||||
}
|
||||
.icon-buyrequest:before {
|
||||
content: "\e910";
|
||||
}
|
||||
.icon-calc_volum .path1:before {
|
||||
content: "\e911";
|
||||
color: rgb(0, 0, 0);
|
||||
}
|
||||
.icon-calc_volum .path2:before {
|
||||
content: "\e912";
|
||||
margin-left: -1em;
|
||||
color: rgb(0, 0, 0);
|
||||
}
|
||||
.icon-calc_volum .path3:before {
|
||||
content: "\e913";
|
||||
margin-left: -1em;
|
||||
color: rgb(0, 0, 0);
|
||||
}
|
||||
.icon-calc_volum .path4:before {
|
||||
content: "\e914";
|
||||
margin-left: -1em;
|
||||
color: rgb(0, 0, 0);
|
||||
}
|
||||
.icon-calc_volum .path5:before {
|
||||
content: "\e915";
|
||||
margin-left: -1em;
|
||||
color: rgb(0, 0, 0);
|
||||
}
|
||||
.icon-calc_volum .path6:before {
|
||||
content: "\e916";
|
||||
margin-left: -1em;
|
||||
color: rgb(255, 255, 255);
|
||||
}
|
||||
.icon-calendar:before {
|
||||
content: "\e917";
|
||||
}
|
||||
.icon-catalog:before {
|
||||
content: "\e918";
|
||||
}
|
||||
.icon-claims:before {
|
||||
content: "\e919";
|
||||
}
|
||||
.icon-client:before {
|
||||
content: "\e91a";
|
||||
}
|
||||
.icon-info:before {
|
||||
content: "\e949";
|
||||
.icon-clone:before {
|
||||
content: "\e91b";
|
||||
}
|
||||
.icon-item:before {
|
||||
content: "\e941";
|
||||
.icon-columnadd:before {
|
||||
content: "\e91c";
|
||||
}
|
||||
.icon-languaje:before {
|
||||
.icon-columndelete:before {
|
||||
content: "\e91d";
|
||||
}
|
||||
.icon-linedelete:before {
|
||||
content: "\e946";
|
||||
}
|
||||
.icon-lines:before {
|
||||
.icon-accessory:before {
|
||||
content: "\e91e";
|
||||
}
|
||||
.icon-linesprepaired:before {
|
||||
content: "\e94b";
|
||||
}
|
||||
.icon-logout:before {
|
||||
.icon-components:before {
|
||||
content: "\e91f";
|
||||
}
|
||||
.icon-mana:before {
|
||||
.icon-handmade:before {
|
||||
content: "\e920";
|
||||
}
|
||||
.icon-mandatory:before {
|
||||
.icon-consignatarios:before {
|
||||
content: "\e921";
|
||||
}
|
||||
.icon-niche:before {
|
||||
.icon-control:before {
|
||||
content: "\e922";
|
||||
}
|
||||
.icon-no036:before {
|
||||
.icon-credit:before {
|
||||
content: "\e923";
|
||||
}
|
||||
.icon-notes:before {
|
||||
.icon-deletedTicketCross:before {
|
||||
content: "\e924";
|
||||
}
|
||||
.icon-noweb:before {
|
||||
.icon-deleteline:before {
|
||||
content: "\e925";
|
||||
}
|
||||
.icon-onlinepayment:before {
|
||||
.icon-delivery:before {
|
||||
content: "\e926";
|
||||
}
|
||||
.icon-package:before {
|
||||
.icon-deliveryprices:before {
|
||||
content: "\e927";
|
||||
}
|
||||
.icon-payment:before {
|
||||
.icon-details:before {
|
||||
content: "\e928";
|
||||
}
|
||||
.icon-person:before {
|
||||
.icon-dfiscales:before {
|
||||
content: "\e929";
|
||||
}
|
||||
.icon-photo:before {
|
||||
.icon-doc:before {
|
||||
content: "\e92a";
|
||||
}
|
||||
.icon-plant:before {
|
||||
.icon-entry:before {
|
||||
content: "\e92b";
|
||||
}
|
||||
.icon-recovery:before {
|
||||
content: "\e92d";
|
||||
}
|
||||
.icon-regentry:before {
|
||||
content: "\e92e";
|
||||
}
|
||||
.icon-reserve:before {
|
||||
content: "\e92f";
|
||||
}
|
||||
.icon-revision:before {
|
||||
content: "\e94c";
|
||||
}
|
||||
.icon-risk:before {
|
||||
content: "\e930";
|
||||
}
|
||||
.icon-services:before {
|
||||
content: "\e94d";
|
||||
}
|
||||
.icon-settings:before {
|
||||
content: "\e931";
|
||||
}
|
||||
.icon-sms:before {
|
||||
content: "\e932";
|
||||
}
|
||||
.icon-solclaim:before {
|
||||
content: "\e933";
|
||||
}
|
||||
.icon-solunion:before {
|
||||
content: "\e934";
|
||||
}
|
||||
.icon-splur:before {
|
||||
content: "\e935";
|
||||
}
|
||||
.icon-stowaway:before {
|
||||
.icon-exit:before {
|
||||
content: "\e92c";
|
||||
}
|
||||
.icon-supplier:before {
|
||||
.icon-eye:before {
|
||||
content: "\e92d";
|
||||
}
|
||||
.icon-fixedPrice:before {
|
||||
content: "\e92e";
|
||||
}
|
||||
.icon-flower:before {
|
||||
content: "\e92f";
|
||||
}
|
||||
.icon-frozen:before {
|
||||
content: "\e930";
|
||||
}
|
||||
.icon-fruit:before {
|
||||
content: "\e931";
|
||||
}
|
||||
.icon-funeral:before {
|
||||
content: "\e932";
|
||||
}
|
||||
.icon-greuge:before {
|
||||
content: "\e933";
|
||||
}
|
||||
.icon-grid:before {
|
||||
content: "\e934";
|
||||
}
|
||||
.icon-handmadeArtificial:before {
|
||||
content: "\e935";
|
||||
}
|
||||
.icon-headercol:before {
|
||||
content: "\e936";
|
||||
}
|
||||
.icon-tags:before {
|
||||
.icon-history:before {
|
||||
content: "\e937";
|
||||
}
|
||||
.icon-tax:before {
|
||||
.icon-disabled:before {
|
||||
content: "\e938";
|
||||
}
|
||||
.icon-ticket:before {
|
||||
.icon-info:before {
|
||||
content: "\e939";
|
||||
}
|
||||
.icon-traceability:before {
|
||||
.icon-inventory:before {
|
||||
content: "\e93a";
|
||||
}
|
||||
.icon-transaction:before {
|
||||
.icon-invoice:before {
|
||||
content: "\e93b";
|
||||
}
|
||||
.icon-volume:before {
|
||||
.icon-invoice-in:before {
|
||||
content: "\e93c";
|
||||
}
|
||||
.icon-invoice-in-create:before {
|
||||
content: "\e93d";
|
||||
}
|
||||
.icon-web:before {
|
||||
.icon-invoice-out:before {
|
||||
content: "\e93e";
|
||||
}
|
||||
.icon-worker:before {
|
||||
.icon-item:before {
|
||||
content: "\e93f";
|
||||
}
|
||||
.icon-languaje:before {
|
||||
content: "\e940";
|
||||
}
|
||||
.icon-lines:before {
|
||||
content: "\e941";
|
||||
}
|
||||
.icon-linesprepaired:before {
|
||||
content: "\e942";
|
||||
}
|
||||
.icon-logout:before {
|
||||
content: "\e943";
|
||||
}
|
||||
.icon-mana:before {
|
||||
content: "\e944";
|
||||
}
|
||||
.icon-mandatory:before {
|
||||
content: "\e945";
|
||||
}
|
||||
.icon-net:before {
|
||||
content: "\e946";
|
||||
}
|
||||
.icon-niche:before {
|
||||
content: "\e947";
|
||||
}
|
||||
.icon-no036:before {
|
||||
content: "\e948";
|
||||
}
|
||||
.icon-notes:before {
|
||||
content: "\e949";
|
||||
}
|
||||
.icon-noweb:before {
|
||||
content: "\e94a";
|
||||
}
|
||||
.icon-onlinepayment:before {
|
||||
content: "\e94b";
|
||||
}
|
||||
.icon-package:before {
|
||||
content: "\e94c";
|
||||
}
|
||||
.icon-payment:before {
|
||||
content: "\e94d";
|
||||
}
|
||||
.icon-pbx:before {
|
||||
content: "\e94e";
|
||||
}
|
||||
.icon-Person:before {
|
||||
content: "\e94f";
|
||||
}
|
||||
.icon-pets:before {
|
||||
content: "\e950";
|
||||
}
|
||||
.icon-photo:before {
|
||||
content: "\e951";
|
||||
}
|
||||
.icon-plant:before {
|
||||
content: "\e952";
|
||||
}
|
||||
.icon-stowaway:before {
|
||||
content: "\e953";
|
||||
}
|
||||
.icon-preserved:before {
|
||||
content: "\e954";
|
||||
}
|
||||
.icon-recovery:before {
|
||||
content: "\e955";
|
||||
}
|
||||
.icon-regentry:before {
|
||||
content: "\e956";
|
||||
}
|
||||
.icon-reserve:before {
|
||||
content: "\e957";
|
||||
}
|
||||
.icon-revision:before {
|
||||
content: "\e958";
|
||||
}
|
||||
.icon-risk:before {
|
||||
content: "\e959";
|
||||
}
|
||||
.icon-services:before {
|
||||
content: "\e95a";
|
||||
}
|
||||
.icon-settings:before {
|
||||
content: "\e95b";
|
||||
}
|
||||
.icon-shipment-01 .path1:before {
|
||||
content: "\e95c";
|
||||
color: rgb(225, 225, 225);
|
||||
}
|
||||
.icon-shipment-01 .path2:before {
|
||||
content: "\e95d";
|
||||
margin-left: -1em;
|
||||
color: rgb(0, 0, 0);
|
||||
}
|
||||
.icon-sign:before {
|
||||
content: "\e95e";
|
||||
}
|
||||
.icon-sms:before {
|
||||
content: "\e95f";
|
||||
}
|
||||
.icon-solclaim:before {
|
||||
content: "\e960";
|
||||
}
|
||||
.icon-solunion:before {
|
||||
content: "\e961";
|
||||
}
|
||||
.icon-splitline:before {
|
||||
content: "\e962";
|
||||
}
|
||||
.icon-splur:before {
|
||||
content: "\e963";
|
||||
}
|
||||
.icon-supplier:before {
|
||||
content: "\e965";
|
||||
}
|
||||
.icon-supplierfalse:before {
|
||||
content: "\e966";
|
||||
}
|
||||
.icon-tags:before {
|
||||
content: "\e967";
|
||||
}
|
||||
.icon-tax:before {
|
||||
content: "\e968";
|
||||
}
|
||||
.icon-thermometer:before {
|
||||
content: "\e969";
|
||||
}
|
||||
.icon-ticket:before {
|
||||
content: "\e96a";
|
||||
}
|
||||
.icon-traceability:before {
|
||||
content: "\e96b";
|
||||
}
|
||||
.icon-transaction:before {
|
||||
content: "\e96c";
|
||||
}
|
||||
.icon-treatments:before {
|
||||
content: "\e96d";
|
||||
}
|
||||
.icon-unavailable:before {
|
||||
content: "\e96e";
|
||||
}
|
||||
.icon-greenery:before {
|
||||
content: "\e96f";
|
||||
}
|
||||
.icon-volume:before {
|
||||
content: "\e970";
|
||||
}
|
||||
.icon-wand:before {
|
||||
content: "\e971";
|
||||
}
|
||||
.icon-web:before {
|
||||
content: "\e972";
|
||||
}
|
||||
.icon-wiki:before {
|
||||
content: "\e973";
|
||||
}
|
||||
.icon-worker:before {
|
||||
content: "\e974";
|
||||
}
|
||||
.icon-zone:before {
|
||||
content: "\e975";
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 136 KiB After Width: | Height: | Size: 145 KiB |
Binary file not shown.
Binary file not shown.
|
@ -214,5 +214,7 @@
|
|||
"You can't change the credit set to zero from a manager": "No puedes cambiar el cŕedito establecido a cero por un gerente",
|
||||
"The PDF document does not exists": "El documento PDF no existe. Prueba a regenerarlo desde la opción 'Regenerar PDF factura'",
|
||||
"The type of business must be filled in basic data": "El tipo de negocio debe estar rellenado en datos básicos",
|
||||
"You can't create a claim from a ticket delivered more than seven days ago": "No puedes crear una reclamación de un ticket entregado hace más de siete días"
|
||||
"You can't create a claim from a ticket delivered more than seven days ago": "No puedes crear una reclamación de un ticket entregado hace más de siete días",
|
||||
"The worker has hours recorded that day": "El trabajador tiene horas fichadas ese día",
|
||||
"The worker has a marked absence that day": "El trabajador tiene marcada una ausencia ese día"
|
||||
}
|
|
@ -29,5 +29,11 @@
|
|||
"foreignKey": "mailAlias",
|
||||
"property": "id"
|
||||
}
|
||||
}
|
||||
},
|
||||
"acls": [{
|
||||
"accessType": "READ",
|
||||
"principalType": "ROLE",
|
||||
"principalId": "$everyone",
|
||||
"permission": "ALLOW"
|
||||
}]
|
||||
}
|
||||
|
|
|
@ -5,14 +5,16 @@
|
|||
<vn-item
|
||||
ng-click="deleteUser.show()"
|
||||
name="deleteUser"
|
||||
vn-acl="developer"
|
||||
vn-acl="it"
|
||||
vn-acl-action="remove"
|
||||
translate>
|
||||
Delete
|
||||
</vn-item>
|
||||
<vn-item
|
||||
ng-click="$ctrl.onChangeRole()"
|
||||
name="changeRole"
|
||||
vn-acl="developer"
|
||||
vn-acl="hr"
|
||||
vn-acl-action="remove"
|
||||
translate>
|
||||
Change role
|
||||
</vn-item>
|
||||
|
@ -20,13 +22,16 @@
|
|||
ng-if="::$root.user.id == $ctrl.id"
|
||||
ng-click="$ctrl.onChangePassClick(true)"
|
||||
name="changePassword"
|
||||
vn-acl="hr"
|
||||
vn-acl-action="remove"
|
||||
translate>
|
||||
Change password
|
||||
</vn-item>
|
||||
<vn-item
|
||||
ng-click="$ctrl.onChangePassClick(false)"
|
||||
name="setPassword"
|
||||
vn-acl="developer"
|
||||
vn-acl="hr"
|
||||
vn-acl-action="remove"
|
||||
translate>
|
||||
Set password
|
||||
</vn-item>
|
||||
|
@ -34,7 +39,8 @@
|
|||
ng-if="!$ctrl.hasAccount"
|
||||
ng-click="enableAccount.show()"
|
||||
name="enableAccount"
|
||||
vn-acl="developer"
|
||||
vn-acl="it"
|
||||
vn-acl-action="remove"
|
||||
translate>
|
||||
Enable account
|
||||
</vn-item>
|
||||
|
@ -42,7 +48,8 @@
|
|||
ng-if="$ctrl.hasAccount"
|
||||
ng-click="disableAccount.show()"
|
||||
name="disableAccount"
|
||||
vn-acl="developer"
|
||||
vn-acl="it"
|
||||
vn-acl-action="remove"
|
||||
translate>
|
||||
Disable account
|
||||
</vn-item>
|
||||
|
@ -50,7 +57,8 @@
|
|||
ng-if="!$ctrl.user.active"
|
||||
ng-click="activateUser.show()"
|
||||
name="activateUser"
|
||||
vn-acl="developer"
|
||||
vn-acl="hr"
|
||||
vn-acl-action="remove"
|
||||
translate>
|
||||
Activate user
|
||||
</vn-item>
|
||||
|
@ -58,7 +66,8 @@
|
|||
ng-if="$ctrl.user.active"
|
||||
ng-click="deactivateUser.show()"
|
||||
name="deactivateUser"
|
||||
vn-acl="developer"
|
||||
vn-acl="hr"
|
||||
vn-acl-action="remove"
|
||||
translate>
|
||||
Deactivate user
|
||||
</vn-item>
|
||||
|
|
|
@ -36,9 +36,12 @@
|
|||
<vn-popup vn-id="summary">
|
||||
<vn-user-summary user="$ctrl.selectedUser"></vn-user-summary>
|
||||
</vn-popup>
|
||||
<a ui-sref="account.create"
|
||||
<a
|
||||
fixed-bottom-right
|
||||
ui-sref="account.create"
|
||||
vn-tooltip="New user"
|
||||
vn-bind="+"
|
||||
fixed-bottom-right>
|
||||
vn-acl="it"
|
||||
vn-acl-action="remove">
|
||||
<vn-float-button icon="add"></vn-float-button>
|
||||
</a>
|
|
@ -35,7 +35,7 @@
|
|||
ui-sref-opts="{inherit: false}"
|
||||
vn-tooltip="New role"
|
||||
vn-bind="+"
|
||||
vn-acl="developer"
|
||||
vn-acl="it"
|
||||
vn-acl-action="remove"
|
||||
fixed-bottom-right>
|
||||
<vn-float-button icon="add"></vn-float-button>
|
||||
|
|
|
@ -41,24 +41,29 @@
|
|||
"component": "vn-user",
|
||||
"description": "Users",
|
||||
"abstract": true
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"url": "/index?q",
|
||||
"state": "account.index",
|
||||
"component": "vn-user-index",
|
||||
"description": "Users",
|
||||
"acl": ["hr"]
|
||||
}, {
|
||||
"acl": ["marketing", "hr"]
|
||||
},
|
||||
{
|
||||
"url": "/create",
|
||||
"state": "account.create",
|
||||
"component": "vn-user-create",
|
||||
"description": "New user"
|
||||
}, {
|
||||
"description": "New user",
|
||||
"acl": ["it"]
|
||||
},
|
||||
{
|
||||
"url": "/:id",
|
||||
"state": "account.card",
|
||||
"component": "vn-user-card",
|
||||
"abstract": true,
|
||||
"description": "Detail"
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"url": "/summary",
|
||||
"state": "account.card.summary",
|
||||
"component": "vn-user-summary",
|
||||
|
@ -66,88 +71,110 @@
|
|||
"params": {
|
||||
"user": "$ctrl.user"
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"url": "/basic-data",
|
||||
"state": "account.card.basicData",
|
||||
"component": "vn-user-basic-data",
|
||||
"description": "Basic data"
|
||||
}, {
|
||||
"description": "Basic data",
|
||||
"acl": ["hr"]
|
||||
},
|
||||
{
|
||||
"url": "/roles",
|
||||
"state": "account.card.roles",
|
||||
"component": "vn-user-roles",
|
||||
"description": "Inherited roles"
|
||||
}, {
|
||||
"description": "Inherited roles",
|
||||
"acl": ["it"]
|
||||
},
|
||||
{
|
||||
"url": "/mail-forwarding",
|
||||
"state": "account.card.mailForwarding",
|
||||
"component": "vn-user-mail-forwarding",
|
||||
"description": "Mail forwarding"
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"url": "/aliases",
|
||||
"state": "account.card.aliases",
|
||||
"component": "vn-user-aliases",
|
||||
"description": "Mail aliases"
|
||||
}, {
|
||||
"description": "Mail aliases",
|
||||
"acl": ["marketing", "hr"]
|
||||
},
|
||||
{
|
||||
"url": "/role?q",
|
||||
"state": "account.role",
|
||||
"component": "vn-role",
|
||||
"description": "Roles"
|
||||
}, {
|
||||
"description": "Roles",
|
||||
"acl": ["it"]
|
||||
},
|
||||
{
|
||||
"url": "/create",
|
||||
"state": "account.role.create",
|
||||
"component": "vn-role-create",
|
||||
"description": "New role"
|
||||
}, {
|
||||
"description": "New role",
|
||||
"acl": ["it"]
|
||||
},
|
||||
{
|
||||
"url": "/:id",
|
||||
"state": "account.role.card",
|
||||
"component": "vn-role-card",
|
||||
"abstract": true,
|
||||
"description": "Detail"
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"url": "/summary",
|
||||
"state": "account.role.card.summary",
|
||||
"component": "vn-role-summary",
|
||||
"description": "Summary",
|
||||
"params": {
|
||||
"role": "$ctrl.role"
|
||||
}
|
||||
}, {
|
||||
},
|
||||
"acl": ["it"]
|
||||
},
|
||||
{
|
||||
"url": "/basic-data",
|
||||
"state": "account.role.card.basicData",
|
||||
"component": "vn-role-basic-data",
|
||||
"description": "Basic data",
|
||||
"acl": ["developer"],
|
||||
"params": {
|
||||
"role": "$ctrl.role"
|
||||
}
|
||||
}, {
|
||||
},
|
||||
"acl": ["it"]
|
||||
},
|
||||
{
|
||||
"url": "/subroles",
|
||||
"state": "account.role.card.subroles",
|
||||
"component": "vn-role-subroles",
|
||||
"acl": ["developer"],
|
||||
"description": "Subroles"
|
||||
}, {
|
||||
"description": "Subroles",
|
||||
"acl": ["it"]
|
||||
},
|
||||
{
|
||||
"url": "/inherited",
|
||||
"state": "account.role.card.inherited",
|
||||
"component": "vn-role-inherited",
|
||||
"description": "Inherited roles"
|
||||
}, {
|
||||
"description": "Inherited roles",
|
||||
"acl": ["it"]
|
||||
},
|
||||
{
|
||||
"url": "/alias?q",
|
||||
"state": "account.alias",
|
||||
"component": "vn-alias",
|
||||
"description": "Mail aliases",
|
||||
"acl": ["developer"]
|
||||
}, {
|
||||
"acl": ["marketing"]
|
||||
},
|
||||
{
|
||||
"url": "/create",
|
||||
"state": "account.alias.create",
|
||||
"component": "vn-alias-create",
|
||||
"description": "New alias"
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"url": "/:id",
|
||||
"state": "account.alias.card",
|
||||
"component": "vn-alias-card",
|
||||
"abstract": true,
|
||||
"description": "Detail"
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"url": "/summary",
|
||||
"state": "account.alias.card.summary",
|
||||
"component": "vn-alias-summary",
|
||||
|
@ -155,7 +182,8 @@
|
|||
"params": {
|
||||
"alias": "$ctrl.alias"
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"url": "/basic-data",
|
||||
"state": "account.alias.card.basicData",
|
||||
"component": "vn-alias-basic-data",
|
||||
|
@ -163,50 +191,62 @@
|
|||
"params": {
|
||||
"alias": "$ctrl.alias"
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"url": "/users",
|
||||
"state": "account.alias.card.users",
|
||||
"component": "vn-alias-users",
|
||||
"description": "Users"
|
||||
}, {
|
||||
"description": "Users",
|
||||
"acl": ["it"]
|
||||
},
|
||||
{
|
||||
"url": "/accounts",
|
||||
"state": "account.accounts",
|
||||
"component": "vn-account-accounts",
|
||||
"description": "Accounts",
|
||||
"acl": ["developer"]
|
||||
}, {
|
||||
"acl": ["sysadmin"]
|
||||
},
|
||||
{
|
||||
"url": "/ldap",
|
||||
"state": "account.ldap",
|
||||
"component": "vn-account-ldap",
|
||||
"description": "LDAP",
|
||||
"acl": ["developer"]
|
||||
}, {
|
||||
"acl": ["sysadmin"]
|
||||
},
|
||||
{
|
||||
"url": "/samba",
|
||||
"state": "account.samba",
|
||||
"component": "vn-account-samba",
|
||||
"description": "Samba",
|
||||
"acl": ["developer"]
|
||||
}, {
|
||||
"acl": ["sysadmin"]
|
||||
},
|
||||
{
|
||||
"url": "/acl?q",
|
||||
"state": "account.acl",
|
||||
"component": "vn-acl-component",
|
||||
"description": "ACLs",
|
||||
"acl": ["developer"]
|
||||
}, {
|
||||
},
|
||||
{
|
||||
"url": "/create",
|
||||
"state": "account.acl.create",
|
||||
"component": "vn-acl-create",
|
||||
"description": "New ACL"
|
||||
}, {
|
||||
"description": "New ACL",
|
||||
"acl": ["developer"]
|
||||
},
|
||||
{
|
||||
"url": "/:id/edit",
|
||||
"state": "account.acl.edit",
|
||||
"component": "vn-acl-create",
|
||||
"description": "Edit ACL"
|
||||
}, {
|
||||
"description": "Edit ACL",
|
||||
"acl": ["developer"]
|
||||
},
|
||||
{
|
||||
"url": "/connections",
|
||||
"state": "account.connections",
|
||||
"component": "vn-connections",
|
||||
"description": "Connections"
|
||||
"description": "Connections",
|
||||
"acl": ["developer"]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -82,7 +82,7 @@
|
|||
<vn-quick-link
|
||||
tooltip="Client invoices list"
|
||||
state="['invoiceOut.index', {q: $ctrl.filter}]"
|
||||
icon="icon-invoices">
|
||||
icon="icon-invoice">
|
||||
</vn-quick-link>
|
||||
</div>
|
||||
<div ng-transclude="btnThree">
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
{"state": "client.card.note.index", "icon": "insert_drive_file"},
|
||||
{"state": "client.card.credit.index", "icon": "credit_card"},
|
||||
{"state": "client.card.greuge.index", "icon": "work"},
|
||||
{"state": "client.card.balance.index", "icon": "icon-invoices"},
|
||||
{"state": "client.card.balance.index", "icon": "icon-invoice"},
|
||||
{"state": "client.card.recovery.index", "icon": "icon-recovery"},
|
||||
{"state": "client.card.webAccess", "icon": "cloud"},
|
||||
{"state": "client.card.log", "icon": "history"},
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
url="Tickets"
|
||||
link="{clientFk: $ctrl.client.id}"
|
||||
filter="::$ctrl.ticketFilter"
|
||||
limit="5"
|
||||
limit="10"
|
||||
data="tickets"
|
||||
order="shipped DESC, id">
|
||||
</vn-crud-model>
|
||||
|
@ -287,7 +287,7 @@
|
|||
<vn-horizontal>
|
||||
<vn-one>
|
||||
<h4 translate>Latest tickets</h4>
|
||||
<vn-table model="ticketsModel" class="scrollable sm">
|
||||
<vn-table model="ticketsModel">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th field="id" number>Id</vn-th>
|
||||
|
|
|
@ -113,7 +113,6 @@
|
|||
|
||||
<vn-dialog
|
||||
vn-id="filterDialog"
|
||||
on-accept="$ctrl.addTime()"
|
||||
message="Filter item">
|
||||
<tpl-body class="itemFilter">
|
||||
<vn-horizontal>
|
||||
|
|
|
@ -133,7 +133,7 @@ class Controller extends Section {
|
|||
case 'producerFk':
|
||||
case 'typeFk':
|
||||
case 'size':
|
||||
case 'ink':
|
||||
case 'inkFk':
|
||||
where[key] = value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
</div>
|
||||
<div ng-transclude="btnThree">
|
||||
<vn-quick-link tooltip="Invoice list" state="['invoiceIn.index', {q: $ctrl.invoiceInFilter}]"
|
||||
icon="icon-invoiceIn">
|
||||
icon="icon-invoice-in">
|
||||
</vn-quick-link>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"module": "invoiceIn",
|
||||
"name": "Invoices in",
|
||||
"icon": "icon-invoiceIn",
|
||||
"icon": "icon-invoice-in",
|
||||
"validations": true,
|
||||
"dependencies": [
|
||||
"worker",
|
||||
|
@ -11,7 +11,7 @@
|
|||
"main": [
|
||||
{
|
||||
"state": "invoiceIn.index",
|
||||
"icon": "icon-invoiceIn"
|
||||
"icon": "icon-invoice-in"
|
||||
}
|
||||
],
|
||||
"card": [
|
||||
|
|
|
@ -76,7 +76,7 @@
|
|||
ng-click="$ctrl.showExportationLetter()"
|
||||
ng-show="$ctrl.invoiceOut.serial == 'E'"
|
||||
translate>
|
||||
Show CIES letter
|
||||
Show CITES letter
|
||||
</vn-item>
|
||||
</vn-list>
|
||||
</vn-menu>
|
||||
|
|
|
@ -6,7 +6,7 @@ Delete Invoice: Eliminar factura
|
|||
Clone Invoice: Clonar factura
|
||||
Book invoice: Asentar factura
|
||||
Generate PDF invoice: Generar PDF factura
|
||||
Show CIES letter: Ver carta CIES
|
||||
Show CITES letter: Ver carta CITES
|
||||
InvoiceOut deleted: Factura eliminada
|
||||
Are you sure you want to delete this invoice?: Estas seguro de eliminar esta factura?
|
||||
Are you sure you want to clone this invoice?: Estas seguro de clonar esta factura?
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"module": "invoiceOut",
|
||||
"name": "Invoices out",
|
||||
"icon": "icon-invoices",
|
||||
"icon": "icon-invoice-out",
|
||||
"validations" : true,
|
||||
"dependencies": ["worker", "client", "ticket"],
|
||||
"menus": {
|
||||
"main": [
|
||||
{"state": "invoiceOut.index", "icon": "icon-invoices"}
|
||||
{"state": "invoiceOut.index", "icon": "icon-invoice-out"}
|
||||
]
|
||||
},
|
||||
"routes": [
|
||||
|
|
|
@ -176,6 +176,11 @@
|
|||
"model": "Expense",
|
||||
"foreignKey": "expenseFk"
|
||||
},
|
||||
"generic": {
|
||||
"type": "belongsTo",
|
||||
"model": "Item",
|
||||
"foreignKey": "genericFk"
|
||||
},
|
||||
"tags": {
|
||||
"type": "hasMany",
|
||||
"model": "ItemTag",
|
||||
|
|
|
@ -137,6 +137,29 @@
|
|||
ng-model="$ctrl.item.compression"
|
||||
rule>
|
||||
</vn-input-number>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
label="Generic"
|
||||
url="Items/withName"
|
||||
ng-model="$ctrl.item.genericFk"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
search-function="$ctrl.itemSearchFunc($search)"
|
||||
order="id DESC"
|
||||
tabindex="1">
|
||||
<tpl-item>
|
||||
{{::id}} - {{::name}}
|
||||
</tpl-item>
|
||||
<append>
|
||||
<vn-icon-button
|
||||
icon="filter_alt"
|
||||
vn-click-stop="$ctrl.showFilterDialog($ctrl.item)"
|
||||
vn-tooltip="Filter...">
|
||||
</vn-icon-button>
|
||||
</append>
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textarea
|
||||
vn-one
|
||||
label="Description"
|
||||
|
@ -203,3 +226,92 @@
|
|||
<button response="accept" translate>Create</button>
|
||||
</tpl-buttons>
|
||||
</vn-dialog>
|
||||
|
||||
<!-- Filter item dialog -->
|
||||
<vn-dialog
|
||||
vn-id="filterDialog"
|
||||
message="Filter item">
|
||||
<tpl-body class="itemFilter">
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
label="Name"
|
||||
ng-model="$ctrl.itemFilterParams.name"
|
||||
vn-focus>
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
label="Size"
|
||||
ng-model="$ctrl.itemFilterParams.size">
|
||||
</vn-textfield>
|
||||
<vn-autocomplete
|
||||
label="Producer"
|
||||
ng-model="$ctrl.itemFilterParams.producerFk"
|
||||
url="Producers"
|
||||
show-field="name"
|
||||
value-field="id">
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete
|
||||
label="Type"
|
||||
ng-model="$ctrl.itemFilterParams.typeFk"
|
||||
url="ItemTypes"
|
||||
show-field="name"
|
||||
value-field="id">
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete
|
||||
label="Color"
|
||||
ng-model="$ctrl.itemFilterParams.inkFk"
|
||||
url="Inks"
|
||||
show-field="name"
|
||||
value-field="id">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal class="vn-mb-md">
|
||||
<vn-button vn-none
|
||||
label="Search"
|
||||
ng-click="$ctrl.filter()">
|
||||
</vn-button>
|
||||
</vn-horizontal>
|
||||
<vn-crud-model
|
||||
vn-id="itemsModel"
|
||||
url="Items/withName"
|
||||
filter="$ctrl.itemFilter"
|
||||
data="items"
|
||||
limit="10">
|
||||
</vn-crud-model>
|
||||
<vn-data-viewer
|
||||
model="itemsModel"
|
||||
class="vn-w-lg">
|
||||
<vn-table class="scrollable">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th shrink>ID</vn-th>
|
||||
<vn-th expand>Item</vn-th>
|
||||
<vn-th number>Size</vn-th>
|
||||
<vn-th expand>Producer</vn-th>
|
||||
<vn-th>Color</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
<a ng-repeat="item in items"
|
||||
class="clickable vn-tr search-result"
|
||||
ng-click="$ctrl.selectItem(item.id)">
|
||||
<vn-td shrink>
|
||||
<span
|
||||
ng-click="itemDescriptor.show($event, item.id)"
|
||||
class="link">
|
||||
{{::item.id}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td expand>{{::item.name}}</vn-td>
|
||||
<vn-td number>{{::item.size}}</vn-td>
|
||||
<vn-td expand>{{::item.producer.name}}</vn-td>
|
||||
<vn-td>{{::item.ink.name}}</vn-td>
|
||||
</a>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-data-viewer>
|
||||
<vn-item-descriptor-popover
|
||||
vn-id="item-descriptor"
|
||||
warehouse-fk="$ctrl.vnConfig.warehouseFk">
|
||||
</vn-item-descriptor-popover>
|
||||
</tpl-body>
|
||||
</vn-dialog>
|
|
@ -17,6 +17,65 @@ class Controller extends Section {
|
|||
return this.$http.patch(query, this.newIntrastat)
|
||||
.then(res => this.item.intrastatFk = res.data.id);
|
||||
}
|
||||
|
||||
itemSearchFunc($search) {
|
||||
return /^\d+$/.test($search)
|
||||
? {id: $search}
|
||||
: {name: {like: '%' + $search + '%'}};
|
||||
}
|
||||
|
||||
showFilterDialog(item) {
|
||||
this.activeItem = item;
|
||||
this.itemFilterParams = {};
|
||||
this.itemFilter = {
|
||||
include: [
|
||||
{
|
||||
relation: 'producer',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
},
|
||||
{
|
||||
relation: 'ink',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
this.$.filterDialog.show();
|
||||
}
|
||||
|
||||
selectItem(id) {
|
||||
this.activeItem['genericFk'] = id;
|
||||
this.$.filterDialog.hide();
|
||||
}
|
||||
|
||||
filter() {
|
||||
const filter = this.itemFilter;
|
||||
const params = this.itemFilterParams;
|
||||
const where = {};
|
||||
for (let key in params) {
|
||||
const value = params[key];
|
||||
if (!value) continue;
|
||||
|
||||
switch (key) {
|
||||
case 'name':
|
||||
where[key] = {like: `%${value}%`};
|
||||
break;
|
||||
case 'producerFk':
|
||||
case 'typeFk':
|
||||
case 'size':
|
||||
case 'inkFk':
|
||||
where[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
filter.where = where;
|
||||
|
||||
this.$.itemsModel.applyFilter(filter);
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnItemBasicData', {
|
||||
|
|
|
@ -11,3 +11,4 @@ Identifier: Identificador
|
|||
Fragile: Frágil
|
||||
Is shown at website, app that this item cannot travel (wreath, palms, ...): Se muestra en la web, app que este artículo no puede viajar (coronas, palmas, ...)
|
||||
Multiplier: Multiplicador
|
||||
Generic: Genérico
|
|
@ -7,7 +7,7 @@
|
|||
"menus": {
|
||||
"main": [
|
||||
{"state": "item.index", "icon": "icon-item"},
|
||||
{"state": "item.request", "icon": "pan_tool"},
|
||||
{"state": "item.request", "icon": "icon-buyrequest"},
|
||||
{"state": "item.waste.index", "icon": "icon-claims"},
|
||||
{"state": "item.fixedPrice", "icon": "icon-fixedPrice"}
|
||||
],
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
ng-show="::ticket.hasTicketRequest"
|
||||
translate-attr="{title: 'Purchase request'}"
|
||||
class="bright"
|
||||
icon="icon-100">
|
||||
icon="icon-buyrequest">
|
||||
</vn-icon>
|
||||
<vn-icon
|
||||
ng-show="::ticket.isAvailable === 0"
|
||||
|
|
|
@ -55,7 +55,13 @@ module.exports = Self => {
|
|||
{
|
||||
relation: 'address',
|
||||
scope: {
|
||||
fields: ['id', 'street', 'postalCode', 'city'],
|
||||
fields: ['street', 'city', 'provinceFk', 'phone', 'nickname', 'postalCode'],
|
||||
include: {
|
||||
relation: 'province',
|
||||
scope: {
|
||||
fields: ['name']
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
]
|
||||
|
|
|
@ -121,11 +121,17 @@
|
|||
data="$ctrl.possibleTickets">
|
||||
</vn-crud-model>
|
||||
<vn-dialog
|
||||
vn-id="possibleTicketsDialog"
|
||||
on-accept="$ctrl.setTicketsRoute()"
|
||||
message="Tickets to add">
|
||||
vn-id="possibleTicketsDialog">
|
||||
<tpl-title>
|
||||
<vn-horizontal>
|
||||
<span translate>Tickets to add</span>
|
||||
<div class="button-right">
|
||||
<vn-button label="Add" ng-click="$ctrl.setTicketsRoute()"></vn-button>
|
||||
</div>
|
||||
</vn-horizontal>
|
||||
</tpl-title>
|
||||
<tpl-body>
|
||||
<vn-data-viewer class="vn-pa-md" model="possibleTicketsModel">
|
||||
<vn-data-viewer model="possibleTicketsModel">
|
||||
<vn-table model="possibleTicketsModel" auto-load="false">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
|
@ -136,10 +142,15 @@
|
|||
</vn-th>
|
||||
<vn-th number>Ticket</vn-th>
|
||||
<vn-th>Client</vn-th>
|
||||
<vn-th number shrink>Packages</vn-th>
|
||||
<vn-th shrink>Warehouse</vn-th>
|
||||
<vn-th expand>Postcode</vn-th>
|
||||
<vn-th shrink>Province</vn-th>
|
||||
<vn-th shrink>
|
||||
<span translate>
|
||||
Population
|
||||
</span>
|
||||
</vn-th>
|
||||
<vn-th expand>PC</vn-th>
|
||||
<vn-th>Address</vn-th>
|
||||
<vn-th shrink>Warehouse</vn-th>
|
||||
</vn-tr>
|
||||
</vn-thead>
|
||||
<vn-tbody>
|
||||
|
@ -154,24 +165,21 @@
|
|||
{{::ticket.id}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td number>
|
||||
<vn-td expand>
|
||||
<span class="link" ng-click="clientDescriptor.show($event, ticket.clientFk)">
|
||||
{{::ticket.nickname}}
|
||||
</span>
|
||||
</vn-td>
|
||||
<vn-td number shrink>{{::ticket.packages}}</vn-td>
|
||||
<vn-td expand>{{::ticket.warehouse.name}}</vn-td>
|
||||
<vn-td shrink>{{::ticket.address.province.name}}</vn-td>
|
||||
<vn-td shrink>{{::ticket.address.city}}</vn-td>
|
||||
<vn-td number shrink>{{::ticket.address.postalCode}}</vn-td>
|
||||
<vn-td expand title="{{::ticket.address.street}}">{{::ticket.address.street}}</vn-td>
|
||||
<vn-td expand>{{::ticket.warehouse.name}}</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
</vn-table>
|
||||
</vn-data-viewer>
|
||||
</tpl-body>
|
||||
<tpl-buttons>
|
||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
||||
<button response="accept" translate>Add</button>
|
||||
</tpl-buttons>
|
||||
</vn-dialog>
|
||||
<vn-float-button
|
||||
icon="add"
|
||||
|
|
|
@ -56,7 +56,7 @@ class Controller extends Section {
|
|||
|
||||
this.$http.get(query).then(response => {
|
||||
if (!response.data)
|
||||
throw new UserError(`The route's vehicle doesn't have a departing warehouse`);
|
||||
throw new UserError(`The route's vehicle doesn't have a delivery point`);
|
||||
|
||||
return response.data;
|
||||
}).then(address => {
|
||||
|
@ -132,6 +132,7 @@ class Controller extends Section {
|
|||
this.$.model.data = this.$.model.data.concat(tickets);
|
||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||
this.updateVolume();
|
||||
this.$.possibleTicketsDialog.hide();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -197,6 +197,9 @@ describe('Route', () => {
|
|||
|
||||
describe('setTicketsRoute()', () => {
|
||||
it('should perform a POST query to add tickets to the route', () => {
|
||||
controller.$.possibleTicketsDialog = {hide: () => {}};
|
||||
jest.spyOn(controller.$.possibleTicketsDialog, 'hide');
|
||||
|
||||
controller.$params = {id: 1101};
|
||||
controller.$.model.data = [{id: 1, checked: false}];
|
||||
|
||||
|
@ -223,6 +226,7 @@ describe('Route', () => {
|
|||
$httpBackend.flush();
|
||||
|
||||
expect(controller.$.model.data).toEqual(expectedResult);
|
||||
expect(controller.$.possibleTicketsDialog.hide).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -9,5 +9,6 @@ Tickets to add: Tickets a añadir
|
|||
Ticket not found: No se ha encontrado el ticket
|
||||
The selected ticket is not suitable for this route: El ticket seleccionado no es apto para esta ruta
|
||||
PC: CP
|
||||
The route's vehicle doesn't have a departing warehouse: El vehículo de la ruta no tiene un almacén de salida
|
||||
The route's vehicle doesn't have a delivery point: El vehículo de la ruta no tiene un punto de entrega
|
||||
The route doesn't have a vehicle: La ruta no tiene un vehículo
|
||||
Population: Población
|
|
@ -8,3 +8,9 @@ vn-route-tickets form{
|
|||
max-width: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.button-right{
|
||||
display: block;
|
||||
padding-right: 50px;
|
||||
text-align: right;
|
||||
}
|
|
@ -16,7 +16,6 @@
|
|||
<vn-card class="vn-pa-lg">
|
||||
<vn-horizontal ng-repeat="supplierAccount in $ctrl.supplierAccounts">
|
||||
<vn-textfield
|
||||
ng-show="supplierAccount.iban || supplierAccount.iban == undefined"
|
||||
label="Iban"
|
||||
ng-model="supplierAccount.iban"
|
||||
on-change="supplierAccount.bankEntityFk = supplierAccount.iban.slice(4,8)"
|
||||
|
@ -30,10 +29,10 @@
|
|||
rule>
|
||||
<append>
|
||||
<vn-icon-button
|
||||
vn-auto
|
||||
icon="add_circle"
|
||||
vn-tooltip="New bank entity"
|
||||
ng-click="$ctrl.showBankEntity($event, $index)"
|
||||
tabindex="-1">
|
||||
vn-click-stop="bankEntity.show({index: $index})"
|
||||
vn-tooltip="New bank entity">
|
||||
</vn-icon-button>
|
||||
</append>
|
||||
</vn-autocomplete>
|
||||
|
@ -41,14 +40,6 @@
|
|||
label="Beneficiary"
|
||||
ng-model="supplierAccount.beneficiary"
|
||||
info="Beneficiary information">
|
||||
<append>
|
||||
<vn-icon-button
|
||||
vn-auto
|
||||
icon="add_circle"
|
||||
vn-click-stop="bankEntity.show({index: $index})"
|
||||
vn-tooltip="New bank entity">
|
||||
</vn-icon-button>
|
||||
</append>
|
||||
</vn-textfield>
|
||||
<vn-none>
|
||||
<vn-icon-button
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
{"state": "supplier.card.fiscalData", "icon": "account_balance"},
|
||||
{"state": "supplier.card.billingData", "icon": "icon-payment"},
|
||||
{"state": "supplier.card.address.index", "icon": "icon-delivery"},
|
||||
{"state": "supplier.card.account", "icon": "icon-accounts"},
|
||||
{"state": "supplier.card.account", "icon": "icon-account"},
|
||||
{"state": "supplier.card.contact", "icon": "contact_phone"},
|
||||
{"state": "supplier.card.log", "icon": "history"},
|
||||
{"state": "supplier.card.consumption", "icon": "show_chart"}
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('recalculatePrice', {
|
||||
description: 'Calculates the price of a sale and its components',
|
||||
description: 'Calculates the price of sales and its components',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'id',
|
||||
description: 'The sale id',
|
||||
type: 'number',
|
||||
arg: 'sales',
|
||||
description: 'The sales',
|
||||
type: ['object'],
|
||||
required: true,
|
||||
http: {source: 'path'}
|
||||
http: {source: 'body'}
|
||||
}],
|
||||
returns: {
|
||||
type: 'Number',
|
||||
type: 'number',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/:id/recalculatePrice`,
|
||||
path: `/recalculatePrice`,
|
||||
verb: 'post'
|
||||
}
|
||||
});
|
||||
|
||||
Self.recalculatePrice = async(ctx, id, options) => {
|
||||
Self.recalculatePrice = async(ctx, sales, options) => {
|
||||
const models = Self.app.models;
|
||||
const myOptions = {};
|
||||
let tx;
|
||||
|
@ -34,18 +34,33 @@ module.exports = Self => {
|
|||
}
|
||||
|
||||
try {
|
||||
const sale = await Self.findById(id, null, myOptions);
|
||||
const isEditable = await models.Ticket.isEditable(ctx, sale.ticketFk, myOptions);
|
||||
const salesIds = [];
|
||||
const params = [];
|
||||
sales.forEach(sale => {
|
||||
salesIds.push(sale.id);
|
||||
params.push('?');
|
||||
});
|
||||
|
||||
const isEditable = await models.Ticket.isEditable(ctx, sales[0].ticketFk, myOptions);
|
||||
if (!isEditable)
|
||||
throw new UserError(`The sales of this ticket can't be modified`);
|
||||
|
||||
const canEditSale = await models.Sale.canEdit(ctx, [id], myOptions);
|
||||
|
||||
const canEditSale = await models.Sale.canEdit(ctx, sales, myOptions);
|
||||
if (!canEditSale)
|
||||
throw new UserError(`Sale(s) blocked, please contact production`);
|
||||
|
||||
const recalculation = await Self.rawSql('CALL vn.sale_calculateComponent(?, null)', [id], myOptions);
|
||||
const paramsString = params.join();
|
||||
|
||||
const query = `
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.recalculateSales;
|
||||
CREATE TEMPORARY TABLE tmp.recalculateSales
|
||||
SELECT s.id
|
||||
FROM sale s
|
||||
WHERE s.id IN (${paramsString});
|
||||
CALL vn.sale_recalcComponent(null);
|
||||
DROP TEMPORARY TABLE tmp.recalculateSales;`;
|
||||
|
||||
const recalculation = await Self.rawSql(query, salesIds, myOptions);
|
||||
|
||||
if (tx) await tx.commit();
|
||||
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
describe('sale recalculatePrice()', () => {
|
||||
const saleId = 7;
|
||||
|
||||
it('should update the sale price', async() => {
|
||||
const tx = await models.Sale.beginTransaction({});
|
||||
|
||||
const sales = [
|
||||
{id: 7, ticketFk: 11},
|
||||
{id: 8, ticketFk: 11}
|
||||
];
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const ctx = {req: {accessToken: {userId: 9}}};
|
||||
const response = await models.Sale.recalculatePrice(ctx, saleId, options);
|
||||
const response = await models.Sale.recalculatePrice(ctx, sales, options);
|
||||
|
||||
expect(response.affectedRows).toBeDefined();
|
||||
expect(response[0].affectedRows).toBeDefined();
|
||||
expect(response[1].affectedRows).toBeDefined();
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
|
@ -29,8 +31,8 @@ describe('sale recalculatePrice()', () => {
|
|||
const options = {transaction: tx};
|
||||
|
||||
const ctx = {req: {accessToken: {userId: 9}}};
|
||||
const immutableSaleId = 1;
|
||||
await models.Sale.recalculatePrice(ctx, immutableSaleId, options);
|
||||
const immutableSale = [{id: 1, ticketFk: 1}];
|
||||
await models.Sale.recalculatePrice(ctx, immutableSale, options);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
|
|
|
@ -85,9 +85,10 @@ module.exports = Self => {
|
|||
};
|
||||
|
||||
if (sale.quantity == originalSale.quantity) {
|
||||
await models.Sale.updateAll({
|
||||
id: sale.id
|
||||
}, {ticketFk: ticketId}, myOptions);
|
||||
query = `UPDATE sale
|
||||
SET ticketFk = ?
|
||||
WHERE id = ?`;
|
||||
await Self.rawSql(query, [ticketId, sale.id], myOptions);
|
||||
} else if (sale.quantity != originalSale.quantity) {
|
||||
await transferPartialSale(
|
||||
ticketId, originalSale, sale, myOptions);
|
||||
|
@ -170,29 +171,31 @@ module.exports = Self => {
|
|||
|
||||
// Update original sale
|
||||
const rest = originalSale.quantity - sale.quantity;
|
||||
const originalInstance = await models.Sale.findById(sale.id, null, options);
|
||||
await originalInstance.updateAttribute('quantity', rest, options);
|
||||
query = `UPDATE sale
|
||||
SET quantity = ?
|
||||
WHERE id = ?`;
|
||||
await Self.rawSql(query, [rest, sale.id], options);
|
||||
|
||||
// Clone sale with new quantity
|
||||
const newSale = originalSale;
|
||||
newSale.id = undefined;
|
||||
newSale.ticketFk = ticketId;
|
||||
newSale.quantity = sale.quantity;
|
||||
|
||||
const createdSale = await models.Sale.create(newSale, options);
|
||||
query = `INSERT INTO sale (itemFk, ticketFk, concept, quantity, originalQuantity, price, discount, priceFixed,
|
||||
reserved, isPicked, isPriceFixed, isAdded)
|
||||
SELECT itemFk, ?, concept, ?, originalQuantity, price, discount, priceFixed,
|
||||
reserved, isPicked, isPriceFixed, isAdded
|
||||
FROM sale
|
||||
WHERE id = ?`;
|
||||
await Self.rawSql(query, [ticketId, sale.quantity, sale.id], options);
|
||||
const [lastInsertedSale] = await Self.rawSql('SELECT LAST_INSERT_ID() AS id', null, options);
|
||||
|
||||
// Clone sale components
|
||||
const saleComponents = await models.SaleComponent.find({
|
||||
where: {saleFk: sale.id}
|
||||
}, options);
|
||||
const newComponents = saleComponents.map(component => {
|
||||
component.saleFk = createdSale.id;
|
||||
component.saleFk = lastInsertedSale.id;
|
||||
|
||||
return component;
|
||||
});
|
||||
|
||||
await models.SaleComponent.create(newComponents, options);
|
||||
|
||||
return originalInstance;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
ng-show="::ticket.hasTicketRequest"
|
||||
translate-attr="{title: 'Purchase request'}"
|
||||
class="bright"
|
||||
icon="icon-100">
|
||||
icon="icon-buyrequest">
|
||||
</vn-icon>
|
||||
<vn-icon
|
||||
ng-show="::ticket.isAvailable === 0"
|
||||
|
@ -167,7 +167,7 @@
|
|||
tooltip-position="left">
|
||||
</vn-button>
|
||||
<vn-button class="round sm vn-mb-sm"
|
||||
icon="icon-invoices"
|
||||
icon="icon-invoice"
|
||||
ng-click="makeInvoiceConfirmation.show()"
|
||||
ng-show="$ctrl.totalChecked > 0"
|
||||
vn-tooltip="Make invoice..."
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
"card": [
|
||||
{"state": "ticket.card.basicData.stepOne", "icon": "settings"},
|
||||
{"state": "ticket.card.sale", "icon": "icon-lines"},
|
||||
{"state": "ticket.card.request.index", "icon": "icon-100"},
|
||||
{"state": "ticket.card.request.index", "icon": "icon-buyrequest"},
|
||||
{"state": "ticket.card.tracking.index", "icon": "remove_red_eye"},
|
||||
{"state": "ticket.card.log", "icon": "history"},
|
||||
{"state": "ticket.card.observation", "icon": "insert_drive_file"},
|
||||
|
|
|
@ -464,7 +464,7 @@
|
|||
<vn-item translate
|
||||
name="calculatePrice"
|
||||
ng-click="$ctrl.calculateSalePrice()"
|
||||
ng-if="$ctrl.isEditable && $ctrl.hasOneSaleSelected()">
|
||||
ng-if="$ctrl.isEditable">
|
||||
Recalculate price
|
||||
</vn-item>
|
||||
<vn-item translate
|
||||
|
|
|
@ -450,10 +450,11 @@ class Controller extends Section {
|
|||
}
|
||||
|
||||
calculateSalePrice() {
|
||||
const sale = this.selectedValidSales()[0];
|
||||
if (!sale) return;
|
||||
const query = `Sales/${sale.id}/recalculatePrice`;
|
||||
this.$http.post(query).then(() => {
|
||||
const sales = this.selectedValidSales();
|
||||
if (!sales) return;
|
||||
|
||||
const query = `Sales/recalculatePrice`;
|
||||
this.$http.post(query, sales).then(() => {
|
||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||
this.$.model.refresh();
|
||||
});
|
||||
|
|
|
@ -684,14 +684,15 @@ describe('Ticket', () => {
|
|||
});
|
||||
|
||||
describe('calculateSalePrice()', () => {
|
||||
it('should make an HTTP post query ', () => {
|
||||
it('should make an HTTP post query', () => {
|
||||
jest.spyOn(controller.vnApp, 'showSuccess').mockReturnThis();
|
||||
jest.spyOn(controller.$.model, 'refresh').mockReturnThis();
|
||||
|
||||
const selectedSale = controller.sales[0];
|
||||
selectedSale.checked = true;
|
||||
controller.sales.forEach(sale => {
|
||||
sale.checked = true;
|
||||
});
|
||||
|
||||
$httpBackend.expect('POST', `Sales/1/recalculatePrice`).respond(200);
|
||||
$httpBackend.expect('POST', `Sales/recalculatePrice`).respond(200);
|
||||
controller.calculateSalePrice();
|
||||
$httpBackend.flush();
|
||||
|
||||
|
|
|
@ -46,12 +46,29 @@ module.exports = Self => {
|
|||
if (isSubordinate === false || (isSubordinate && isHimself && !isTeamBoss))
|
||||
throw new UserError(`You don't have enough privileges`);
|
||||
|
||||
const timed = new Date(args.timed);
|
||||
const minTime = new Date(args.timed);
|
||||
minTime.setHours(0, 0, 0, 0);
|
||||
|
||||
query = `SELECT * FROM vn.workerLabour WHERE workerFk = ? AND (ended >= ? OR ended IS NULL);`;
|
||||
const [workerLabour] = await Self.rawSql(query, [workerId, minTime]);
|
||||
const absence = await models.Calendar.findOne({
|
||||
where: {
|
||||
businessFk: workerLabour.businessFk,
|
||||
dated: minTime
|
||||
}
|
||||
});
|
||||
if (absence) {
|
||||
const absenceType = await models.AbsenceType.findById(absence.dayOffTypeFk, null, myOptions);
|
||||
const isNotHalfAbsence = absenceType.code != 'halfHoliday'
|
||||
&& absenceType.code != 'halfPaidLeave'
|
||||
&& absenceType.code != 'halfFurlough';
|
||||
if (isNotHalfAbsence)
|
||||
throw new UserError(`The worker has a marked absence that day`);
|
||||
}
|
||||
return models.WorkerTimeControl.create({
|
||||
userFk: workerId,
|
||||
direction: args.direction,
|
||||
timed: timed,
|
||||
timed: args.timed,
|
||||
manual: true
|
||||
}, myOptions);
|
||||
};
|
||||
|
|
|
@ -77,6 +77,23 @@ describe('workerTimeControl add/delete timeEntry()', () => {
|
|||
}
|
||||
});
|
||||
|
||||
it('should fail to add a time entry if the target user has absent that day', async() => {
|
||||
activeCtx.accessToken.userId = salesBossId;
|
||||
const workerId = salesPersonId;
|
||||
let error;
|
||||
|
||||
let calendar = await app.models.Calendar.findById(3);
|
||||
|
||||
try {
|
||||
ctx.args = {timed: new Date(calendar.dated), direction: 'in'};
|
||||
await models.WorkerTimeControl.addTimeEntry(ctx, workerId);
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
|
||||
expect(error.message).toBe(`The worker has a marked absence that day`);
|
||||
});
|
||||
|
||||
it('should try but fail to delete his own time entry', async() => {
|
||||
activeCtx.accessToken.userId = salesBossId;
|
||||
const workerId = salesBossId;
|
||||
|
|
|
@ -65,7 +65,22 @@ module.exports = Self => {
|
|||
if (args.dated < labour.started || (labour.ended != null && args.dated > labour.ended))
|
||||
throw new UserError(`The contract was not active during the selected date`);
|
||||
|
||||
const result = await Self.rawSql(
|
||||
query = `SELECT *
|
||||
FROM vn.workerTimeControl
|
||||
WHERE userFk = ? AND timed BETWEEN DATE(?) AND CONCAT(DATE(?), ' 23:59:59')
|
||||
LIMIT 1;`;
|
||||
const [hasHoursRecorded] = await Self.rawSql(query, [id, args.dated, args.dated]);
|
||||
|
||||
const absenceType = await models.AbsenceType.findById(args.absenceTypeId, null, myOptions);
|
||||
|
||||
const isNotHalfAbsence = absenceType.code != 'halfHoliday'
|
||||
&& absenceType.code != 'halfPaidLeave'
|
||||
&& absenceType.code != 'halfFurlough';
|
||||
|
||||
if (hasHoursRecorded && isNotHalfAbsence)
|
||||
throw new UserError(`The worker has hours recorded that day`);
|
||||
|
||||
const [result] = await Self.rawSql(
|
||||
`SELECT COUNT(*) halfHolidayCounter
|
||||
FROM vn.calendar c
|
||||
JOIN postgresql.business b ON b.business_id = c.businessFk
|
||||
|
@ -74,10 +89,10 @@ module.exports = Self => {
|
|||
WHERE c.dayOffTypeFk = 6
|
||||
AND pe.workerFk = ?
|
||||
AND c.dated BETWEEN util.firstDayOfYear(CURDATE())
|
||||
AND LAST_DAY(DATE_ADD(NOW(), INTERVAL 12-MONTH(NOW()) MONTH))`, [args.id]);
|
||||
AND LAST_DAY(DATE_ADD(NOW(), INTERVAL 12-MONTH(NOW()) MONTH))`, [id]);
|
||||
|
||||
const hasHalfHoliday = result[0].halfHolidayCounter > 0;
|
||||
const isHalfHoliday = args.absenceTypeId == 6;
|
||||
const hasHalfHoliday = result.halfHolidayCounter > 0;
|
||||
const isHalfHoliday = absenceType.code === 'halfHoliday';
|
||||
|
||||
if (isHalfHoliday && hasHalfHoliday)
|
||||
throw new UserError(`Cannot add more than one '1/2 day vacation'`);
|
||||
|
|
|
@ -77,7 +77,7 @@ describe('Worker createAbsence()', () => {
|
|||
|
||||
it(`should throw an error when adding a "Half holiday" absence if there's already one`, async() => {
|
||||
const ctx = {
|
||||
req: {accessToken: {userId: 19}},
|
||||
req: {accessToken: {userId: 9}},
|
||||
args: {
|
||||
id: 1,
|
||||
businessFk: 1,
|
||||
|
@ -85,6 +85,7 @@ describe('Worker createAbsence()', () => {
|
|||
dated: new Date()
|
||||
}
|
||||
};
|
||||
const workerId = 1;
|
||||
|
||||
const tx = await app.models.Calendar.beginTransaction({});
|
||||
|
||||
|
@ -102,4 +103,33 @@ describe('Worker createAbsence()', () => {
|
|||
|
||||
expect(error.message).toEqual(`Cannot add more than one '1/2 day vacation'`);
|
||||
});
|
||||
|
||||
it(`should throw an error when adding a absence if the worker has hours recorded that day and not is a half absence`, async() => {
|
||||
const ctx = {
|
||||
req: {accessToken: {userId: 19}},
|
||||
args: {
|
||||
id: 1106,
|
||||
businessFk: 1106,
|
||||
absenceTypeId: 1,
|
||||
dated: new Date()
|
||||
}
|
||||
};
|
||||
const workerId = 1106;
|
||||
|
||||
const tx = await app.models.Calendar.beginTransaction({});
|
||||
|
||||
let error;
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
await app.models.Worker.createAbsence(ctx, workerId, options);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
error = e;
|
||||
}
|
||||
|
||||
expect(error.message).toEqual(`The worker has hours recorded that day`);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
"id": true,
|
||||
"type": "Number"
|
||||
},
|
||||
"workerFk": {
|
||||
"type": "Number"
|
||||
},
|
||||
"started": {
|
||||
"type": "date"
|
||||
},
|
||||
|
|
|
@ -83,7 +83,7 @@
|
|||
"worker": "$ctrl.worker"
|
||||
}
|
||||
}, {
|
||||
"url": "/time-control",
|
||||
"url": "/time-control?timestamp",
|
||||
"state": "worker.card.timeControl",
|
||||
"component": "vn-worker-time-control",
|
||||
"description": "Time control",
|
||||
|
|
|
@ -91,6 +91,7 @@
|
|||
</vn-label-value>
|
||||
</div>
|
||||
<vn-calendar
|
||||
vn-id="calendar"
|
||||
class="vn-pt-md"
|
||||
ng-model="$ctrl.date"
|
||||
has-events="$ctrl.hasEvents($day)">
|
||||
|
|
|
@ -15,7 +15,15 @@ class Controller extends Section {
|
|||
}
|
||||
|
||||
$postLink() {
|
||||
this.date = new Date();
|
||||
const timestamp = this.$params.timestamp;
|
||||
let initialDate = new Date();
|
||||
|
||||
if (timestamp) {
|
||||
initialDate = new Date(timestamp * 1000);
|
||||
this.$.calendar.defaultDate = initialDate;
|
||||
}
|
||||
|
||||
this.date = initialDate;
|
||||
}
|
||||
|
||||
get worker() {
|
||||
|
|
|
@ -129,5 +129,28 @@ describe('Component vnWorkerTimeControl', () => {
|
|||
expect(controller.fetchHours).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('$postLink() ', () => {
|
||||
it(`should set the controller date as today if no timestamp is defined`, () => {
|
||||
controller.$.model = {applyFilter: jest.fn().mockReturnValue(Promise.resolve())};
|
||||
controller.$params = {timestamp: undefined};
|
||||
controller.$postLink();
|
||||
|
||||
expect(controller.date).toEqual(jasmine.any(Date));
|
||||
});
|
||||
|
||||
it(`should set the controller date using the received timestamp`, () => {
|
||||
const timestamp = 1;
|
||||
const date = new Date(timestamp);
|
||||
|
||||
controller.$.model = {applyFilter: jest.fn().mockReturnValue(Promise.resolve())};
|
||||
controller.$.calendar = {};
|
||||
controller.$params = {timestamp: timestamp};
|
||||
|
||||
controller.$postLink();
|
||||
|
||||
expect(controller.date.toDateString()).toEqual(date.toDateString());
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue