diff --git a/db/changes/10430-ash/00-aclAgency.sql b/db/changes/10430-ash/00-aclAgency.sql deleted file mode 100644 index 2134285cbf..0000000000 --- a/db/changes/10430-ash/00-aclAgency.sql +++ /dev/null @@ -1,2 +0,0 @@ -INSERT INTO salix.ACL (id, model, property, accessType, permission, principalType, principalId) -VALUES(301, 'Agency', '*', 'READ', 'ALLOW', 'ROLE', 'employee'); diff --git a/db/changes/10440-fallas/00-aclAgency.sql b/db/changes/10440-fallas/00-aclAgency.sql new file mode 100644 index 0000000000..9e5bb6382d --- /dev/null +++ b/db/changes/10440-fallas/00-aclAgency.sql @@ -0,0 +1,2 @@ +INSERT INTO `salix`.`ACL` (`id`, `model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) + VALUES(304, 'Agency', '*', '*', 'ALLOW', 'ROLE', 'employee'); diff --git a/db/changes/10440-fallas/00-aclSupplierAgencyTerms.sql b/db/changes/10440-fallas/00-aclSupplierAgencyTerms.sql new file mode 100644 index 0000000000..fa57c1d646 --- /dev/null +++ b/db/changes/10440-fallas/00-aclSupplierAgencyTerms.sql @@ -0,0 +1,3 @@ +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) + VALUES + ('SupplierAgencyTerm', '*', '*', 'ALLOW', 'ROLE', 'administrative'); diff --git a/db/changes/10430-ash/00-agencyTerm.sql b/db/changes/10440-fallas/00-agencyTermConfig.sql similarity index 100% rename from db/changes/10430-ash/00-agencyTerm.sql rename to db/changes/10440-fallas/00-agencyTermConfig.sql diff --git a/db/changes/10440-fallas/00-supplierAgencyTerm.sql b/db/changes/10440-fallas/00-supplierAgencyTerm.sql new file mode 100644 index 0000000000..f8539f6075 --- /dev/null +++ b/db/changes/10440-fallas/00-supplierAgencyTerm.sql @@ -0,0 +1,48 @@ +ALTER TABLE `vn`.`agencyTerm` ADD `supplierFk` INT NULL; +ALTER TABLE `vn`.`agencyTerm` CHANGE `supplierFk` `supplierFk` INT NULL AFTER `agencyFk`; + +UPDATE `vn`.`agencyTerm` `at` + JOIN `vn`.`agency` `a` ON `a`.`id` = `at`.`agencyFk` +SET `at`.`supplierFk` = `a`.`supplierFk`; + +ALTER TABLE `vn`.`agencyTerm` ADD CONSTRAINT `agencyTerm_FK` FOREIGN KEY (`agencyFk`) REFERENCES `vn`.`agency`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; +ALTER TABLE `vn`.`agencyTerm` ADD CONSTRAINT `agencyTerm_FK_1` FOREIGN KEY (`supplierFk`) REFERENCES `vn`.`supplier`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; + +RENAME TABLE `vn`.`agencyTerm` TO `vn`.`supplierAgencyTerm`; + +CREATE OR REPLACE +ALGORITHM = UNDEFINED +DEFINER=`root`@`localhost` +VIEW `vn`.`agencyTerm` AS +SELECT + `sat`.`agencyFk` AS `agencyFk`, + `sat`.`minimumPackages` AS `minimumPackages`, + `sat`.`kmPrice` AS `kmPrice`, + `sat`.`packagePrice` AS `packagePrice`, + `sat`.`routePrice` AS `routePrice`, + `sat`.`minimumKm` AS `minimumKm`, + `sat`.`minimumM3` AS `minimumM3`, + `sat`.`m3Price` AS `m3Price` +FROM + `vn`.`supplierAgencyTerm` `sat`; + +ALTER TABLE `vn`.`agency` DROP FOREIGN KEY `agency_ibfk_4`; +ALTER TABLE `vn`.`agency` CHANGE `supplierFk` `supplierFk__` int(11) DEFAULT NULL NULL; + +CREATE OR REPLACE +ALGORITHM = UNDEFINED +DEFINER=`root`@`localhost` +VIEW `vn2008`.`agency` AS +SELECT + `a`.`id` AS `agency_id`, + `a`.`name` AS `name`, + `a`.`warehouseFk` AS `warehouse_id`, + `a`.`isVolumetric` AS `por_volumen`, + `a`.`bankFk` AS `Id_Banco`, + `a`.`warehouseAliasFk` AS `warehouse_alias_id`, + `a`.`isOwn` AS `propios`, + `a`.`labelZone` AS `zone_label`, + `a`.`workCenterFk` AS `workCenterFk`, + `a`.`supplierFk__` AS `supplierFk__` +FROM + `vn`.`agency` `a`; \ No newline at end of file diff --git a/db/changes/10440-fallas/00-workerBusinessType.sql b/db/changes/10440-fallas/00-workerBusinessType.sql new file mode 100644 index 0000000000..489caa6c9e --- /dev/null +++ b/db/changes/10440-fallas/00-workerBusinessType.sql @@ -0,0 +1,3 @@ +ALTER TABLE `postgresql`.`business_labour_payroll` DROP FOREIGN KEY `business_labour_payroll_cod_contrato`; +ALTER TABLE `vn`.`workerBusinessType` MODIFY COLUMN `id` int(11) NOT NULL; +ALTER TABLE `postgresql`.`business_labour_payroll` ADD CONSTRAINT `business_labour_payroll_FK` FOREIGN KEY (cod_contrato) REFERENCES `vn`.`workerBusinessType`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 23f625e7ff..aa03c39b56 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -1902,14 +1902,29 @@ INSERT INTO `vn`.`workCenterHoliday` (`workCenterFk`, `days`, `year`) ('1', '24.5', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 YEAR))), ('5', '23', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 YEAR))); -INSERT INTO `postgresql`.`calendar_state` (`calendar_state_id`, `type`, `rgb`, `code`, `holidayEntitlementRate`) +INSERT INTO `postgresql`.`calendar_state` (`calendar_state_id`, `type`, `rgb`, `code`, `holidayEntitlementRate`, `discountRate`) VALUES - (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); + (1, 'Holidays', '#FF4444', 'holiday', 0, 0), + (2, 'Leave of absence', '#C71585', 'absence', 0, 1), + (6, 'Half holiday', '#E65F00', 'halfHoliday', 0, 0.5), + (15, 'Half Paid Leave', '#5151c0', 'halfPaidLeave', 0, 1), + (20, 'Furlough', '#97B92F', 'furlough', 1, 1), + (21, 'Furlough half day', '#778899', 'halfFurlough', 0.5, 1); + +ALTER TABLE `postgresql`.`business_labour_payroll` DROP FOREIGN KEY `business_labour_payroll_cod_categoria`; + +INSERT INTO `vn`.`workerBusinessType` (`id`, `name`, `isFullTime`, `isPermanent`, `hasHolidayEntitlement`) + VALUES + (1, 'CONTRATO HOLANDA', 1, 0, 1), + (100, 'INDEFINIDO A TIEMPO COMPLETO', 1, 1, 1), + (109, 'CONVERSION DE TEMPORAL EN INDEFINIDO T.COMPLETO', 1, 1, 1); + +INSERT INTO `postgresql`.`business_labour_payroll` (`business_id`, `cod_tarifa`, `cod_categoria`, `cod_contrato`, `importepactado`) + VALUES + (1, 7, 12, 100, 900.50), + (1106, 7, 12, 100, 1263.03), + (1107, 7, 12, 100, 2000), + (1108, 7, 12, 100, 1500); INSERT INTO `postgresql`.`calendar_employee` (`business_id`, `calendar_state_id`, `date`) VALUES @@ -2462,28 +2477,25 @@ INSERT INTO `bs`.`defaulter` (`clientFk`, `amount`, `created`, `defaulterSinced` (1107, 500, CURDATE(), CURDATE()), (1109, 500, CURDATE(), CURDATE()); -INSERT INTO `vn`.`agencyTerm` (`agencyFk`, `minimumPackages`, `kmPrice`, `packagePrice`, `routePrice`, `minimumKm`, `minimumM3`, `m3Price`) - VALUES - (1, 0, 0.00, 0.00, NULL, 0, 0.00, 0), - (3, 0, 0.00, 3.05, NULL, 0, 0.00, 0), - (2, 60, 0.00, 0.00, NULL, 0, 5.00, 33); +UPDATE `vn`.`agency` + SET `supplierFk`=1 + WHERE `id`=1; UPDATE `vn`.`agency` -SET `supplierFk`=1 -WHERE `id`=1; + SET `supplierFk`=1 + WHERE `id`=2; + UPDATE `vn`.`agency` -SET `supplierFk`=1 -WHERE `id`=2; -UPDATE `vn`.`agency` -SET `supplierFk`=2 -WHERE `id`=3; + SET `supplierFk`=2 + WHERE `id`=3; UPDATE `vn`.`route` -SET `invoiceInFk`=1 -WHERE `id`=1; + SET `invoiceInFk`=1 + WHERE `id`=1; + UPDATE `vn`.`route` -SET `invoiceInFk`=2 -WHERE `id`=2; + SET `invoiceInFk`=2 + WHERE `id`=2; INSERT INTO `bs`.`salesPerson` (`workerFk`, `year`, `month`, `portfolioWeight`) VALUES (18, YEAR(CURDATE()), MONTH(CURDATE()), 807.23), @@ -2496,6 +2508,7 @@ INSERT INTO `bs`.`sale` (`saleFk`, `amount`, `dated`, `typeFk`, `clientFk`) (3, 200.78, CURDATE(), 2, 1101), (4, 33.8, CURDATE(), 1, 1101), (30, 34.4, CURDATE(), 1, 1108); + INSERT INTO `vn`.`docuware` (`code`, `fileCabinetName`, `dialogName` , `find`) VALUES ('deliveryClientTest', 'deliveryClientTest', 'findTest', 'word'); @@ -2503,3 +2516,23 @@ INSERT INTO `vn`.`docuware` (`code`, `fileCabinetName`, `dialogName` , `find`) INSERT INTO `vn`.`docuwareConfig` (`url`) VALUES ('https://verdnatura.docuware.cloud/docuware/platform'); + +INSERT INTO `vn`.`calendarHolidaysName` (`id`, `name`) + VALUES + (1, 'dayOfIT'); + +INSERT INTO `vn`.`calendarHolidaysType` (`id`, `name`, `hexColour`) + VALUES + (1, 'National', '#4169E1'); + +INSERT INTO `vn`.`calendarHolidays` (`id`, `calendarHolidaysTypeFk`, `dated`, `calendarHolidaysNameFk`, `workCenterFk`) + VALUES + (1, 1, CONCAT(YEAR(CURDATE()), '-12-09'), 1, 1); + +INSERT INTO `vn`.`supplierAgencyTerm` (`agencyFk`, `supplierFk`, `minimumPackages`, `kmPrice`, `packagePrice`, `routePrice`, `minimumKm`, `minimumM3`, `m3Price`) + VALUES + (1, 1, 0, 0.00, 0.00, NULL, 0, 0.00, 23), + (2, 1, 60, 0.00, 0.00, NULL, 0, 5.00, 33), + (3, 2, 0, 15.00, 0.00, NULL, 0, 0.00, 0), + (4, 2, 0, 20.00, 0.00, NULL, 0, 0.00, 0), + (5, 442, 0, 0.00, 3.05, NULL, 0, 0.00, 0); diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 21abc6e9e4..f7c0dad541 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -221,6 +221,7 @@ "Can't transfer claimed sales": "No puedes transferir lineas reclamadas", "You don't have privileges to create pay back": "No tienes permisos para crear un abono", "The item is required": "El artículo es requerido", + "The agency is already assigned to another autonomous": "La agencia ya está asignada a otro autónomo", "date in the future": "Fecha en el futuro", "reference duplicated": "Referencia duplicada" } \ No newline at end of file diff --git a/modules/route/back/methods/agency-term/filter.js b/modules/route/back/methods/agency-term/filter.js index ee79a04a7f..5a9cbb5642 100644 --- a/modules/route/back/methods/agency-term/filter.js +++ b/modules/route/back/methods/agency-term/filter.js @@ -87,21 +87,21 @@ module.exports = Self => { SUM(t.packages) packages, r.m3, r.kmEnd - r.kmStart kmTotal, - CAST(IFNULL(ate.routePrice, - (ate.kmPrice * (GREATEST(r.kmEnd - r.kmStart , ate.minimumKm)) - + GREATEST(r.m3 , ate.minimumM3) * ate.m3Price) - + ate.packagePrice * SUM(t.packages) ) + CAST(IFNULL(sat.routePrice, + (sat.kmPrice * (GREATEST(r.kmEnd - r.kmStart , sat.minimumKm)) + + GREATEST(r.m3 , sat.minimumM3) * sat.m3Price) + + sat.packagePrice * SUM(t.packages) ) AS DECIMAL(10,2)) price, r.invoiceInFk, - a.supplierFk, + sat.supplierFk, s.name supplierName FROM vn.route r LEFT JOIN vn.agencyMode am ON r.agencyModeFk = am.id LEFT JOIN vn.agency a ON am.agencyFk = a.id LEFT JOIN vn.ticket t ON t.routeFk = r.id - LEFT JOIN vn.agencyTerm ate ON ate.agencyFk = a.id - LEFT JOIN vn.supplier s ON s.id = a.supplierFk - WHERE r.created > DATE_ADD(CURDATE(), INTERVAL -2 MONTH) AND a.supplierFk IS NOT NULL + LEFT JOIN vn.supplierAgencyTerm sat ON sat.agencyFk = a.id + LEFT JOIN vn.supplier s ON s.id = sat.supplierFk + WHERE r.created > DATE_ADD(CURDATE(), INTERVAL -2 MONTH) AND sat.supplierFk IS NOT NULL GROUP BY r.id ) a` ); diff --git a/modules/route/back/methods/agency-term/specs/filter.spec.js b/modules/route/back/methods/agency-term/specs/filter.spec.js index 2f00b1de26..d6c00e5858 100644 --- a/modules/route/back/methods/agency-term/specs/filter.spec.js +++ b/modules/route/back/methods/agency-term/specs/filter.spec.js @@ -18,7 +18,7 @@ describe('AgencyTerm filter()', () => { const firstAgencyTerm = agencyTerms[0]; expect(firstAgencyTerm.routeFk).toEqual(1); - expect(agencyTerms.length).toEqual(3); + expect(agencyTerms.length).toEqual(5); await tx.rollback(); } catch (e) { @@ -72,7 +72,7 @@ describe('AgencyTerm filter()', () => { const results = await models.AgencyTerm.filter(ctx, options); - expect(results.length).toBe(3); + expect(results.length).toBe(5); await tx.rollback(); } catch (e) { diff --git a/modules/supplier/back/methods/supplier/freeAgencies.js b/modules/supplier/back/methods/supplier/freeAgencies.js new file mode 100644 index 0000000000..48c027e4ed --- /dev/null +++ b/modules/supplier/back/methods/supplier/freeAgencies.js @@ -0,0 +1,42 @@ +const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; +const mergeFilters = require('vn-loopback/util/filter').mergeFilters; + +module.exports = Self => { + Self.remoteMethod('freeAgencies', { + description: 'Returns a list of agencies without a supplier assigned', + 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: `/freeAgencies`, + verb: 'GET' + } + }); + + Self.freeAgencies = async(filter, options) => { + const conn = Self.dataSource.connector; + const where = {'sat.supplierFk': null}; + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + filter = mergeFilters(filter, {where}); + + let stmt = new ParameterizedSQL( + `SELECT a.name, a.id + FROM agency a + LEFT JOIN supplierAgencyTerm sat ON sat.agencyFk = a.id`, + null, myOptions); + + stmt.merge(conn.makeSuffix(filter)); + + return conn.executeStmt(stmt); + }; +}; diff --git a/modules/supplier/back/model-config.json b/modules/supplier/back/model-config.json index 7febc17b47..7c1bba1ec6 100644 --- a/modules/supplier/back/model-config.json +++ b/modules/supplier/back/model-config.json @@ -11,6 +11,9 @@ "SupplierAccount": { "dataSource": "vn" }, + "SupplierAgencyTerm": { + "dataSource": "vn" + }, "SupplierLog": { "dataSource": "vn" }, diff --git a/modules/supplier/back/models/supplier-agency-term.js b/modules/supplier/back/models/supplier-agency-term.js new file mode 100644 index 0000000000..961413c18f --- /dev/null +++ b/modules/supplier/back/models/supplier-agency-term.js @@ -0,0 +1,9 @@ +const UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + Self.rewriteDbError(function(err) { + if (err.code === 'ER_DUP_ENTRY') + return new UserError(`The agency is already assigned to another autonomous`); + return err; + }); +}; diff --git a/modules/supplier/back/models/supplier-agency-term.json b/modules/supplier/back/models/supplier-agency-term.json new file mode 100644 index 0000000000..f9c39729af --- /dev/null +++ b/modules/supplier/back/models/supplier-agency-term.json @@ -0,0 +1,46 @@ +{ + "name": "SupplierAgencyTerm", + "base": "VnModel", + "options": { + "mysql": { + "table": "supplierAgencyTerm" + } + }, + "properties": { + "agencyFk": { + "type": "number", + "id": true + }, + "supplierFk": { + "type": "number" + }, + "minimumPackages": { + "type": "number" + }, + "kmPrice": { + "type": "number" + }, + "packagePrice": { + "type": "number" + }, + "routePrice": { + "type": "number" + }, + "minimumKm": { + "type": "number" + }, + "minimumM3": { + "type": "number" + }, + "m3Price": { + "type": "number" + } + }, + "relations": { + "agency": { + "type": "belongsTo", + "model": "Agency", + "foreignKey": "agencyFk" + } + } +} \ No newline at end of file diff --git a/modules/supplier/back/models/supplier.js b/modules/supplier/back/models/supplier.js index f8b096b305..c1be3488fc 100644 --- a/modules/supplier/back/models/supplier.js +++ b/modules/supplier/back/models/supplier.js @@ -7,6 +7,7 @@ module.exports = Self => { require('../methods/supplier/getSummary')(Self); require('../methods/supplier/updateFiscalData')(Self); require('../methods/supplier/consumption')(Self); + require('../methods/supplier/freeAgencies')(Self); Self.validatesPresenceOf('name', { message: 'The social name cannot be empty' diff --git a/modules/supplier/front/agency-term/create/index.html b/modules/supplier/front/agency-term/create/index.html new file mode 100644 index 0000000000..e43f6396af --- /dev/null +++ b/modules/supplier/front/agency-term/create/index.html @@ -0,0 +1,74 @@ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/modules/supplier/front/agency-term/create/index.js b/modules/supplier/front/agency-term/create/index.js new file mode 100644 index 0000000000..3f66ac5e93 --- /dev/null +++ b/modules/supplier/front/agency-term/create/index.js @@ -0,0 +1,26 @@ +import ngModule from '../../module'; +import Section from 'salix/components/section'; + +export default class Controller extends Section { + constructor($element, $) { + super($element, $); + + this.supplierAgencyTerm = { + supplierFk: this.$params.id + }; + } + + onSubmit() { + this.$.watcher.submit().then(res => { + this.$state.go('supplier.card.agencyTerm.index'); + }); + } +} + +ngModule.vnComponent('vnSupplierAgencyTermCreate', { + template: require('./index.html'), + controller: Controller, + bindings: { + supplier: '<' + } +}); diff --git a/modules/supplier/front/agency-term/create/index.spec.js b/modules/supplier/front/agency-term/create/index.spec.js new file mode 100644 index 0000000000..682e1cc582 --- /dev/null +++ b/modules/supplier/front/agency-term/create/index.spec.js @@ -0,0 +1,28 @@ +import './index'; +import watcher from 'core/mocks/watcher'; + +describe('Supplier', () => { + describe('Component vnSupplierAddressCreate', () => { + let $scope; + let controller; + let $element; + + beforeEach(ngModule('supplier')); + + beforeEach(inject(($componentController, $rootScope, _$state_) => { + $scope = $rootScope.$new(); + $scope.watcher = watcher; + $element = angular.element(''); + controller = $componentController('vnSupplierAgencyTermCreate', {$element, $scope}); + })); + + describe('onSubmit()', () => { + it(`should redirect to 'supplier.card.agencyTerm.index' state`, () => { + jest.spyOn(controller.$state, 'go'); + controller.onSubmit(); + + expect(controller.$state.go).toHaveBeenCalledWith('supplier.card.agencyTerm.index'); + }); + }); + }); +}); diff --git a/modules/supplier/front/agency-term/index/index.html b/modules/supplier/front/agency-term/index/index.html new file mode 100644 index 0000000000..ac3b9b0d57 --- /dev/null +++ b/modules/supplier/front/agency-term/index/index.html @@ -0,0 +1,85 @@ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + diff --git a/modules/supplier/front/agency-term/index/index.js b/modules/supplier/front/agency-term/index/index.js new file mode 100644 index 0000000000..9f77d686a8 --- /dev/null +++ b/modules/supplier/front/agency-term/index/index.js @@ -0,0 +1,36 @@ +import ngModule from '../../module'; +import Section from 'salix/components/section'; + +class Controller extends Section { + constructor($element, $) { + super($element, $); + this.filter = { + include: + {relation: 'agency', + scope: { + fields: ['id', 'name'] + } + } + }; + } + + add() { + this.$.model.insert({}); + } + + onSubmit() { + this.$.watcher.check(); + this.$.model.save().then(() => { + this.$.watcher.notifySaved(); + this.$.watcher.updateOriginalData(); + }); + } +} + +ngModule.vnComponent('vnSupplierAgencyTermIndex', { + template: require('./index.html'), + controller: Controller, + bindings: { + supplier: '<' + } +}); diff --git a/modules/supplier/front/agency-term/index/index.spec.js b/modules/supplier/front/agency-term/index/index.spec.js new file mode 100644 index 0000000000..3e9ea4c1e2 --- /dev/null +++ b/modules/supplier/front/agency-term/index/index.spec.js @@ -0,0 +1,37 @@ +import './index'; +import watcher from 'core/mocks/watcher'; +import crudModel from 'core/mocks/crud-model'; + +describe('Supplier', () => { + describe('Component vnSupplierAddressCreate', () => { + let $scope; + let controller; + let $element; + + beforeEach(ngModule('supplier')); + + beforeEach(inject(($componentController, $rootScope, _$state_) => { + $scope = $rootScope.$new(); + $scope.model = crudModel; + $scope.watcher = watcher; + $element = angular.element(''); + controller = $componentController('vnSupplierAgencyTermIndex', {$element, $scope}); + })); + + describe('onSubmit()', () => { + it('should make HTTP POST request to save values', () => { + jest.spyOn($scope.watcher, 'check'); + jest.spyOn($scope.watcher, 'notifySaved'); + jest.spyOn($scope.watcher, 'updateOriginalData'); + jest.spyOn($scope.model, 'save'); + + controller.onSubmit(); + + expect($scope.model.save).toHaveBeenCalledWith(); + expect($scope.watcher.updateOriginalData).toHaveBeenCalledWith(); + expect($scope.watcher.check).toHaveBeenCalledWith(); + expect($scope.watcher.notifySaved).toHaveBeenCalledWith(); + }); + }); + }); +}); diff --git a/modules/supplier/front/agency-term/locale/es.yml b/modules/supplier/front/agency-term/locale/es.yml new file mode 100644 index 0000000000..f4ba7d87df --- /dev/null +++ b/modules/supplier/front/agency-term/locale/es.yml @@ -0,0 +1,8 @@ +Minimum M3: M3 minimos +Package Price: Precio bulto +Km Price: Precio Km +M3 Price: Precio M3 +Route Price: Precio ruta +Minimum Km: Km minimos +Remove row: Eliminar fila +Add row: Añadir fila \ No newline at end of file diff --git a/modules/supplier/front/index.js b/modules/supplier/front/index.js index dc131ef4ad..ba27688547 100644 --- a/modules/supplier/front/index.js +++ b/modules/supplier/front/index.js @@ -18,3 +18,5 @@ import './billing-data'; import './address/index'; import './address/create'; import './address/edit'; +import './agency-term/index'; +import './agency-term/create'; diff --git a/modules/supplier/front/routes.json b/modules/supplier/front/routes.json index 3d3814f5d8..35519b89a4 100644 --- a/modules/supplier/front/routes.json +++ b/modules/supplier/front/routes.json @@ -15,6 +15,7 @@ {"state": "supplier.card.address.index", "icon": "icon-delivery"}, {"state": "supplier.card.account", "icon": "icon-account"}, {"state": "supplier.card.contact", "icon": "contact_phone"}, + {"state": "supplier.card.agencyTerm.index", "icon": "contact_support"}, {"state": "supplier.card.log", "icon": "history"}, {"state": "supplier.card.consumption", "icon": "show_chart"} ] @@ -86,6 +87,30 @@ "supplier": "$ctrl.supplier" } }, + { + "url": "/agency-term", + "state": "supplier.card.agencyTerm", + "component": "ui-view", + "abstract": true + }, + { + "url": "/index", + "state": "supplier.card.agencyTerm.index", + "component": "vn-supplier-agency-term-index", + "description": "Autonomous", + "params": { + "supplier": "$ctrl.supplier" + } + }, + { + "url": "/create", + "state": "supplier.card.agencyTerm.create", + "component": "vn-supplier-agency-term-create", + "description": "New autonomous", + "params": { + "supplier": "$ctrl.supplier" + } + }, { "url": "/consumption?q", "state": "supplier.card.consumption", diff --git a/modules/worker/back/methods/worker/holidays.js b/modules/worker/back/methods/worker/holidays.js index bcf4d7f51c..339b84b7bd 100644 --- a/modules/worker/back/methods/worker/holidays.js +++ b/modules/worker/back/methods/worker/holidays.js @@ -1,4 +1,5 @@ const UserError = require('vn-loopback/util/user-error'); +const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; module.exports = Self => { Self.remoteMethodCtx('holidays', { @@ -33,7 +34,8 @@ module.exports = Self => { Self.holidays = async(ctx, id, options) => { const models = Self.app.models; const args = ctx.args; - + const conn = Self.dataSource.connector; + const stmts = []; const myOptions = {}; if (typeof options == 'object') @@ -56,42 +58,6 @@ module.exports = Self => { ended.setHours(23, 59, 59, 59); const filter = { - include: [{ - relation: 'holidays', - scope: { - where: {year: args.year} - } - }, - { - relation: 'absences', - scope: { - include: { - relation: 'absenceType', - }, - where: { - dated: {between: [started, ended]} - } - } - }, - { - relation: 'workCenter', - scope: { - include: { - relation: 'holidays', - scope: { - include: [{ - relation: 'detail' - }, - { - relation: 'type' - }], - where: { - dated: {between: [started, ended]} - } - } - } - } - }], where: { and: [ {workerFk: id}, @@ -107,76 +73,32 @@ module.exports = Self => { } }; - if (args.businessFk) - filter.where.and.push({businessFk: args.businessFk}); - const contracts = await models.WorkerLabour.find(filter, myOptions); - let [firstContract] = contracts; - let payedHolidays; + const payedHolidays = firstContract.payedHolidays; - if (firstContract.payedHolidays) - payedHolidays = firstContract.payedHolidays; - else payedHolidays = 0; + let queryIndex; + const year = started.getFullYear(); - let totalHolidays = 0; - let holidaysEnjoyed = 0; - - for (let contract of contracts) { - const contractStarted = contract.started; - contractStarted.setHours(0, 0, 0, 0); - const contractEnded = contract.ended; - if (contractEnded) - contractEnded.setHours(23, 59, 59, 59); - - let startedTime; - if (contractStarted < started) - startedTime = started.getTime(); - else startedTime = contractStarted.getTime(); - - let endedTime; - if (!contractEnded || (contractEnded && contractEnded > ended)) - endedTime = ended.getTime(); - else endedTime = contractEnded.getTime(); - - const dayTimestamp = 1000 * 60 * 60 * 24; - - // Get number of worked days between dates - let workedDays = Math.floor((endedTime - startedTime) / dayTimestamp); - workedDays += 1; // 1 day inclusion - - // Calculates absences - let entitlementRate = 0; - for (let absence of contract.absences()) { - const absenceType = absence.absenceType(); - const isHoliday = absenceType.code === 'holiday'; - const isHalfHoliday = absenceType.code === 'halfHoliday'; - - if (isHoliday) holidaysEnjoyed += 1; - if (isHalfHoliday) holidaysEnjoyed += 0.5; - - entitlementRate += absenceType.holidayEntitlementRate; - } - - workedDays -= entitlementRate; - - // Max holidays for the selected year - const maxHolidays = contract.holidays() && contract.holidays().days; - - if (workedDays < daysInYear()) - totalHolidays += Math.round(2 * maxHolidays * (workedDays) / daysInYear()) / 2; - else totalHolidays = maxHolidays; + if (args.businessFk) { + stmts.push(new ParameterizedSQL('CALL vn.workerCalendar_calculateBusiness(?,?)', [year, args.businessFk])); + queryIndex = stmts.push('SELECT * FROM tmp.workerCalendarCalculateBusiness') - 1; + stmts.push('DROP TEMPORARY TABLE tmp.workerCalendarCalculateBusiness'); + } else { + stmts.push(new ParameterizedSQL('CALL vn.workerCalendar_calculateYear(?,?)', [year, id])); + queryIndex = stmts.push('SELECT * FROM tmp.workerCalendarCalculateYear') - 1; + stmts.push('DROP TEMPORARY TABLE tmp.workerCalendarCalculateYear'); } - function daysInYear() { - const year = started.getFullYear(); + const sql = ParameterizedSQL.join(stmts, ';'); + const result = await conn.executeStmt(sql, myOptions); + const [holidays] = result[queryIndex]; - return isLeapYear(year) ? 366 : 365; - } - return {totalHolidays, holidaysEnjoyed, payedHolidays}; + const totalHolidays = holidays.days; + const holidaysEnjoyed = holidays.daysEnjoyed; + const totalHours = holidays.hours; + const hoursEnjoyed = holidays.hoursEnjoyed; + + return {totalHolidays, holidaysEnjoyed, totalHours, hoursEnjoyed, payedHolidays}; }; - - function isLeapYear(year) { - return year % 400 === 0 || (year % 100 !== 0 && year % 4 === 0); - } }; diff --git a/modules/worker/back/models/department.json b/modules/worker/back/models/department.json index 7d6f7a7be6..c3f627e930 100644 --- a/modules/worker/back/models/department.json +++ b/modules/worker/back/models/department.json @@ -34,6 +34,9 @@ }, "notificationEmail": { "type": "string" + }, + "hasToMistake": { + "type": "number" } } } diff --git a/modules/worker/front/calendar/index.html b/modules/worker/front/calendar/index.html index 7ef586b36b..cff4d0bc9f 100644 --- a/modules/worker/front/calendar/index.html +++ b/modules/worker/front/calendar/index.html @@ -25,20 +25,28 @@
{{'Contract' | translate}} #{{$ctrl.businessId}}
- {{'Used' | translate}} {{$ctrl.contractHolidays.holidaysEnjoyed}} + {{'Used' | translate}} {{$ctrl.contractHolidays.holidaysEnjoyed || 0}} {{'of' | translate}} {{$ctrl.contractHolidays.totalHolidays || 0}} {{'days' | translate}}
- {{'Paid holidays' | translate}} {{$ctrl.contractHolidays.payedHolidays}} {{'days' | translate}} + {{'Spent' | translate}} {{$ctrl.contractHolidays.hoursEnjoyed || 0}} + {{'of' | translate}} {{$ctrl.contractHolidays.totalHours || 0}} {{'hours' | translate}} +
+
+ {{'Paid holidays' | translate}} {{$ctrl.contractHolidays.payedHolidays || 0}} {{'days' | translate}}
{{'Year' | translate}} {{$ctrl.year}}
- {{'Used' | translate}} {{$ctrl.yearHolidays.holidaysEnjoyed}} + {{'Used' | translate}} {{$ctrl.yearHolidays.holidaysEnjoyed || 0}} {{'of' | translate}} {{$ctrl.yearHolidays.totalHolidays || 0}} {{'days' | translate}}
+
+ {{'Spent' | translate}} {{$ctrl.yearHolidays.hoursEnjoyed || 0}} + {{'of' | translate}} {{$ctrl.yearHolidays.totalHours || 0}} {{'hours' | translate}} +
diff --git a/modules/worker/front/calendar/index.js b/modules/worker/front/calendar/index.js index 92bad1f0fa..95e1fc1342 100644 --- a/modules/worker/front/calendar/index.js +++ b/modules/worker/front/calendar/index.js @@ -198,7 +198,7 @@ class Controller extends Section { const event = this.events[stamp]; const calendar = $event.target.closest('vn-calendar').$ctrl; - if (event) { + if (event && event.absenceId) { if (event.type == this.absenceType.code) this.delete(calendar, day, event); else @@ -230,6 +230,7 @@ class Controller extends Section { .then(calendar.repaint()) .then(() => this.getContractHolidays()) .then(() => this.getYearHolidays()) + .then(() => this.repaint()) ); }); } @@ -266,6 +267,7 @@ class Controller extends Section { .then(calendar.repaint()) .then(() => this.getContractHolidays()) .then(() => this.getYearHolidays()) + .then(() => this.repaint()) ); }); } diff --git a/modules/worker/front/calendar/index.spec.js b/modules/worker/front/calendar/index.spec.js index 3d57756632..1da4066d9d 100644 --- a/modules/worker/front/calendar/index.spec.js +++ b/modules/worker/front/calendar/index.spec.js @@ -191,7 +191,8 @@ describe('Worker', () => { const selectedDay = new Date(); const expectedEvent = { dated: selectedDay, - type: 'holiday' + type: 'holiday', + absenceId: 1 }; const $event = { target: { @@ -214,7 +215,8 @@ describe('Worker', () => { const selectedDay = new Date(); const expectedEvent = { dated: selectedDay, - type: 'leaveOfAbsence' + type: 'leaveOfAbsence', + absenceId: 1 }; const $event = { target: { diff --git a/modules/worker/front/calendar/locale/es.yml b/modules/worker/front/calendar/locale/es.yml index 8e9f9cdf8d..bd75458aab 100644 --- a/modules/worker/front/calendar/locale/es.yml +++ b/modules/worker/front/calendar/locale/es.yml @@ -2,9 +2,11 @@ Calendar: Calendario Contract: Contrato Festive: Festivo Used: Utilizados +Spent: Utilizadas Year: Año of: de days: días +hours: horas Choose an absence type from the right menu: Elige un tipo de ausencia desde el menú de la derecha To start adding absences, click an absence type from the right menu and then on the day you want to add an absence: Para empezar a añadir ausencias, haz clic en un tipo de ausencia desde el menu de la derecha y después en el día que quieres añadir la ausencia You can just add absences within the current year: Solo puedes añadir ausencias dentro del año actual diff --git a/modules/zone/back/models/agency.json b/modules/zone/back/models/agency.json index edec36f874..be262b6707 100644 --- a/modules/zone/back/models/agency.json +++ b/modules/zone/back/models/agency.json @@ -16,5 +16,12 @@ "type": "string", "required": false } + }, + "relations": { + "supplierAgencyTerm": { + "type": "hasOne", + "model": "SupplierAgencyTerm", + "foreignKey": "agencyFk" + } } }