1447-updateClaim_refactor #405
|
@ -0,0 +1,41 @@
|
||||||
|
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||||
|
const mergeFilters = require('vn-loopback/util/filter').mergeFilters;
|
||||||
|
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('latest', {
|
||||||
|
description: 'Returns the lastest campaigns',
|
||||||
|
accessType: 'READ',
|
||||||
|
accepts: [{
|
||||||
|
arg: 'filter',
|
||||||
|
type: 'Object',
|
||||||
|
description: `Filter defining where, order, offset, and limit - must be a JSON-encoded string`
|
||||||
|
}],
|
||||||
|
returns: {
|
||||||
|
type: ['object'],
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/latest`,
|
||||||
|
verb: 'GET'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.latest = async filter => {
|
||||||
|
const conn = Self.dataSource.connector;
|
||||||
|
const minDate = new Date();
|
||||||
|
minDate.setFullYear(minDate.getFullYear() - 1);
|
||||||
|
minDate.setMonth(0);
|
||||||
|
minDate.setDate(1);
|
||||||
|
|
||||||
|
const where = {dated: {gte: minDate}};
|
||||||
|
filter = mergeFilters(filter, {where});
|
||||||
|
|
||||||
|
const stmt = new ParameterizedSQL(
|
||||||
|
`SELECT * FROM campaign`);
|
||||||
|
stmt.merge(conn.makeWhere(filter.where));
|
||||||
|
stmt.merge('GROUP BY code');
|
||||||
|
stmt.merge(conn.makePagination(filter));
|
||||||
|
|
||||||
|
return conn.executeStmt(stmt);
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,34 @@
|
||||||
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('campaign latest()', () => {
|
||||||
|
it('should return the campaigns from the last year', async() => {
|
||||||
|
let result = await app.models.Campaign.latest();
|
||||||
|
|
||||||
|
const lastYearDate = new Date();
|
||||||
|
lastYearDate.setFullYear(lastYearDate.getFullYear() - 1);
|
||||||
|
const lastYear = lastYearDate.getFullYear();
|
||||||
|
|
||||||
|
const randomIndex = Math.floor(Math.random() * result.length);
|
||||||
|
const campaignDated = result[randomIndex].dated;
|
||||||
|
const campaignYear = campaignDated.getFullYear();
|
||||||
|
|
||||||
|
expect(result.length).toEqual(3);
|
||||||
|
expect(campaignYear).toEqual(lastYear);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the campaigns from the current year', async() => {
|
||||||
|
const currentDate = new Date();
|
||||||
|
const currentYear = currentDate.getFullYear();
|
||||||
|
|
||||||
|
const result = await app.models.Campaign.latest({
|
||||||
|
where: {dated: {like: `%${currentYear}%`}}
|
||||||
|
});
|
||||||
|
|
||||||
|
const randomIndex = Math.floor(Math.random() * result.length);
|
||||||
|
const campaignDated = result[randomIndex].dated;
|
||||||
|
const campaignYear = campaignDated.getFullYear();
|
||||||
|
|
||||||
|
expect(result.length).toEqual(3);
|
||||||
|
expect(campaignYear).toEqual(currentYear);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,16 @@
|
||||||
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('campaign upcoming()', () => {
|
||||||
|
it('should return the upcoming campaign but from the last year', async() => {
|
||||||
|
let response = await app.models.Campaign.upcoming();
|
||||||
|
|
||||||
|
const lastYearDate = new Date();
|
||||||
|
lastYearDate.setFullYear(lastYearDate.getFullYear() - 1);
|
||||||
|
const lastYear = lastYearDate.getFullYear();
|
||||||
|
|
||||||
|
const campaignDated = response.dated;
|
||||||
|
const campaignYear = campaignDated.getFullYear();
|
||||||
|
|
||||||
|
expect(campaignYear).toEqual(lastYear);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,29 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('upcoming', {
|
||||||
|
description: 'Returns the upcoming campaign',
|
||||||
|
accessType: 'READ',
|
||||||
|
accepts: [],
|
||||||
|
returns: {
|
||||||
|
type: ['object'],
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/upcoming`,
|
||||||
|
verb: 'GET'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.upcoming = async() => {
|
||||||
|
const minDate = new Date();
|
||||||
|
minDate.setFullYear(minDate.getFullYear() - 1);
|
||||||
|
|
||||||
|
return Self.findOne({
|
||||||
|
where: {
|
||||||
|
dated: {
|
||||||
|
gte: minDate
|
||||||
|
}
|
||||||
|
},
|
||||||
|
order: 'dated ASC'
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
|
@ -8,6 +8,9 @@
|
||||||
"Bank": {
|
"Bank": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"Campaign": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"Country": {
|
"Country": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
require('../methods/campaign/latest')(Self);
|
||||||
|
require('../methods/campaign/upcoming')(Self);
|
||||||
|
};
|
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"name": "Campaign",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "campaign"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "number",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"code": {
|
||||||
|
"type": "string",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"dated": {
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
"scopeDays": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"acls": [
|
||||||
|
{
|
||||||
|
"accessType": "READ",
|
||||||
|
"principalType": "ROLE",
|
||||||
|
"principalId": "$everyone",
|
||||||
|
"permission": "ALLOW"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -4,3 +4,4 @@ ADD COLUMN `oldInstance` text CHARACTER SET utf8 COLLATE utf8_unicode_ci,
|
||||||
ADD COLUMN `newInstance` text CHARACTER SET utf8 COLLATE utf8_unicode_ci,
|
ADD COLUMN `newInstance` text CHARACTER SET utf8 COLLATE utf8_unicode_ci,
|
||||||
ADD COLUMN `changedModelId` int(11) DEFAULT NULL,
|
ADD COLUMN `changedModelId` int(11) DEFAULT NULL,
|
||||||
ADD COLUMN `changedModelValue` varchar(45) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL;
|
ADD COLUMN `changedModelValue` varchar(45) CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
ALTER TABLE `vn`.`ticketService`
|
||||||
|
DROP FOREIGN KEY `ticketServiceIvaGroup`;
|
||||||
|
ALTER TABLE `vn`.`ticketService`
|
||||||
|
CHANGE COLUMN `taxClassFk` `taxClassFk` TINYINT(3) UNSIGNED NOT NULL DEFAULT 2 ;
|
||||||
|
ALTER TABLE `vn`.`ticketService`
|
||||||
|
ADD CONSTRAINT `ticketServiceIvaGroup`
|
||||||
|
FOREIGN KEY (`taxClassFk`)
|
||||||
|
REFERENCES `vn`.`taxClass` (`id`)
|
||||||
|
ON UPDATE CASCADE;
|
|
@ -0,0 +1 @@
|
||||||
|
UPDATE salix.ACL t SET t.principalId = 'salesAssistant' WHERE t.id = 234
|
|
@ -0,0 +1,37 @@
|
||||||
|
CREATE TABLE `vn`.campaign
|
||||||
|
(
|
||||||
|
id INT AUTO_INCREMENT,
|
||||||
|
code ENUM('mothersDay', 'allSaints', 'valentinesDay') NOT NULL,
|
||||||
|
dated DATE DEFAULT CURDATE() NOT NULL,
|
||||||
|
scopeDays INT NOT NULL DEFAULT '15',
|
||||||
|
CONSTRAINT campaign_pk
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX campaign_dated_uindex
|
||||||
|
ON `vn`.campaign (dated);
|
||||||
|
|
||||||
|
-- TODOS SANTOS
|
||||||
|
INSERT INTO `vn`.campaign(code, dated)
|
||||||
|
SELECT 'allSaints' AS code, dated
|
||||||
|
FROM `vn`.time
|
||||||
|
WHERE dated >= CONCAT(YEAR(CURDATE()) - 1, '-01-01')
|
||||||
|
AND month = 11
|
||||||
|
AND day = 1;
|
||||||
|
|
||||||
|
-- SAN VALENTIN
|
||||||
|
INSERT INTO `vn`.campaign(code, dated)
|
||||||
|
SELECT 'valentinesDay' AS code, dated
|
||||||
|
FROM `vn`.time
|
||||||
|
WHERE dated >= CONCAT(YEAR(CURDATE()) - 1, '-01-01')
|
||||||
|
AND month = 2
|
||||||
|
AND day = 14;
|
||||||
|
|
||||||
|
-- DIA DE LA MADRE
|
||||||
|
INSERT INTO `vn`.campaign(code, dated)
|
||||||
|
SELECT 'mothersDay' AS code, dated
|
||||||
|
FROM `vn`.time
|
||||||
|
WHERE dated >= CONCAT(YEAR(CURDATE()) - 1, '-01-01')
|
||||||
|
AND month = 5
|
||||||
|
AND WEEK(dated, 5) - WEEK(DATE_SUB(dated, INTERVAL DAYOFMONTH(dated) - 1 DAY), 5) + 1 = 1 -- WEEK OF MONTH
|
||||||
|
AND DAYOFWEEK(dated) = 1;
|
|
@ -0,0 +1,4 @@
|
||||||
|
ALTER TABLE `vn`.department
|
||||||
|
ADD notificationEmail VARCHAR(150) null;
|
||||||
|
|
||||||
|
UPDATE vn.department t SET t.notificationEmail = 'direccioncomercial@verdnatura.es' WHERE t.id = 43
|
|
@ -42,8 +42,8 @@ INSERT INTO `vn`.`worker`(`id`,`code`, `firstName`, `lastName`, `userFk`, `bossF
|
||||||
FROM `vn`.`user`;
|
FROM `vn`.`user`;
|
||||||
|
|
||||||
UPDATE `vn`.`worker` SET bossFk = NULL WHERE id = 20;
|
UPDATE `vn`.`worker` SET bossFk = NULL WHERE id = 20;
|
||||||
UPDATE `vn`.`worker` SET bossFk = 20
|
UPDATE `vn`.`worker` SET bossFk = 20 WHERE id = 1 OR id = 9;
|
||||||
WHERE id = 1 OR id = 9;
|
UPDATE `vn`.`worker` SET bossFk = 19 WHERE id = 18;
|
||||||
|
|
||||||
DELETE FROM `vn`.`worker` WHERE firstName ='customer';
|
DELETE FROM `vn`.`worker` WHERE firstName ='customer';
|
||||||
|
|
||||||
|
@ -479,7 +479,9 @@ INSERT INTO `vn`.`expence`(`id`, `taxTypeFk`, `name`, `isWithheld`)
|
||||||
(4751000000, 1, 'Retenciones', 1),
|
(4751000000, 1, 'Retenciones', 1),
|
||||||
(4751000000, 6, 'Retencion', 0),
|
(4751000000, 6, 'Retencion', 0),
|
||||||
(6210000567, 0, 'Alquiler VNH', 0),
|
(6210000567, 0, 'Alquiler VNH', 0),
|
||||||
(7001000000, 1, 'Mercaderia', 0);
|
(7001000000, 1, 'Mercaderia', 0),
|
||||||
|
(7050000000, 1, 'Prestacion de servicios', 1);
|
||||||
|
|
||||||
|
|
||||||
INSERT INTO `vn`.`invoiceOutExpence`(`id`, `invoiceOutFk`, `amount`, `expenceFk`, `created`)
|
INSERT INTO `vn`.`invoiceOutExpence`(`id`, `invoiceOutFk`, `amount`, `expenceFk`, `created`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -1694,6 +1696,10 @@ UPDATE `postgresql`.`business_labour` bl
|
||||||
SET bl.`professional_category_id` = 31
|
SET bl.`professional_category_id` = 31
|
||||||
WHERE p.`Id_trabajador` = 110;
|
WHERE p.`Id_trabajador` = 110;
|
||||||
|
|
||||||
|
UPDATE `postgresql`.`business_labour` bl
|
||||||
|
SET bl.`department_id` = 43
|
||||||
|
WHERE business_id IN(18, 19);
|
||||||
|
|
||||||
INSERT INTO `postgresql`.`media`(`media_id`, `media_type_id`, `value`, `sort`)
|
INSERT INTO `postgresql`.`media`(`media_id`, `media_type_id`, `value`, `sort`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 10, 600123321, 0),
|
(1, 10, 600123321, 0),
|
||||||
|
|
|
@ -510,10 +510,8 @@ export default {
|
||||||
firstServiceType: 'vn-ticket-service vn-autocomplete[ng-model="service.ticketServiceTypeFk"]',
|
firstServiceType: 'vn-ticket-service vn-autocomplete[ng-model="service.ticketServiceTypeFk"]',
|
||||||
firstQuantity: 'vn-ticket-service vn-input-number[ng-model="service.quantity"]',
|
firstQuantity: 'vn-ticket-service vn-input-number[ng-model="service.quantity"]',
|
||||||
firstPrice: 'vn-ticket-service vn-horizontal:nth-child(1) vn-input-number[ng-model="service.price"]',
|
firstPrice: 'vn-ticket-service vn-horizontal:nth-child(1) vn-input-number[ng-model="service.price"]',
|
||||||
firstVatType: 'vn-ticket-service vn-autocomplete[label="Tax class"]',
|
|
||||||
fistDeleteServiceButton: 'vn-ticket-service form vn-horizontal:nth-child(1) vn-icon-button[icon="delete"]',
|
fistDeleteServiceButton: 'vn-ticket-service form vn-horizontal:nth-child(1) vn-icon-button[icon="delete"]',
|
||||||
newServiceTypeName: '.vn-dialog.shown vn-textfield[ng-model="newServiceType.name"]',
|
newServiceTypeName: '.vn-dialog.shown vn-textfield[ng-model="newServiceType.name"]',
|
||||||
newServiceTypeExpense: '.vn-dialog.shown vn-autocomplete[ng-model="newServiceType.expenseFk"]',
|
|
||||||
serviceLine: 'vn-ticket-service > form > vn-card > vn-one:nth-child(2) > vn-horizontal',
|
serviceLine: 'vn-ticket-service > form > vn-card > vn-one:nth-child(2) > vn-horizontal',
|
||||||
saveServiceButton: 'button[type=submit]',
|
saveServiceButton: 'button[type=submit]',
|
||||||
saveServiceTypeButton: '.vn-dialog.shown tpl-buttons > button'
|
saveServiceTypeButton: '.vn-dialog.shown tpl-buttons > button'
|
||||||
|
|
|
@ -78,7 +78,6 @@ describe('Ticket services path', () => {
|
||||||
|
|
||||||
it('should create a new service type then add price then create the service', async() => {
|
it('should create a new service type then add price then create the service', async() => {
|
||||||
await page.write(selectors.ticketService.newServiceTypeName, 'Documentos');
|
await page.write(selectors.ticketService.newServiceTypeName, 'Documentos');
|
||||||
await page.autocompleteSearch(selectors.ticketService.newServiceTypeExpense, 'Retencion');
|
|
||||||
await page.waitToClick(selectors.ticketService.saveServiceTypeButton);
|
await page.waitToClick(selectors.ticketService.saveServiceTypeButton);
|
||||||
await page.write(selectors.ticketService.firstPrice, '999');
|
await page.write(selectors.ticketService.firstPrice, '999');
|
||||||
await page.waitToClick(selectors.ticketService.saveServiceButton);
|
await page.waitToClick(selectors.ticketService.saveServiceButton);
|
||||||
|
@ -109,13 +108,6 @@ describe('Ticket services path', () => {
|
||||||
expect(result).toEqual('999');
|
expect(result).toEqual('999');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should confirm the service VAT was created correctly', async() => {
|
|
||||||
const result = await page
|
|
||||||
.waitToGetProperty(selectors.ticketService.firstVatType, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('General VAT');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should delete the service', async() => {
|
it('should delete the service', async() => {
|
||||||
await page.waitToClick(selectors.ticketService.fistDeleteServiceButton);
|
await page.waitToClick(selectors.ticketService.fistDeleteServiceButton);
|
||||||
await page.waitForNumberOfElements(selectors.ticketService.serviceLine, 0);
|
await page.waitForNumberOfElements(selectors.ticketService.serviceLine, 0);
|
||||||
|
|
|
@ -42,6 +42,7 @@ describe('Ticket create path', () => {
|
||||||
|
|
||||||
it('should again open the new ticket form', async() => {
|
it('should again open the new ticket form', async() => {
|
||||||
await page.waitToClick(selectors.globalItems.returnToModuleIndexButton);
|
await page.waitToClick(selectors.globalItems.returnToModuleIndexButton);
|
||||||
|
await page.waitFor(500);
|
||||||
await page.waitToClick(selectors.ticketsIndex.newTicketButton);
|
await page.waitToClick(selectors.ticketsIndex.newTicketButton);
|
||||||
await page.waitForState('ticket.create');
|
await page.waitForState('ticket.create');
|
||||||
});
|
});
|
||||||
|
|
|
@ -20,14 +20,13 @@ describe('Entry create path', () => {
|
||||||
await page.waitForState('entry.create');
|
await page.waitForState('entry.create');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fill the form to create a valid entry', async() => {
|
it('should fill the form to create a valid entry then redirect to basic Data', async() => {
|
||||||
await page.autocompleteSearch(selectors.entryIndex.newEntrySupplier, '2');
|
await page.autocompleteSearch(selectors.entryIndex.newEntrySupplier, '2');
|
||||||
await page.autocompleteSearch(selectors.entryIndex.newEntryTravel, 'Warehouse Three');
|
await page.autocompleteSearch(selectors.entryIndex.newEntryTravel, 'Warehouse Three');
|
||||||
await page.autocompleteSearch(selectors.entryIndex.newEntryCompany, 'ORN');
|
await page.autocompleteSearch(selectors.entryIndex.newEntryCompany, 'ORN');
|
||||||
await page.waitToClick(selectors.entryIndex.saveNewEntry);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be redirected to entry basic data', async() => {
|
await page.waitToClick(selectors.entryIndex.saveNewEntry);
|
||||||
|
await page.waitFor(500);
|
||||||
await page.waitForState('entry.card.basicData');
|
await page.waitForState('entry.card.basicData');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -190,9 +190,24 @@ export default class Autocomplete extends Field {
|
||||||
|
|
||||||
this.input.value = display;
|
this.input.value = display;
|
||||||
|
|
||||||
if (this.translateFields) {
|
if (this.translateFields && this.selection) {
|
||||||
if (this.translateFields.indexOf(this.showField) > -1)
|
const translations = [];
|
||||||
this.input.value = this.$t(display);
|
for (let field of this.translateFields) {
|
||||||
|
const fieldValue = this._selection[field];
|
||||||
|
translations.push({
|
||||||
|
original: fieldValue,
|
||||||
|
value: this.$t(fieldValue)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let translation of translations) {
|
||||||
|
const orgValue = translation.original;
|
||||||
|
const value = translation.value;
|
||||||
|
|
||||||
|
display = display.replace(orgValue, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.input.value = display;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,5 +68,7 @@
|
||||||
"Incoterms is required for a non UEE member": "Incoterms is required for a non UEE member",
|
"Incoterms is required for a non UEE member": "Incoterms is required for a non UEE member",
|
||||||
"Client checked as validated despite of duplication": "Client checked as validated despite of duplication from client id {{clientId}}",
|
"Client checked as validated despite of duplication": "Client checked as validated despite of duplication from client id {{clientId}}",
|
||||||
"Landing cannot be lesser than shipment": "Landing cannot be lesser than shipment",
|
"Landing cannot be lesser than shipment": "Landing cannot be lesser than shipment",
|
||||||
"NOT_ZONE_WITH_THIS_PARAMETERS": "NOT_ZONE_WITH_THIS_PARAMETERS"
|
"NOT_ZONE_WITH_THIS_PARAMETERS": "NOT_ZONE_WITH_THIS_PARAMETERS",
|
||||||
|
"Created absence": "The worker <strong>{{author}}</strong> has added an absence of type '{{absenceType}}' to <a href='{{{workerUrl}}}'><strong>{{employee}}</strong></a> for day {{dated}}.",
|
||||||
|
"Deleted absence": "The worker <strong>{{author}}</strong> has deleted an absence of type '{{absenceType}}' to <a href='{{{workerUrl}}}'><strong>{{employee}}</strong></a> for day {{dated}}."
|
||||||
}
|
}
|
|
@ -143,5 +143,8 @@
|
||||||
"Role name must be written in camelCase": "Role name must be written in camelCase",
|
"Role name must be written in camelCase": "Role name must be written in camelCase",
|
||||||
"can't be set": "can't be set",
|
"can't be set": "can't be set",
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
"User already exists": "User already exists"
|
"User already exists": "User already exists",
|
||||||
|
"Absence change notification on the labour calendar": "Notificacion de cambio de ausencia en el calendario laboral",
|
||||||
|
"Created absence": "El empleado <strong>{{author}}</strong> ha añadido una ausencia de tipo '{{absenceType}}' a <a href='{{{workerUrl}}}'><strong>{{employee}}</strong></a> para el día {{dated}}.",
|
||||||
|
"Deleted absence": "El empleado <strong>{{author}}</strong> ha eliminado una ausencia de tipo '{{absenceType}}' a <a href='{{{workerUrl}}}'><strong>{{employee}}</strong></a> del día {{dated}}."
|
||||||
}
|
}
|
|
@ -39,7 +39,8 @@
|
||||||
"url": "/index?q",
|
"url": "/index?q",
|
||||||
"state": "account.index",
|
"state": "account.index",
|
||||||
"component": "vn-user-index",
|
"component": "vn-user-index",
|
||||||
"description": "Users"
|
"description": "Users",
|
||||||
|
"acl": ["hr"]
|
||||||
}, {
|
}, {
|
||||||
"url": "/create",
|
"url": "/create",
|
||||||
"state": "account.create",
|
"state": "account.create",
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
<vn-portal slot="topbar">
|
<vn-portal slot="topbar">
|
||||||
<vn-searchbar
|
<vn-searchbar
|
||||||
|
vn-focus
|
||||||
panel="vn-claim-search-panel"
|
panel="vn-claim-search-panel"
|
||||||
info="Search claim by id or client name"
|
info="Search claim by id or client name"
|
||||||
model="model">
|
model="model">
|
||||||
|
|
|
@ -49,6 +49,22 @@
|
||||||
ng-model="filter.categoryId">
|
ng-model="filter.categoryId">
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-autocomplete vn-one
|
||||||
|
url="Campaigns/latest"
|
||||||
|
label="Campaign"
|
||||||
|
translate-fields="['code']"
|
||||||
|
show-field="code"
|
||||||
|
value-field="id"
|
||||||
|
ng-model="filter.campaign"
|
||||||
|
order="dated DESC"
|
||||||
|
selection="$ctrl.campaignSelection"
|
||||||
|
search-function="{dated: {like: '%'+ $search +'%'}}">
|
||||||
|
<tpl-item>
|
||||||
|
{{code}} {{dated | date: 'yyyy'}}
|
||||||
|
</tpl-item>
|
||||||
|
</vn-autocomplete>
|
||||||
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-date-picker
|
<vn-date-picker
|
||||||
vn-one
|
vn-one
|
||||||
|
|
|
@ -1,7 +1,39 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
import SearchPanel from 'core/components/searchbar/search-panel';
|
import SearchPanel from 'core/components/searchbar/search-panel';
|
||||||
|
|
||||||
|
class Controller extends SearchPanel {
|
||||||
|
constructor($, $element) {
|
||||||
|
super($, $element);
|
||||||
|
|
||||||
|
this.getUpcomingCampaing();
|
||||||
|
}
|
||||||
|
|
||||||
|
getUpcomingCampaing() {
|
||||||
|
this.$http.get('Campaigns/upcoming').then(res => {
|
||||||
|
const filter = this.$.filter;
|
||||||
|
filter.campaign = res.data.id;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get campaignSelection() {
|
||||||
|
return this._campaignSelection;
|
||||||
|
}
|
||||||
|
|
||||||
|
set campaignSelection(value) {
|
||||||
|
this._campaignSelection = value;
|
||||||
|
|
||||||
|
if (!value) return;
|
||||||
|
|
||||||
|
const filter = this.$.filter;
|
||||||
|
const from = new Date(value.dated);
|
||||||
|
from.setDate(from.getDate() - value.scopeDays);
|
||||||
|
|
||||||
|
filter.to = value.dated;
|
||||||
|
filter.from = from;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ngModule.vnComponent('vnConsumptionSearchPanel', {
|
ngModule.vnComponent('vnConsumptionSearchPanel', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
controller: SearchPanel
|
controller: Controller
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
import './index.js';
|
||||||
|
|
||||||
|
describe('Client', () => {
|
||||||
|
describe('Component vnConsumptionSearchPanel', () => {
|
||||||
|
let $httpBackend;
|
||||||
|
let $element;
|
||||||
|
let controller;
|
||||||
|
|
||||||
|
beforeEach(ngModule('client'));
|
||||||
|
|
||||||
|
beforeEach(inject(($componentController, _$httpBackend_) => {
|
||||||
|
$httpBackend = _$httpBackend_;
|
||||||
|
$element = angular.element(`<div></div>`);
|
||||||
|
controller = $componentController('vnConsumptionSearchPanel', {$element});
|
||||||
|
controller.$.filter = {};
|
||||||
|
$httpBackend.expect('GET', 'Campaigns/upcoming').respond(200, {id: 1});
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('getUpcomingCampaing()', () => {
|
||||||
|
it(`should make an HTTP query and then set the campaign property`, () => {
|
||||||
|
$httpBackend.expect('GET', 'Campaigns/upcoming').respond(200, {id: 2, code: 'allSaints'});
|
||||||
|
controller.getUpcomingCampaing();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
const filter = controller.$.filter;
|
||||||
|
|
||||||
|
expect(filter.campaign).toEqual(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,3 @@
|
||||||
|
allSaints: All Saints Day
|
||||||
|
valentinesDay: Valentine's Day
|
||||||
|
mothersDay: Mother's day
|
|
@ -1,3 +1,7 @@
|
||||||
Item id: Id artículo
|
Item id: Id artículo
|
||||||
From: Desde
|
From: Desde
|
||||||
To: Hasta
|
To: Hasta
|
||||||
|
Campaign: Campaña
|
||||||
|
allSaints: Día de todos los Santos
|
||||||
|
valentinesDay: Día de San Valentín
|
||||||
|
mothersDay: Día de la madre
|
|
@ -7,6 +7,7 @@
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
<vn-portal slot="topbar">
|
<vn-portal slot="topbar">
|
||||||
<vn-searchbar
|
<vn-searchbar
|
||||||
|
vn-focus
|
||||||
panel="vn-client-search-panel"
|
panel="vn-client-search-panel"
|
||||||
info="Search client by id or name"
|
info="Search client by id or name"
|
||||||
model="model"
|
model="model"
|
||||||
|
|
|
@ -99,7 +99,7 @@
|
||||||
"component": "ui-view",
|
"component": "ui-view",
|
||||||
"abstract": true
|
"abstract": true
|
||||||
}, {
|
}, {
|
||||||
"url": "/index",
|
"url": "/index?q",
|
||||||
"state": "client.card.address.index",
|
"state": "client.card.address.index",
|
||||||
"component": "vn-client-address-index",
|
"component": "vn-client-address-index",
|
||||||
"description": "Addresses",
|
"description": "Addresses",
|
||||||
|
@ -353,7 +353,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "/consumption",
|
"url": "/consumption?q",
|
||||||
"state": "client.card.consumption",
|
"state": "client.card.consumption",
|
||||||
"component": "vn-client-consumption",
|
"component": "vn-client-consumption",
|
||||||
"description": "Consumption",
|
"description": "Consumption",
|
||||||
|
|
|
@ -9,30 +9,6 @@
|
||||||
</vn-watcher>
|
</vn-watcher>
|
||||||
<form name="form" ng-submit="watcher.submit()" class="vn-w-md">
|
<form name="form" ng-submit="watcher.submit()" class="vn-w-md">
|
||||||
<vn-card class="vn-pa-lg">
|
<vn-card class="vn-pa-lg">
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Reference"
|
|
||||||
ng-model="$ctrl.entry.ref"
|
|
||||||
rule
|
|
||||||
vn-focus>
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Notes"
|
|
||||||
ng-model="$ctrl.entry.notes"
|
|
||||||
rule
|
|
||||||
vn-focus>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textarea
|
|
||||||
vn-one
|
|
||||||
label="Observation"
|
|
||||||
ng-model="$ctrl.entry.observation"
|
|
||||||
rule>
|
|
||||||
</vn-textarea>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-autocomplete
|
<vn-autocomplete
|
||||||
vn-one
|
vn-one
|
||||||
|
@ -63,6 +39,30 @@
|
||||||
</tpl-item>
|
</tpl-item>
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-textfield
|
||||||
|
vn-one
|
||||||
|
label="Reference"
|
||||||
|
ng-model="$ctrl.entry.ref"
|
||||||
|
rule
|
||||||
|
vn-focus>
|
||||||
|
</vn-textfield>
|
||||||
|
<vn-textfield
|
||||||
|
vn-one
|
||||||
|
label="Notes"
|
||||||
|
ng-model="$ctrl.entry.notes"
|
||||||
|
rule
|
||||||
|
vn-focus>
|
||||||
|
</vn-textfield>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-textarea
|
||||||
|
vn-one
|
||||||
|
label="Observation"
|
||||||
|
ng-model="$ctrl.entry.observation"
|
||||||
|
rule>
|
||||||
|
</vn-textarea>
|
||||||
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-autocomplete
|
<vn-autocomplete
|
||||||
vn-one
|
vn-one
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
<vn-portal slot="topbar">
|
<vn-portal slot="topbar">
|
||||||
<vn-searchbar
|
<vn-searchbar
|
||||||
|
vn-focus
|
||||||
panel="vn-latest-buys-search-panel"
|
panel="vn-latest-buys-search-panel"
|
||||||
placeholder="Search by item id or name"
|
placeholder="Search by item id or name"
|
||||||
info="You can search by item id or name"
|
info="You can search by item id or name"
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
<vn-portal slot="topbar">
|
<vn-portal slot="topbar">
|
||||||
<vn-searchbar
|
<vn-searchbar
|
||||||
|
vn-focus
|
||||||
panel="vn-entry-search-panel"
|
panel="vn-entry-search-panel"
|
||||||
info="Search entrys by id"
|
info="Search entrys by id"
|
||||||
model="model">
|
model="model">
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
<vn-portal slot="topbar">
|
<vn-portal slot="topbar">
|
||||||
<vn-searchbar
|
<vn-searchbar
|
||||||
|
vn-focus
|
||||||
panel="vn-invoice-search-panel"
|
panel="vn-invoice-search-panel"
|
||||||
info="Search invoices by reference"
|
info="Search invoices by reference"
|
||||||
model="model">
|
model="model">
|
||||||
|
|
|
@ -7,25 +7,25 @@
|
||||||
order="landed DESC, buyFk DESC"
|
order="landed DESC, buyFk DESC"
|
||||||
limit="20">
|
limit="20">
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
|
<vn-card class="vn-mb-md vn-w-xl vn-pa-lg">
|
||||||
|
<vn-date-picker
|
||||||
|
vn-none
|
||||||
|
label="Since"
|
||||||
|
ng-model="$ctrl.date">
|
||||||
|
</vn-date-picker>
|
||||||
|
</vn-card>
|
||||||
|
|
||||||
<vn-data-viewer
|
<vn-data-viewer
|
||||||
model="model"
|
model="model"
|
||||||
class="vn-mb-xl vn-w-xl">
|
class="vn-mb-xl vn-w-xl">
|
||||||
<vn-card class="vn-pa-lg">
|
<vn-card class="vn-pa-lg">
|
||||||
<vn-vertical>
|
<vn-vertical>
|
||||||
<vn-horizontal>
|
|
||||||
<vn-date-picker
|
|
||||||
vn-one
|
|
||||||
label="Since"
|
|
||||||
ng-model="$ctrl.date">
|
|
||||||
</vn-date-picker>
|
|
||||||
<!--datepicker-->
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-table model="model">
|
<vn-table model="model">
|
||||||
<vn-thead>
|
<vn-thead>
|
||||||
<vn-tr>
|
<vn-tr>
|
||||||
<vn-th vn-tooltip="Ignored" center>Ig</vn-th>
|
<vn-th vn-tooltip="Ignored" center>Ig</vn-th>
|
||||||
<vn-th field="warehouseFk">Warehouse</vn-th>
|
<vn-th field="warehouseFk">Warehouse</vn-th>
|
||||||
<vn-th field="landed">Landed</vn-th>
|
<vn-th field="landed" expand>Landed</vn-th>
|
||||||
<vn-th number>Entry</vn-th>
|
<vn-th number>Entry</vn-th>
|
||||||
<vn-th number vn-tooltip="Price Per Unit">P.P.U</vn-th>
|
<vn-th number vn-tooltip="Price Per Unit">P.P.U</vn-th>
|
||||||
<vn-th number vn-tooltip="Price Per Package">P.P.P</vn-th>
|
<vn-th number vn-tooltip="Price Per Package">P.P.P</vn-th>
|
||||||
|
@ -48,8 +48,8 @@
|
||||||
disabled="true">
|
disabled="true">
|
||||||
</vn-check>
|
</vn-check>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td>{{::entry.warehouse| dashIfEmpty}}</vn-td>
|
<vn-td title="{{::entry.warehouse| dashIfEmpty}}">{{::entry.warehouse| dashIfEmpty}}</vn-td>
|
||||||
<vn-td>{{::entry.landed | date:'dd/MM/yyyy HH:mm'}}</vn-td>
|
<vn-td expand>{{::entry.landed | date:'dd/MM/yyyy HH:mm'}}</vn-td>
|
||||||
<vn-td number>{{::entry.entryFk | dashIfEmpty}}</vn-td>
|
<vn-td number>{{::entry.entryFk | dashIfEmpty}}</vn-td>
|
||||||
<vn-td number>{{::entry.price2 | dashIfEmpty}}</vn-td>
|
<vn-td number>{{::entry.price2 | dashIfEmpty}}</vn-td>
|
||||||
<vn-td number>{{::entry.price3 | dashIfEmpty}}</vn-td>
|
<vn-td number>{{::entry.price3 | dashIfEmpty}}</vn-td>
|
||||||
|
@ -69,7 +69,7 @@
|
||||||
<vn-td number class="expendable">{{::entry.buyingValue | dashIfEmpty}}</vn-td>
|
<vn-td number class="expendable">{{::entry.buyingValue | dashIfEmpty}}</vn-td>
|
||||||
<vn-td number>{{::entry.weight | dashIfEmpty}}</vn-td>
|
<vn-td number>{{::entry.weight | dashIfEmpty}}</vn-td>
|
||||||
<vn-td number>{{::entry.packageFk | dashIfEmpty}}</vn-td>
|
<vn-td number>{{::entry.packageFk | dashIfEmpty}}</vn-td>
|
||||||
<vn-td class="expendable">{{::entry.supplier | dashIfEmpty}}</vn-td>
|
<vn-td class="expendable" title="{{::entry.supplier | dashIfEmpty}}">{{::entry.supplier | dashIfEmpty}}</vn-td>
|
||||||
</vn-tr>
|
</vn-tr>
|
||||||
</vn-tbody>
|
</vn-tbody>
|
||||||
</vn-table>
|
</vn-table>
|
||||||
|
|
|
@ -30,7 +30,16 @@ class Controller extends Section {
|
||||||
|
|
||||||
if (!value) return;
|
if (!value) return;
|
||||||
|
|
||||||
this.filter.where.date = value;
|
const from = new Date(value);
|
||||||
|
from.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
|
const to = new Date();
|
||||||
|
to.setDate(to.getDate() + 10);
|
||||||
|
to.setHours(23, 59, 59, 59);
|
||||||
|
|
||||||
|
this.filter.where.shipped = {
|
||||||
|
between: [from, to]
|
||||||
|
};
|
||||||
this.$.model.refresh();
|
this.$.model.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
<vn-portal slot="topbar">
|
<vn-portal slot="topbar">
|
||||||
<vn-searchbar
|
<vn-searchbar
|
||||||
|
vn-focus
|
||||||
panel="vn-item-search-panel"
|
panel="vn-item-search-panel"
|
||||||
info="Search items by id, name or barcode"
|
info="Search items by id, name or barcode"
|
||||||
suggested-filter="{isActive: true}"
|
suggested-filter="{isActive: true}"
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
<vn-portal slot="topbar">
|
<vn-portal slot="topbar">
|
||||||
<vn-searchbar
|
<vn-searchbar
|
||||||
|
vn-focus
|
||||||
panel="vn-order-search-panel"
|
panel="vn-order-search-panel"
|
||||||
info="Search orders by id"
|
info="Search orders by id"
|
||||||
model="model"
|
model="model"
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
<vn-portal slot="topbar">
|
<vn-portal slot="topbar">
|
||||||
<vn-searchbar
|
<vn-searchbar
|
||||||
|
vn-focus
|
||||||
panel="vn-route-search-panel"
|
panel="vn-route-search-panel"
|
||||||
info="Search routes by id"
|
info="Search routes by id"
|
||||||
filter="$ctrl.filter"
|
filter="$ctrl.filter"
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
},
|
},
|
||||||
"expenseFk": {
|
"expenseFk": {
|
||||||
"type": "Number",
|
"type": "Number",
|
||||||
"required": true,
|
|
||||||
"mysql": {
|
"mysql": {
|
||||||
"columnName": "expenceFk"
|
"columnName": "expenceFk"
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
<vn-portal slot="topbar">
|
<vn-portal slot="topbar">
|
||||||
<vn-searchbar
|
<vn-searchbar
|
||||||
|
vn-focus
|
||||||
panel="vn-ticket-search-panel"
|
panel="vn-ticket-search-panel"
|
||||||
info="Search ticket by id or alias"
|
info="Search ticket by id or alias"
|
||||||
model="model"
|
model="model"
|
||||||
|
|
|
@ -53,13 +53,6 @@
|
||||||
ng-model="service.price"
|
ng-model="service.price"
|
||||||
step="0.01">
|
step="0.01">
|
||||||
</vn-input-number>
|
</vn-input-number>
|
||||||
<vn-autocomplete vn-one
|
|
||||||
data="taxClasses"
|
|
||||||
label="Tax class"
|
|
||||||
show-field="description"
|
|
||||||
value-field="id"
|
|
||||||
ng-model="service.taxClassFk">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-auto>
|
<vn-auto>
|
||||||
<vn-icon-button
|
<vn-icon-button
|
||||||
pointer
|
pointer
|
||||||
|
@ -97,17 +90,6 @@
|
||||||
vn-focus>
|
vn-focus>
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
vn-focus
|
|
||||||
url="Expenses"
|
|
||||||
label="Expense"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
ng-model="newServiceType.expenseFk">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
</tpl-body>
|
</tpl-body>
|
||||||
<tpl-buttons>
|
<tpl-buttons>
|
||||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
<vn-portal slot="topbar">
|
<vn-portal slot="topbar">
|
||||||
<vn-searchbar
|
<vn-searchbar
|
||||||
|
vn-focus
|
||||||
placeholder="Search by weekly ticket"
|
placeholder="Search by weekly ticket"
|
||||||
info="Search weekly ticket by id or client id"
|
info="Search weekly ticket by id or client id"
|
||||||
auto-state="false"
|
auto-state="false"
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
<vn-portal slot="topbar">
|
<vn-portal slot="topbar">
|
||||||
<vn-searchbar
|
<vn-searchbar
|
||||||
|
vn-focus
|
||||||
panel="vn-travel-search-panel"
|
panel="vn-travel-search-panel"
|
||||||
info="Search travels by id"
|
info="Search travels by id"
|
||||||
model="model"
|
model="model"
|
||||||
|
|
|
@ -31,6 +31,7 @@ module.exports = Self => {
|
||||||
|
|
||||||
Self.createAbsence = async(ctx, id, absenceTypeId, dated) => {
|
Self.createAbsence = async(ctx, id, absenceTypeId, dated) => {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
|
const $t = ctx.req.__; // $translate
|
||||||
const userId = ctx.req.accessToken.userId;
|
const userId = ctx.req.accessToken.userId;
|
||||||
const isSubordinate = await models.Worker.isSubordinate(ctx, id);
|
const isSubordinate = await models.Worker.isSubordinate(ctx, id);
|
||||||
const isTeamBoss = await models.Account.hasRole(userId, 'teamBoss');
|
const isTeamBoss = await models.Account.hasRole(userId, 'teamBoss');
|
||||||
|
@ -39,6 +40,7 @@ module.exports = Self => {
|
||||||
throw new UserError(`You don't have enough privileges`);
|
throw new UserError(`You don't have enough privileges`);
|
||||||
|
|
||||||
const labour = await models.WorkerLabour.findOne({
|
const labour = await models.WorkerLabour.findOne({
|
||||||
|
include: {relation: 'department'},
|
||||||
where: {
|
where: {
|
||||||
and: [
|
and: [
|
||||||
{workerFk: id},
|
{workerFk: id},
|
||||||
|
@ -49,10 +51,42 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return models.Calendar.create({
|
const absence = await models.Calendar.create({
|
||||||
businessFk: labour.businessFk,
|
businessFk: labour.businessFk,
|
||||||
dayOffTypeFk: absenceTypeId,
|
dayOffTypeFk: absenceTypeId,
|
||||||
dated: dated
|
dated: dated
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const department = labour.department();
|
||||||
|
if (department && department.notificationEmail) {
|
||||||
|
const absenceType = await models.AbsenceType.findById(absenceTypeId);
|
||||||
|
const account = await models.Account.findById(userId);
|
||||||
|
const subordinated = await models.Account.findById(id);
|
||||||
|
const origin = ctx.req.headers.origin;
|
||||||
|
const body = $t('Created absence', {
|
||||||
|
author: account.nickname,
|
||||||
|
employee: subordinated.nickname,
|
||||||
|
absenceType: absenceType.name,
|
||||||
|
dated: formatDate(dated),
|
||||||
|
workerUrl: `${origin}/#!/worker/${id}/calendar`
|
||||||
|
});
|
||||||
|
await models.Mail.create({
|
||||||
|
subject: $t('Absence change notification on the labour calendar'),
|
||||||
|
body: body,
|
||||||
|
sender: department.notificationEmail
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return absence;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function formatDate(date) {
|
||||||
|
let day = date.getDate();
|
||||||
|
if (day < 10) day = `0${day}`;
|
||||||
|
let month = date.getMonth();
|
||||||
|
if (month < 10) month = `0${month}`;
|
||||||
|
let year = date.getFullYear();
|
||||||
|
|
||||||
|
return `${day}-${month}-${year}`;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,6 +23,7 @@ module.exports = Self => {
|
||||||
|
|
||||||
Self.deleteAbsence = async(ctx, id, absenceId) => {
|
Self.deleteAbsence = async(ctx, id, absenceId) => {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
|
const $t = ctx.req.__; // $translate
|
||||||
const userId = ctx.req.accessToken.userId;
|
const userId = ctx.req.accessToken.userId;
|
||||||
const isSubordinate = await models.Worker.isSubordinate(ctx, id);
|
const isSubordinate = await models.Worker.isSubordinate(ctx, id);
|
||||||
const isTeamBoss = await models.Account.hasRole(userId, 'teamBoss');
|
const isTeamBoss = await models.Account.hasRole(userId, 'teamBoss');
|
||||||
|
@ -30,8 +31,46 @@ module.exports = Self => {
|
||||||
if (!isSubordinate || (isSubordinate && userId == id && !isTeamBoss))
|
if (!isSubordinate || (isSubordinate && userId == id && !isTeamBoss))
|
||||||
throw new UserError(`You don't have enough privileges`);
|
throw new UserError(`You don't have enough privileges`);
|
||||||
|
|
||||||
const absence = await models.Calendar.findById(absenceId);
|
const absence = await models.Calendar.findById(absenceId, {
|
||||||
|
include: {
|
||||||
|
relation: 'labour',
|
||||||
|
scope: {
|
||||||
|
include: {relation: 'department'}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const result = await absence.destroy();
|
||||||
|
const labour = absence.labour();
|
||||||
|
const department = labour && labour.department();
|
||||||
|
if (department && department.notificationEmail) {
|
||||||
|
const absenceType = await models.AbsenceType.findById(absence.dayOffTypeFk);
|
||||||
|
const account = await models.Account.findById(userId);
|
||||||
|
const subordinated = await models.Account.findById(labour.workerFk);
|
||||||
|
const origin = ctx.req.headers.origin;
|
||||||
|
const body = $t('Deleted absence', {
|
||||||
|
author: account.nickname,
|
||||||
|
employee: subordinated.nickname,
|
||||||
|
absenceType: absenceType.name,
|
||||||
|
dated: formatDate(absence.dated),
|
||||||
|
workerUrl: `${origin}/#!/worker/${id}/calendar`
|
||||||
|
});
|
||||||
|
await models.Mail.create({
|
||||||
|
subject: $t('Absence change notification on the labour calendar'),
|
||||||
|
body: body,
|
||||||
|
sender: department.notificationEmail
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return absence.destroy();
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function formatDate(date) {
|
||||||
|
let day = date.getDate();
|
||||||
|
if (day < 10) day = `0${day}`;
|
||||||
|
let month = date.getMonth();
|
||||||
|
if (month < 10) month = `0${month}`;
|
||||||
|
let year = date.getFullYear();
|
||||||
|
|
||||||
|
return `${day}-${month}-${year}`;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,16 +1,11 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('Worker createAbsence()', () => {
|
describe('Worker createAbsence()', () => {
|
||||||
const workerId = 106;
|
const workerId = 18;
|
||||||
let createdAbsence;
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
const absence = await app.models.Calendar.findById(createdAbsence.id);
|
|
||||||
await absence.destroy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return an error for a user without enough privileges', async() => {
|
it('should return an error for a user without enough privileges', async() => {
|
||||||
const ctx = {req: {accessToken: {userId: 106}}};
|
const ctx = {req: {accessToken: {userId: 18}}};
|
||||||
const absenceTypeId = 1;
|
const absenceTypeId = 1;
|
||||||
const dated = new Date();
|
const dated = new Date();
|
||||||
|
|
||||||
|
@ -25,15 +20,29 @@ describe('Worker createAbsence()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create a new absence', async() => {
|
it('should create a new absence', async() => {
|
||||||
const ctx = {req: {accessToken: {userId: 37}}};
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 19},
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
};
|
||||||
|
const ctx = {req: activeCtx};
|
||||||
|
ctx.req.__ = value => {
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: activeCtx
|
||||||
|
});
|
||||||
|
|
||||||
const absenceTypeId = 1;
|
const absenceTypeId = 1;
|
||||||
const dated = new Date();
|
const dated = new Date();
|
||||||
createdAbsence = await app.models.Worker.createAbsence(ctx, workerId, absenceTypeId, dated);
|
const createdAbsence = await app.models.Worker.createAbsence(ctx, workerId, absenceTypeId, dated);
|
||||||
|
|
||||||
const expectedBusinessId = 106;
|
const expectedBusinessId = 18;
|
||||||
const expectedAbsenceTypeId = 1;
|
const expectedAbsenceTypeId = 1;
|
||||||
|
|
||||||
expect(createdAbsence.businessFk).toEqual(expectedBusinessId);
|
expect(createdAbsence.businessFk).toEqual(expectedBusinessId);
|
||||||
expect(createdAbsence.dayOffTypeFk).toEqual(expectedAbsenceTypeId);
|
expect(createdAbsence.dayOffTypeFk).toEqual(expectedAbsenceTypeId);
|
||||||
|
|
||||||
|
// Restores
|
||||||
|
await app.models.Calendar.destroyById(createdAbsence.id);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,20 +1,39 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('Worker deleteAbsence()', () => {
|
describe('Worker deleteAbsence()', () => {
|
||||||
const workerId = 106;
|
const businessId = 18;
|
||||||
|
const workerId = 18;
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 106},
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
};
|
||||||
|
const ctx = {req: activeCtx};
|
||||||
|
ctx.req.__ = value => {
|
||||||
|
return value;
|
||||||
|
};
|
||||||
let createdAbsence;
|
let createdAbsence;
|
||||||
|
|
||||||
it('should return an error for a user without enough privileges', async() => {
|
beforeEach(async() => {
|
||||||
const ctx = {req: {accessToken: {userId: 106}}};
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
const businessId = 106;
|
active: activeCtx
|
||||||
|
});
|
||||||
createdAbsence = await app.models.Calendar.create({
|
createdAbsence = await app.models.Calendar.create({
|
||||||
businessFk: businessId,
|
businessFk: businessId,
|
||||||
dayOffTypeFk: 1,
|
dayOffTypeFk: 1,
|
||||||
dated: new Date()
|
dated: new Date()
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async() => {
|
||||||
|
await app.models.Calendar.destroyById(createdAbsence.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an error for a user without enough privileges', async() => {
|
||||||
|
activeCtx.accessToken.userId = 106;
|
||||||
|
|
||||||
let error;
|
let error;
|
||||||
await app.models.Worker.deleteAbsence(ctx, workerId, createdAbsence.id).catch(e => {
|
await app.models.Worker.deleteAbsence(ctx, 18, createdAbsence.id).catch(e => {
|
||||||
error = e;
|
error = e;
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
expect(error.message).toEqual(`You don't have enough privileges`);
|
expect(error.message).toEqual(`You don't have enough privileges`);
|
||||||
|
@ -24,8 +43,7 @@ describe('Worker deleteAbsence()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create a new absence', async() => {
|
it('should create a new absence', async() => {
|
||||||
const ctx = {req: {accessToken: {userId: 37}}};
|
activeCtx.accessToken.userId = 19;
|
||||||
const businessId = 106;
|
|
||||||
|
|
||||||
expect(createdAbsence.businessFk).toEqual(businessId);
|
expect(createdAbsence.businessFk).toEqual(businessId);
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,37 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
describe('Worker updateAbsence()', () => {
|
describe('Worker updateAbsence()', () => {
|
||||||
const workerId = 106;
|
const workerId = 106;
|
||||||
|
const businessId = 106;
|
||||||
|
const activeCtx = {
|
||||||
|
accessToken: {userId: 106},
|
||||||
|
headers: {origin: 'http://localhost'}
|
||||||
|
};
|
||||||
|
const ctx = {req: activeCtx};
|
||||||
|
ctx.req.__ = value => {
|
||||||
|
return value;
|
||||||
|
};
|
||||||
let createdAbsence;
|
let createdAbsence;
|
||||||
|
|
||||||
afterAll(async() => {
|
beforeEach(async() => {
|
||||||
const absence = await app.models.Calendar.findById(createdAbsence.id);
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
await absence.destroy();
|
active: activeCtx
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return an error for a user without enough privileges', async() => {
|
|
||||||
const ctx = {req: {accessToken: {userId: 106}}};
|
|
||||||
const expectedAbsenceTypeId = 2;
|
|
||||||
createdAbsence = await app.models.Calendar.create({
|
createdAbsence = await app.models.Calendar.create({
|
||||||
businessFk: 106,
|
businessFk: businessId,
|
||||||
dayOffTypeFk: 1,
|
dayOffTypeFk: 1,
|
||||||
dated: new Date()
|
dated: new Date()
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async() => {
|
||||||
|
await app.models.Calendar.destroyById(createdAbsence.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an error for a user without enough privileges', async() => {
|
||||||
|
activeCtx.accessToken.userId = 106;
|
||||||
|
const expectedAbsenceTypeId = 2;
|
||||||
|
|
||||||
let error;
|
let error;
|
||||||
await app.models.Worker.updateAbsence(ctx, workerId, createdAbsence.id, expectedAbsenceTypeId).catch(e => {
|
await app.models.Worker.updateAbsence(ctx, workerId, createdAbsence.id, expectedAbsenceTypeId).catch(e => {
|
||||||
|
@ -29,7 +44,7 @@ describe('Worker updateAbsence()', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create a new absence', async() => {
|
it('should create a new absence', async() => {
|
||||||
const ctx = {req: {accessToken: {userId: 37}}};
|
activeCtx.accessToken.userId = 37;
|
||||||
const expectedAbsenceTypeId = 2;
|
const expectedAbsenceTypeId = 2;
|
||||||
const updatedAbsence = await app.models.Worker.updateAbsence(ctx, workerId, createdAbsence.id, expectedAbsenceTypeId);
|
const updatedAbsence = await app.models.Worker.updateAbsence(ctx, workerId, createdAbsence.id, expectedAbsenceTypeId);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
{
|
{
|
||||||
"name": "Calendar",
|
"name": "Calendar",
|
||||||
"base": "VnModel",
|
"base": "Loggable",
|
||||||
|
"log": {
|
||||||
|
"model": "WorkerLog",
|
||||||
|
"relation": "labour"
|
||||||
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"mysql": {
|
"mysql": {
|
||||||
"table": "calendar"
|
"table": "calendar"
|
||||||
|
@ -23,6 +27,11 @@
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "AbsenceType",
|
"model": "AbsenceType",
|
||||||
"foreignKey": "dayOffTypeFk"
|
"foreignKey": "dayOffTypeFk"
|
||||||
|
},
|
||||||
|
"labour": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "WorkerLabour",
|
||||||
|
"foreignKey": "businessFk"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,9 @@
|
||||||
},
|
},
|
||||||
"chatName": {
|
"chatName": {
|
||||||
"type": "String"
|
"type": "String"
|
||||||
|
},
|
||||||
|
"notificationEmail": {
|
||||||
|
"type": "String"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
<vn-portal slot="topbar">
|
<vn-portal slot="topbar">
|
||||||
<vn-searchbar
|
<vn-searchbar
|
||||||
|
vn-focus
|
||||||
panel="vn-worker-search-panel"
|
panel="vn-worker-search-panel"
|
||||||
info="Search workers by id, firstName, lastName or user name"
|
info="Search workers by id, firstName, lastName or user name"
|
||||||
model="model">
|
model="model">
|
||||||
|
|
|
@ -63,7 +63,7 @@
|
||||||
"state": "worker.card.workerLog",
|
"state": "worker.card.workerLog",
|
||||||
"component": "vn-worker-log",
|
"component": "vn-worker-log",
|
||||||
"description": "Log",
|
"description": "Log",
|
||||||
"acl": ["hr"]
|
"acl": ["salesAssistant"]
|
||||||
}, {
|
}, {
|
||||||
"url": "/pbx",
|
"url": "/pbx",
|
||||||
"state": "worker.card.pbx",
|
"state": "worker.card.pbx",
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
<vn-portal slot="topbar">
|
<vn-portal slot="topbar">
|
||||||
<vn-searchbar
|
<vn-searchbar
|
||||||
|
vn-focus
|
||||||
info="Search zone by id or name"
|
info="Search zone by id or name"
|
||||||
panel="vn-zone-search-panel"
|
panel="vn-zone-search-panel"
|
||||||
model="model"
|
model="model"
|
||||||
|
|
|
@ -5835,7 +5835,7 @@
|
||||||
},
|
},
|
||||||
"util": {
|
"util": {
|
||||||
"version": "0.10.3",
|
"version": "0.10.3",
|
||||||
"resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz",
|
"resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
|
||||||
"integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
|
"integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -6806,7 +6806,7 @@
|
||||||
"base": {
|
"base": {
|
||||||
"version": "0.11.2",
|
"version": "0.11.2",
|
||||||
"resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
|
"resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
|
||||||
"integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
|
"integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"cache-base": "^1.0.1",
|
"cache-base": "^1.0.1",
|
||||||
|
@ -6916,9 +6916,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"bl": {
|
"bl": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/bl/-/bl-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz",
|
||||||
"integrity": "sha512-wbgvOpqopSr7uq6fJrLH8EsvYMJf9gzfo2jCsL2eTy75qXPukA4pCgHamOQkZtY5vmfVtjB+P3LNlMHW5CEZXA==",
|
"integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"readable-stream": "^2.3.5",
|
"readable-stream": "^2.3.5",
|
||||||
"safe-buffer": "^5.1.1"
|
"safe-buffer": "^5.1.1"
|
||||||
|
@ -7329,7 +7329,7 @@
|
||||||
"cache-base": {
|
"cache-base": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
|
||||||
"integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
|
"integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"collection-visit": "^1.0.0",
|
"collection-visit": "^1.0.0",
|
||||||
|
@ -7543,7 +7543,7 @@
|
||||||
"class-utils": {
|
"class-utils": {
|
||||||
"version": "0.3.6",
|
"version": "0.3.6",
|
||||||
"resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
|
||||||
"integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
|
"integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"arr-union": "^3.1.0",
|
"arr-union": "^3.1.0",
|
||||||
|
@ -9796,7 +9796,7 @@
|
||||||
},
|
},
|
||||||
"file-loader": {
|
"file-loader": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"resolved": "http://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/file-loader/-/file-loader-1.1.11.tgz",
|
||||||
"integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==",
|
"integrity": "sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -10982,7 +10982,7 @@
|
||||||
"global-modules": {
|
"global-modules": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
|
||||||
"integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==",
|
"integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"global-prefix": "^1.0.1",
|
"global-prefix": "^1.0.1",
|
||||||
|
@ -13207,7 +13207,7 @@
|
||||||
"is-plain-object": {
|
"is-plain-object": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
|
||||||
"integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
|
"integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"isobject": "^3.0.1"
|
"isobject": "^3.0.1"
|
||||||
|
@ -13541,7 +13541,7 @@
|
||||||
"jasmine-spec-reporter": {
|
"jasmine-spec-reporter": {
|
||||||
"version": "4.2.1",
|
"version": "4.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz",
|
||||||
"integrity": "sha512-FZBoZu7VE5nR7Nilzy+Np8KuVIOxF4oXDPDknehCYBDE080EnlPu0afdZNmpGDBRCUBv3mj5qgqCRmk6W/K8vg==",
|
"integrity": "sha1-HWMq7ANBZwrTJPkrqEtLMrNeniI=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"colors": "1.1.2"
|
"colors": "1.1.2"
|
||||||
|
@ -22227,7 +22227,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jsesc": {
|
"jsesc": {
|
||||||
"version": "0.5.0",
|
"version": "0.5.0",
|
||||||
"resolved": "http://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
|
||||||
"integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
|
"integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
|
@ -22620,7 +22620,7 @@
|
||||||
},
|
},
|
||||||
"safe-regex": {
|
"safe-regex": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
|
||||||
"integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
|
"integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -22834,7 +22834,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"source-map": {
|
"source-map": {
|
||||||
"version": "0.4.4",
|
"version": "0.4.4",
|
||||||
"resolved": "http://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
|
||||||
"integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
|
"integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
@ -22850,18 +22850,18 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"selfsigned": {
|
"selfsigned": {
|
||||||
"version": "1.10.7",
|
"version": "1.10.8",
|
||||||
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.7.tgz",
|
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.8.tgz",
|
||||||
"integrity": "sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA==",
|
"integrity": "sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"node-forge": "0.9.0"
|
"node-forge": "^0.10.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"node-forge": {
|
"node-forge": {
|
||||||
"version": "0.9.0",
|
"version": "0.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
|
||||||
"integrity": "sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ==",
|
"integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23295,7 +23295,7 @@
|
||||||
"snapdragon-node": {
|
"snapdragon-node": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
|
||||||
"integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
|
"integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"define-property": "^1.0.0",
|
"define-property": "^1.0.0",
|
||||||
|
@ -23346,7 +23346,7 @@
|
||||||
"snapdragon-util": {
|
"snapdragon-util": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
|
||||||
"integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
|
"integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"kind-of": "^3.2.0"
|
"kind-of": "^3.2.0"
|
||||||
|
@ -23630,7 +23630,7 @@
|
||||||
"split-string": {
|
"split-string": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
|
||||||
"integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
|
"integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"extend-shallow": "^3.0.0"
|
"extend-shallow": "^3.0.0"
|
||||||
|
@ -24941,7 +24941,7 @@
|
||||||
"touch": {
|
"touch": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
|
||||||
"integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==",
|
"integrity": "sha1-/jZfX3XsntTlaCXgu3bSSrdK+Ds=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"nopt": "~1.0.10"
|
"nopt": "~1.0.10"
|
||||||
|
@ -26733,7 +26733,7 @@
|
||||||
},
|
},
|
||||||
"xmlbuilder": {
|
"xmlbuilder": {
|
||||||
"version": "9.0.7",
|
"version": "9.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
|
"resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
|
||||||
"integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0="
|
"integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0="
|
||||||
},
|
},
|
||||||
"xmlchars": {
|
"xmlchars": {
|
||||||
|
|
Loading…
Reference in New Issue