Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 3686-client_create
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Vicent Llopis 2022-03-30 12:35:37 +02:00
commit b29261cb75
47 changed files with 2276 additions and 1145 deletions

View File

@ -1,2 +0,0 @@
INSERT INTO salix.ACL (id, model, property, accessType, permission, principalType, principalId)
VALUES(301, 'Agency', '*', 'READ', 'ALLOW', 'ROLE', 'employee');

View File

@ -0,0 +1,2 @@
INSERT INTO `salix`.`ACL` (`id`, `model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES(304, 'Agency', '*', '*', 'ALLOW', 'ROLE', 'employee');

View File

@ -0,0 +1,3 @@
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES
('SupplierAgencyTerm', '*', '*', 'ALLOW', 'ROLE', 'administrative');

View File

@ -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`;

View File

@ -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;

File diff suppressed because one or more lines are too long

View File

@ -1902,14 +1902,29 @@ INSERT INTO `vn`.`workCenterHoliday` (`workCenterFk`, `days`, `year`)
('1', '24.5', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 YEAR))), ('1', '24.5', YEAR(DATE_ADD(CURDATE(), INTERVAL -1 YEAR))),
('5', '23', 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 VALUES
(1, 'Holidays', '#FF4444', 'holiday', 0), (1, 'Holidays', '#FF4444', 'holiday', 0, 0),
(2, 'Leave of absence', '#C71585', 'absence', 0), (2, 'Leave of absence', '#C71585', 'absence', 0, 1),
(6, 'Half holiday', '#E65F00', 'halfHoliday', 0), (6, 'Half holiday', '#E65F00', 'halfHoliday', 0, 0.5),
(15, 'Half Paid Leave', '#5151c0', 'halfPaidLeave', 0), (15, 'Half Paid Leave', '#5151c0', 'halfPaidLeave', 0, 1),
(20, 'Furlough', '#97B92F', 'furlough', 1), (20, 'Furlough', '#97B92F', 'furlough', 1, 1),
(21, 'Furlough half day', '#778899', 'halfFurlough', 0.5); (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`) INSERT INTO `postgresql`.`calendar_employee` (`business_id`, `calendar_state_id`, `date`)
VALUES VALUES
@ -2462,18 +2477,14 @@ INSERT INTO `bs`.`defaulter` (`clientFk`, `amount`, `created`, `defaulterSinced`
(1107, 500, CURDATE(), CURDATE()), (1107, 500, CURDATE(), CURDATE()),
(1109, 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` UPDATE `vn`.`agency`
SET `supplierFk`=1 SET `supplierFk`=1
WHERE `id`=1; WHERE `id`=1;
UPDATE `vn`.`agency` UPDATE `vn`.`agency`
SET `supplierFk`=1 SET `supplierFk`=1
WHERE `id`=2; WHERE `id`=2;
UPDATE `vn`.`agency` UPDATE `vn`.`agency`
SET `supplierFk`=2 SET `supplierFk`=2
WHERE `id`=3; WHERE `id`=3;
@ -2481,6 +2492,7 @@ WHERE `id`=3;
UPDATE `vn`.`route` UPDATE `vn`.`route`
SET `invoiceInFk`=1 SET `invoiceInFk`=1
WHERE `id`=1; WHERE `id`=1;
UPDATE `vn`.`route` UPDATE `vn`.`route`
SET `invoiceInFk`=2 SET `invoiceInFk`=2
WHERE `id`=2; WHERE `id`=2;
@ -2496,6 +2508,7 @@ INSERT INTO `bs`.`sale` (`saleFk`, `amount`, `dated`, `typeFk`, `clientFk`)
(3, 200.78, CURDATE(), 2, 1101), (3, 200.78, CURDATE(), 2, 1101),
(4, 33.8, CURDATE(), 1, 1101), (4, 33.8, CURDATE(), 1, 1101),
(30, 34.4, CURDATE(), 1, 1108); (30, 34.4, CURDATE(), 1, 1108);
INSERT INTO `vn`.`docuware` (`code`, `fileCabinetName`, `dialogName` , `find`) INSERT INTO `vn`.`docuware` (`code`, `fileCabinetName`, `dialogName` , `find`)
VALUES VALUES
('deliveryClientTest', 'deliveryClientTest', 'findTest', 'word'); ('deliveryClientTest', 'deliveryClientTest', 'findTest', 'word');
@ -2503,3 +2516,23 @@ INSERT INTO `vn`.`docuware` (`code`, `fileCabinetName`, `dialogName` , `find`)
INSERT INTO `vn`.`docuwareConfig` (`url`) INSERT INTO `vn`.`docuwareConfig` (`url`)
VALUES VALUES
('https://verdnatura.docuware.cloud/docuware/platform'); ('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);

File diff suppressed because it is too large Load Diff

View File

@ -66,7 +66,7 @@ describe('Claim development', () => {
.waitToGetProperty(selectors.claimDevelopment.firstClaimRedelivery, 'value'); .waitToGetProperty(selectors.claimDevelopment.firstClaimRedelivery, 'value');
expect(reason).toEqual('Calor'); expect(reason).toEqual('Calor');
expect(result).toEqual('Cocido'); expect(result).toEqual('Baboso/Cocido');
expect(responsible).toEqual('Calidad general'); expect(responsible).toEqual('Calidad general');
expect(worker).toEqual('adminAssistantNick'); expect(worker).toEqual('adminAssistantNick');
expect(redelivery).toEqual('Cliente'); expect(redelivery).toEqual('Cliente');

View File

@ -50,7 +50,7 @@ describe('InvoiceOut manual invoice path', () => {
}); });
it('should create an invoice from a client', async() => { it('should create an invoice from a client', async() => {
await page.autocompleteSearch(selectors.invoiceOutIndex.manualInvoiceClient, 'Charles Xavier'); await page.autocompleteSearch(selectors.invoiceOutIndex.manualInvoiceClient, 'Max Eisenhardt');
await page.autocompleteSearch(selectors.invoiceOutIndex.manualInvoiceSerial, 'Global nacional'); await page.autocompleteSearch(selectors.invoiceOutIndex.manualInvoiceSerial, 'Global nacional');
await page.autocompleteSearch(selectors.invoiceOutIndex.manualInvoiceTaxArea, 'national'); await page.autocompleteSearch(selectors.invoiceOutIndex.manualInvoiceTaxArea, 'national');
await page.waitToClick(selectors.invoiceOutIndex.saveInvoice); await page.waitToClick(selectors.invoiceOutIndex.saveInvoice);

View File

@ -221,6 +221,7 @@
"Can't transfer claimed sales": "No puedes transferir lineas reclamadas", "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", "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 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", "date in the future": "Fecha en el futuro",
"reference duplicated": "Referencia duplicada" "reference duplicated": "Referencia duplicada"
} }

View File

@ -52,10 +52,12 @@ class Controller extends Section {
} }
scrollToLine(lineFk) { scrollToLine(lineFk) {
this.$.$applyAsync(() => {
const hashFk = this.lineFk || lineFk; const hashFk = this.lineFk || lineFk;
const hash = `vnItemDiary-${hashFk}`; const hash = `vnItemDiary-${hashFk}`;
this.$location.hash(hash); this.$location.hash(hash);
this.$anchorScroll(); this.$anchorScroll();
});
} }
showDescriptor(event, sale) { showDescriptor(event, sale) {

View File

@ -47,6 +47,8 @@ describe('Item', () => {
controller.lineFk = 1; controller.lineFk = 1;
controller.scrollToLine('invalidValue'); controller.scrollToLine('invalidValue');
$scope.$apply();
expect(controller.$location.hash()).toEqual(`vnItemDiary-${1}`); expect(controller.$location.hash()).toEqual(`vnItemDiary-${1}`);
expect(controller.$anchorScroll).toHaveBeenCalledWith(); expect(controller.$anchorScroll).toHaveBeenCalledWith();
}); });
@ -56,6 +58,8 @@ describe('Item', () => {
controller.lineFk = undefined; controller.lineFk = undefined;
controller.scrollToLine(1); controller.scrollToLine(1);
$scope.$apply();
expect(controller.$location.hash()).toEqual(`vnItemDiary-${1}`); expect(controller.$location.hash()).toEqual(`vnItemDiary-${1}`);
expect(controller.$anchorScroll).toHaveBeenCalledWith(); expect(controller.$anchorScroll).toHaveBeenCalledWith();
}); });

View File

@ -222,8 +222,8 @@ describe('SalesMonitor salesFilter()', () => {
const firstTicket = result.shift(); const firstTicket = result.shift();
const secondTicket = result.shift(); const secondTicket = result.shift();
expect(firstTicket.totalProblems).toEqual(3); expect(firstTicket.totalProblems).toEqual(1);
expect(secondTicket.totalProblems).toEqual(2); expect(secondTicket.totalProblems).toEqual(1);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {

View File

@ -87,21 +87,21 @@ module.exports = Self => {
SUM(t.packages) packages, SUM(t.packages) packages,
r.m3, r.m3,
r.kmEnd - r.kmStart kmTotal, r.kmEnd - r.kmStart kmTotal,
CAST(IFNULL(ate.routePrice, CAST(IFNULL(sat.routePrice,
(ate.kmPrice * (GREATEST(r.kmEnd - r.kmStart , ate.minimumKm)) (sat.kmPrice * (GREATEST(r.kmEnd - r.kmStart , sat.minimumKm))
+ GREATEST(r.m3 , ate.minimumM3) * ate.m3Price) + GREATEST(r.m3 , sat.minimumM3) * sat.m3Price)
+ ate.packagePrice * SUM(t.packages) ) + sat.packagePrice * SUM(t.packages) )
AS DECIMAL(10,2)) price, AS DECIMAL(10,2)) price,
r.invoiceInFk, r.invoiceInFk,
a.supplierFk, sat.supplierFk,
s.name supplierName s.name supplierName
FROM vn.route r FROM vn.route r
LEFT JOIN vn.agencyMode am ON r.agencyModeFk = am.id LEFT JOIN vn.agencyMode am ON r.agencyModeFk = am.id
LEFT JOIN vn.agency a ON am.agencyFk = a.id LEFT JOIN vn.agency a ON am.agencyFk = a.id
LEFT JOIN vn.ticket t ON t.routeFk = r.id LEFT JOIN vn.ticket t ON t.routeFk = r.id
LEFT JOIN vn.agencyTerm ate ON ate.agencyFk = a.id LEFT JOIN vn.supplierAgencyTerm sat ON sat.agencyFk = a.id
LEFT JOIN vn.supplier s ON s.id = a.supplierFk LEFT JOIN vn.supplier s ON s.id = sat.supplierFk
WHERE r.created > DATE_ADD(CURDATE(), INTERVAL -2 MONTH) AND a.supplierFk IS NOT NULL WHERE r.created > DATE_ADD(CURDATE(), INTERVAL -2 MONTH) AND sat.supplierFk IS NOT NULL
GROUP BY r.id GROUP BY r.id
) a` ) a`
); );

View File

@ -18,7 +18,7 @@ describe('AgencyTerm filter()', () => {
const firstAgencyTerm = agencyTerms[0]; const firstAgencyTerm = agencyTerms[0];
expect(firstAgencyTerm.routeFk).toEqual(1); expect(firstAgencyTerm.routeFk).toEqual(1);
expect(agencyTerms.length).toEqual(3); expect(agencyTerms.length).toEqual(5);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
@ -72,7 +72,7 @@ describe('AgencyTerm filter()', () => {
const results = await models.AgencyTerm.filter(ctx, options); const results = await models.AgencyTerm.filter(ctx, options);
expect(results.length).toBe(3); expect(results.length).toBe(5);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {

View File

@ -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);
};
};

View File

@ -11,6 +11,9 @@
"SupplierAccount": { "SupplierAccount": {
"dataSource": "vn" "dataSource": "vn"
}, },
"SupplierAgencyTerm": {
"dataSource": "vn"
},
"SupplierLog": { "SupplierLog": {
"dataSource": "vn" "dataSource": "vn"
}, },

View File

@ -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;
});
};

View File

@ -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"
}
}
}

View File

@ -7,6 +7,7 @@ module.exports = Self => {
require('../methods/supplier/getSummary')(Self); require('../methods/supplier/getSummary')(Self);
require('../methods/supplier/updateFiscalData')(Self); require('../methods/supplier/updateFiscalData')(Self);
require('../methods/supplier/consumption')(Self); require('../methods/supplier/consumption')(Self);
require('../methods/supplier/freeAgencies')(Self);
Self.validatesPresenceOf('name', { Self.validatesPresenceOf('name', {
message: 'The social name cannot be empty' message: 'The social name cannot be empty'

View File

@ -0,0 +1,74 @@
<vn-watcher
vn-id="watcher"
url="SupplierAgencyTerms"
primary-key="agencyFk"
data="$ctrl.supplierAgencyTerm"
insert-mode="true"
form="form">
</vn-watcher>
<vn-crud-model
auto-load="true"
url="Suppliers/freeAgencies"
data="$ctrl.agencies">
</vn-crud-model>
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
<vn-card class="vn-pa-lg">
<vn-horizontal>
<vn-autocomplete vn-one
label="Agency"
ng-model="$ctrl.supplierAgencyTerm.agencyFk"
data="$ctrl.agencies"
show-field="name"
value-field="id"
rule>
</vn-autocomplete>
<vn-input-number
type="number"
label="Minimum M3"
ng-model="$ctrl.supplierAgencyTerm.minimumM3"
rule>
</vn-input-number>
</vn-horizontal>
<vn-horizontal>
<vn-input-number
type="number"
label="Package Price"
ng-model="$ctrl.supplierAgencyTerm.packagePrice"
rule>
</vn-input-number>
<vn-input-number
type="number"
label="Km Price"
ng-model="$ctrl.supplierAgencyTerm.kmPrice"
rule>
</vn-input-number>
<vn-input-number
type="number"
label="M3 Price"
ng-model="$ctrl.supplierAgencyTerm.m3Price"
rule>
</vn-input-number>
</vn-horizontal>
<vn-horizontal>
<vn-input-number
type="number"
label="Route Price"
ng-model="$ctrl.supplierAgencyTerm.routePrice"
rule>
</vn-input-number>
<vn-input-number
type="number"
label="Minimum Km"
ng-model="$ctrl.supplierAgencyTerm.minimumKm"
rule>
</vn-input-number>
</vn-horizontal>
</vn-card>
<vn-button-bar>
<vn-submit label="Save"></vn-submit>
<vn-button
label="Cancel"
ui-sref="supplier.card.agencyTerm.index">
</vn-button>
</vn-button-bar>
</form>

View File

@ -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: '<'
}
});

View File

@ -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('<vn-supplier-agency-term-create></vn-supplier-agency-term-create>');
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');
});
});
});
});

View File

@ -0,0 +1,85 @@
<vn-crud-model
vn-id="model"
url="SupplierAgencyTerms"
link="{supplierFk: $ctrl.$params.id}"
primary-key="agencyFk"
filter="$ctrl.filter"
data="$ctrl.supplierAgencyTerms"
auto-load="true">
</vn-crud-model>
<vn-watcher
vn-id="watcher"
data="$ctrl.supplierAgencyTerms"
form="form">
</vn-watcher>
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-lg">
<vn-card class="vn-pa-lg">
<vn-horizontal ng-repeat="supplierAgencyTerm in $ctrl.supplierAgencyTerms">
<vn-textfield
disabled="true"
vn-id="agency"
label="Agency"
ng-model="supplierAgencyTerm.agency.name"
rule>
</vn-textfield>
<vn-input-number
type="number"
label="Minimum M3"
ng-model="supplierAgencyTerm.minimumM3"
rule>
</vn-input-number>
<vn-input-number
type="number"
label="Package Price"
ng-model="supplierAgencyTerm.packagePrice"
rule>
</vn-input-number>
<vn-input-number
type="number"
label="Km Price"
ng-model="supplierAgencyTerm.kmPrice"
rule>
</vn-input-number>
<vn-input-number
type="number"
label="M3 Price"
ng-model="supplierAgencyTerm.m3Price"
rule>
</vn-input-number>
<vn-input-number
type="number"
label="Route Price"
ng-model="supplierAgencyTerm.routePrice"
rule>
</vn-input-number>
<vn-input-number
type="number"
label="Minimum Km"
ng-model="supplierAgencyTerm.minimumKm"
rule>
</vn-input-number>
<vn-none>
<vn-icon-button
vn-tooltip="Remove row"
icon="delete"
ng-click="model.remove($index)"
tabindex="-1">
</vn-icon-button>
</vn-none>
</vn-horizontal>
</vn-card>
<vn-button-bar>
<vn-submit
disabled="!watcher.dataChanged()"
label="Save">
</vn-submit>
</vn-button-bar>
</form>
<vn-float-button
vn-bind="+"
fixed-bottom-right
vn-tooltip="New row"
ui-sref="supplier.card.agencyTerm.create"
icon="add"
label="Add">
</vn-float-button>

View File

@ -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: '<'
}
});

View File

@ -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('<vn-supplier-agency-term-index></vn-supplier-agency-term-index>');
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();
});
});
});
});

View File

@ -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

View File

@ -18,3 +18,5 @@ import './billing-data';
import './address/index'; import './address/index';
import './address/create'; import './address/create';
import './address/edit'; import './address/edit';
import './agency-term/index';
import './agency-term/create';

View File

@ -15,6 +15,7 @@
{"state": "supplier.card.address.index", "icon": "icon-delivery"}, {"state": "supplier.card.address.index", "icon": "icon-delivery"},
{"state": "supplier.card.account", "icon": "icon-account"}, {"state": "supplier.card.account", "icon": "icon-account"},
{"state": "supplier.card.contact", "icon": "contact_phone"}, {"state": "supplier.card.contact", "icon": "contact_phone"},
{"state": "supplier.card.agencyTerm.index", "icon": "contact_support"},
{"state": "supplier.card.log", "icon": "history"}, {"state": "supplier.card.log", "icon": "history"},
{"state": "supplier.card.consumption", "icon": "show_chart"} {"state": "supplier.card.consumption", "icon": "show_chart"}
] ]
@ -86,6 +87,30 @@
"supplier": "$ctrl.supplier" "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", "url": "/consumption?q",
"state": "supplier.card.consumption", "state": "supplier.card.consumption",

View File

@ -28,16 +28,6 @@ module.exports = Self => {
type: 'date', type: 'date',
description: 'The shipped from date filter' description: 'The shipped from date filter'
}, },
{
arg: 'shippedTo',
type: 'date',
description: 'The shipped to date filter'
},
{
arg: 'landedFrom',
type: 'date',
description: 'The landed from date filter'
},
{ {
arg: 'landedTo', arg: 'landedTo',
type: 'date', type: 'date',
@ -101,10 +91,6 @@ module.exports = Self => {
return {'t.ref': {like: `%${value}%`}}; return {'t.ref': {like: `%${value}%`}};
case 'shippedFrom': case 'shippedFrom':
return {'t.shipped': {gte: value}}; return {'t.shipped': {gte: value}};
case 'shippedTo':
return {'t.shipped': {lte: value}};
case 'landedFrom':
return {'t.landed': {gte: value}};
case 'landedTo': case 'landedTo':
return {'t.landed': {lte: value}}; return {'t.landed': {lte: value}};
case 'continent': case 'continent':
@ -162,6 +148,7 @@ module.exports = Self => {
stmt.merge(conn.makeWhere(filter.where)); stmt.merge(conn.makeWhere(filter.where));
stmt.merge(conn.makeGroupBy('t.id')); stmt.merge(conn.makeGroupBy('t.id'));
stmt.merge(conn.makeOrderBy(filter.order));
stmt.merge(conn.makeLimit(filter)); stmt.merge(conn.makeLimit(filter));
stmts.push(stmt); stmts.push(stmt);

View File

@ -46,15 +46,64 @@ describe('Travel extraCommunityFilter()', () => {
expect(result.length).toEqual(3); expect(result.length).toEqual(3);
}); });
it('should return the routes matching "landed from" and "landed to"', async() => { it('should return the travel matching "warehouse in"', async() => {
const from = new Date();
const to = new Date();
from.setHours(0, 0, 0, 0);
to.setHours(23, 59, 59, 999);
to.setDate(to.getDate() + 14);
const ctx = { const ctx = {
args: { args: {
landedFrom: from, warehouseInFk: 1
}
};
const result = await app.models.Travel.extraCommunityFilter(ctx, filter);
expect(result.length).toEqual(4);
});
it('should return the travel matching "continent"', async() => {
const ctx = {
args: {
continent: 'AM'
}
};
const result = await app.models.Travel.extraCommunityFilter(ctx, filter);
expect(result.length).toEqual(3);
});
it('should return the travel matching "agencyFk"', async() => {
const ctx = {
args: {
agencyFk: 1
}
};
const result = await app.models.Travel.extraCommunityFilter(ctx, filter);
expect(result.length).toEqual(8);
});
it('should return the travel matching "cargoSupplierFk"', async() => {
const ctx = {
args: {
cargoSupplierFk: 1
}
};
const result = await app.models.Travel.extraCommunityFilter(ctx, filter);
expect(result.length).toEqual(4);
});
it('should return the routes matching "shipped from" and "landed to"', async() => {
const from = new Date();
from.setDate(from.getDate() - 2);
from.setHours(0, 0, 0, 0);
const to = new Date();
to.setHours(23, 59, 59, 999);
to.setDate(to.getDate() + 7);
const ctx = {
args: {
shippedFrom: from,
landedTo: to landedTo: to
} }
}; };

View File

@ -47,17 +47,6 @@
ng-model="$ctrl.landedTo"> ng-model="$ctrl.landedTo">
</vn-date-picker> </vn-date-picker>
</vn-horizontal> </vn-horizontal>
<vn-horizontal>
<vn-date-picker
vn-one
label="Shipped to"
ng-model="$ctrl.shippedTo">
</vn-date-picker>
<vn-date-picker
vn-one
label="Landed from"
ng-model="$ctrl.landedFrom">
</vn-date-picker>
</vn-horizontal> </vn-horizontal>
<vn-horizontal> <vn-horizontal>
<vn-autocomplete vn-one <vn-autocomplete vn-one

View File

@ -14,31 +14,6 @@ class Controller extends SearchPanel {
set shippedFrom(value) { set shippedFrom(value) {
this.filter.shippedFrom = value; this.filter.shippedFrom = value;
if (!this.filter.landedFrom)
this.filter.landedFrom = value;
}
get shippedTo() {
return this.filter.shippedTo;
}
set shippedTo(value) {
this.filter.shippedTo = value;
if (!this.filter.landedTo)
this.filter.landedTo = value;
}
get landedFrom() {
return this.filter.landedFrom;
}
set landedFrom(value) {
this.filter.landedFrom = value;
if (!this.filter.shippedFrom)
this.filter.shippedFrom = value;
} }
get landedTo() { get landedTo() {
@ -47,9 +22,6 @@ class Controller extends SearchPanel {
set landedTo(value) { set landedTo(value) {
this.filter.landedTo = value; this.filter.landedTo = value;
if (!this.filter.shippedTo)
this.filter.shippedTo = value;
} }
} }

View File

@ -2,7 +2,7 @@
vn-id="model" vn-id="model"
url="Travels/extraCommunityFilter" url="Travels/extraCommunityFilter"
data="travels" data="travels"
order="landed ASC, shipped ASC, travelFk, loadPriority, agencyModeFk, evaNotes" order="shipped ASC, landed ASC, travelFk, loadPriority, agencyModeFk, evaNotes"
limit="20" limit="20"
auto-load="true"> auto-load="true">
</vn-crud-model> </vn-crud-model>

View File

@ -17,16 +17,18 @@ class Controller extends Section {
this.draggableElement = 'a[draggable]'; this.draggableElement = 'a[draggable]';
this.droppableElement = 'vn-tbody[vn-droppable]'; this.droppableElement = 'vn-tbody[vn-droppable]';
const scopeDays = 14; const twoDays = 2;
const landedFrom = new Date(); const shippedFrom = new Date();
landedFrom.setHours(0, 0, 0, 0); shippedFrom.setDate(shippedFrom.getDate() - twoDays);
shippedFrom.setHours(0, 0, 0, 0);
const sevenDays = 7;
const landedTo = new Date(); const landedTo = new Date();
landedTo.setDate(landedTo.getDate() + scopeDays); landedTo.setDate(landedTo.getDate() + sevenDays);
landedTo.setHours(23, 59, 59, 59); landedTo.setHours(23, 59, 59, 59);
this.defaultFilter = { this.defaultFilter = {
landedFrom: landedFrom, shippedFrom: shippedFrom,
landedTo: landedTo, landedTo: landedTo,
continent: 'AM' continent: 'AM'
}; };
@ -34,10 +36,12 @@ class Controller extends Section {
get hasDateRange() { get hasDateRange() {
const userParams = this.$.model.userParams; const userParams = this.$.model.userParams;
const hasLanded = userParams.landedFrom || userParams.landedTo; const hasLanded = userParams.landedTo;
const hasShipped = userParams.shippedFrom || userParams.shippedTo; const hasShipped = userParams.shippedFrom;
const hasContinent = userParams.continent;
const hasWarehouseOut = userParams.warehouseOutFk;
return hasLanded || hasShipped; return hasLanded || hasShipped || hasContinent || hasWarehouseOut;
} }
findDraggable($event) { findDraggable($event) {

View File

@ -9,8 +9,8 @@ vn-travel-extra-community {
padding-bottom: 7px; padding-bottom: 7px;
padding-bottom: 4px; padding-bottom: 4px;
font-weight: lighter; font-weight: lighter;
background-color: #fde6ca; background-color: $color-bg;
color: $color-font-light; color: white;
border-bottom: 1px solid #f7931e; border-bottom: 1px solid #f7931e;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;

View File

@ -1,4 +1,5 @@
const UserError = require('vn-loopback/util/user-error'); const UserError = require('vn-loopback/util/user-error');
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
module.exports = Self => { module.exports = Self => {
Self.remoteMethodCtx('holidays', { Self.remoteMethodCtx('holidays', {
@ -33,7 +34,8 @@ module.exports = Self => {
Self.holidays = async(ctx, id, options) => { Self.holidays = async(ctx, id, options) => {
const models = Self.app.models; const models = Self.app.models;
const args = ctx.args; const args = ctx.args;
const conn = Self.dataSource.connector;
const stmts = [];
const myOptions = {}; const myOptions = {};
if (typeof options == 'object') if (typeof options == 'object')
@ -56,42 +58,6 @@ module.exports = Self => {
ended.setHours(23, 59, 59, 59); ended.setHours(23, 59, 59, 59);
const filter = { 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: { where: {
and: [ and: [
{workerFk: id}, {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); const contracts = await models.WorkerLabour.find(filter, myOptions);
let [firstContract] = contracts; let [firstContract] = contracts;
let payedHolidays; const payedHolidays = firstContract.payedHolidays;
if (firstContract.payedHolidays) let queryIndex;
payedHolidays = firstContract.payedHolidays;
else payedHolidays = 0;
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;
}
function daysInYear() {
const year = started.getFullYear(); const year = started.getFullYear();
return isLeapYear(year) ? 366 : 365; 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');
} }
return {totalHolidays, holidaysEnjoyed, payedHolidays};
};
function isLeapYear(year) { const sql = ParameterizedSQL.join(stmts, ';');
return year % 400 === 0 || (year % 100 !== 0 && year % 4 === 0); const result = await conn.executeStmt(sql, myOptions);
} const [holidays] = result[queryIndex];
const totalHolidays = holidays.days;
const holidaysEnjoyed = holidays.daysEnjoyed;
const totalHours = holidays.hours;
const hoursEnjoyed = holidays.hoursEnjoyed;
return {totalHolidays, holidaysEnjoyed, totalHours, hoursEnjoyed, payedHolidays};
};
}; };

View File

@ -34,6 +34,9 @@
}, },
"notificationEmail": { "notificationEmail": {
"type": "string" "type": "string"
},
"hasToMistake": {
"type": "number"
} }
} }
} }

View File

@ -25,20 +25,28 @@
<div class="totalBox vn-mb-sm" style="text-align: center;"> <div class="totalBox vn-mb-sm" style="text-align: center;">
<h6>{{'Contract' | translate}} #{{$ctrl.businessId}}</h6> <h6>{{'Contract' | translate}} #{{$ctrl.businessId}}</h6>
<div> <div>
{{'Used' | translate}} {{$ctrl.contractHolidays.holidaysEnjoyed}} {{'Used' | translate}} {{$ctrl.contractHolidays.holidaysEnjoyed || 0}}
{{'of' | translate}} {{$ctrl.contractHolidays.totalHolidays || 0}} {{'days' | translate}} {{'of' | translate}} {{$ctrl.contractHolidays.totalHolidays || 0}} {{'days' | translate}}
</div> </div>
<div> <div>
{{'Paid holidays' | translate}} {{$ctrl.contractHolidays.payedHolidays}} {{'days' | translate}} {{'Spent' | translate}} {{$ctrl.contractHolidays.hoursEnjoyed || 0}}
{{'of' | translate}} {{$ctrl.contractHolidays.totalHours || 0}} {{'hours' | translate}}
</div>
<div>
{{'Paid holidays' | translate}} {{$ctrl.contractHolidays.payedHolidays || 0}} {{'days' | translate}}
</div> </div>
</div> </div>
<div class="totalBox" style="text-align: center;"> <div class="totalBox" style="text-align: center;">
<h6>{{'Year' | translate}} {{$ctrl.year}}</h6> <h6>{{'Year' | translate}} {{$ctrl.year}}</h6>
<div> <div>
{{'Used' | translate}} {{$ctrl.yearHolidays.holidaysEnjoyed}} {{'Used' | translate}} {{$ctrl.yearHolidays.holidaysEnjoyed || 0}}
{{'of' | translate}} {{$ctrl.yearHolidays.totalHolidays || 0}} {{'days' | translate}} {{'of' | translate}} {{$ctrl.yearHolidays.totalHolidays || 0}} {{'days' | translate}}
</div> </div>
<div>
{{'Spent' | translate}} {{$ctrl.yearHolidays.hoursEnjoyed || 0}}
{{'of' | translate}} {{$ctrl.yearHolidays.totalHours || 0}} {{'hours' | translate}}
</div>
</div> </div>
<div class="vn-pt-md"> <div class="vn-pt-md">

View File

@ -198,7 +198,7 @@ class Controller extends Section {
const event = this.events[stamp]; const event = this.events[stamp];
const calendar = $event.target.closest('vn-calendar').$ctrl; const calendar = $event.target.closest('vn-calendar').$ctrl;
if (event) { if (event && event.absenceId) {
if (event.type == this.absenceType.code) if (event.type == this.absenceType.code)
this.delete(calendar, day, event); this.delete(calendar, day, event);
else else
@ -230,6 +230,7 @@ class Controller extends Section {
.then(calendar.repaint()) .then(calendar.repaint())
.then(() => this.getContractHolidays()) .then(() => this.getContractHolidays())
.then(() => this.getYearHolidays()) .then(() => this.getYearHolidays())
.then(() => this.repaint())
); );
}); });
} }
@ -266,6 +267,7 @@ class Controller extends Section {
.then(calendar.repaint()) .then(calendar.repaint())
.then(() => this.getContractHolidays()) .then(() => this.getContractHolidays())
.then(() => this.getYearHolidays()) .then(() => this.getYearHolidays())
.then(() => this.repaint())
); );
}); });
} }

View File

@ -191,7 +191,8 @@ describe('Worker', () => {
const selectedDay = new Date(); const selectedDay = new Date();
const expectedEvent = { const expectedEvent = {
dated: selectedDay, dated: selectedDay,
type: 'holiday' type: 'holiday',
absenceId: 1
}; };
const $event = { const $event = {
target: { target: {
@ -214,7 +215,8 @@ describe('Worker', () => {
const selectedDay = new Date(); const selectedDay = new Date();
const expectedEvent = { const expectedEvent = {
dated: selectedDay, dated: selectedDay,
type: 'leaveOfAbsence' type: 'leaveOfAbsence',
absenceId: 1
}; };
const $event = { const $event = {
target: { target: {

View File

@ -2,9 +2,11 @@ Calendar: Calendario
Contract: Contrato Contract: Contrato
Festive: Festivo Festive: Festivo
Used: Utilizados Used: Utilizados
Spent: Utilizadas
Year: Año Year: Año
of: de of: de
days: días days: días
hours: horas
Choose an absence type from the right menu: Elige un tipo de ausencia desde el menú de la derecha 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 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 You can just add absences within the current year: Solo puedes añadir ausencias dentro del año actual

View File

@ -16,5 +16,12 @@
"type": "string", "type": "string",
"required": false "required": false
} }
},
"relations": {
"supplierAgencyTerm": {
"type": "hasOne",
"model": "SupplierAgencyTerm",
"foreignKey": "agencyFk"
}
} }
} }

View File

@ -8,11 +8,16 @@ module.exports = {
async serverPrefetch() { async serverPrefetch() {
this.filters = this.$options.filters; this.filters = this.$options.filters;
const args = { const args = {
landedFrom: this.landedStart,
landedTo: this.landedEnd, landedTo: this.landedEnd,
shippedFrom: this.shippedStart, shippedFrom: this.shippedStart,
shippedTo: this.shippedEnd, continent: this.continent,
continent: this.continent id: this.id,
agencyFk: this.agencyFk,
warehouseInFk: this.warehouseInFk,
warehouseOutFk: this.warehouseOutFk,
totalEntries: this.totalEntries,
ref: this.ref,
cargoSupplierFk: this.cargoSupplierFk
}; };
const travels = await this.fetchTravels(args); const travels = await this.fetchTravels(args);
@ -38,11 +43,6 @@ module.exports = {
dated: function() { dated: function() {
return this.filters.date(new Date(), '%d-%m-%Y'); return this.filters.date(new Date(), '%d-%m-%Y');
}, },
landedStart: function() {
if (!this.landedFrom) return;
return this.filters.date(this.landedFrom, '%Y-%m-%d');
},
landedEnd: function() { landedEnd: function() {
if (!this.landedTo) return; if (!this.landedTo) return;
@ -52,11 +52,6 @@ module.exports = {
if (!this.shippedFrom) return; if (!this.shippedFrom) return;
return this.filters.date(this.shippedFrom, '%Y-%m-%d'); return this.filters.date(this.shippedFrom, '%Y-%m-%d');
},
shippedEnd: function() {
if (!this.shippedTo) return;
return this.filters.date(this.shippedTo, '%Y-%m-%d');
} }
}, },
methods: { methods: {
@ -65,20 +60,29 @@ module.exports = {
switch (key) { switch (key) {
case 'shippedFrom': case 'shippedFrom':
return `t.shipped >= ${value}`; return `t.shipped >= ${value}`;
case 'shippedTo':
return `t.shipped <= ${value}`;
case 'landedFrom':
return `t.landed >= ${value}`;
case 'landedTo': case 'landedTo':
return `t.landed <= ${value}`; return `t.landed <= ${value}`;
case 'continent': case 'continent':
return `cnt.code = ${value}`; return `cnt.code = ${value}`;
case 'ref':
return {'t.ref': {like: `%${value}%`}};
case 'id':
return `t.id = ${value}`;
case 'agencyFk':
return `am.id = ${value}`;
case 'warehouseOutFk':
return `wo.id = ${value}`;
case 'warehouseInFk':
return `w.id = ${value}`;
case 'cargoSupplierFk':
return `s.id = ${value}`;
} }
}); });
let query = this.getSqlFromDef('travels'); let query = this.getSqlFromDef('travels');
query = db.merge(query, where); query = db.merge(query, where);
query = db.merge(query, 'GROUP BY t.id'); query = db.merge(query, 'GROUP BY t.id');
query = db.merge(query, 'ORDER BY `shipped` ASC, `landed` ASC, `travelFk`, `loadPriority`, `agencyModeFk`, `evaNotes`');
return this.rawSql(query); return this.rawSql(query);
}, },
@ -92,10 +96,15 @@ module.exports = {
'report-footer': reportFooter.build() 'report-footer': reportFooter.build()
}, },
props: [ props: [
'landedFrom',
'landedTo', 'landedTo',
'shippedFrom', 'shippedFrom',
'shippedTo', 'continent',
'continent' 'ref',
'id',
'agencyFk',
'warehouseOutFk',
'warehouseInFk',
'totalEntries',
'cargoSupplierFk'
] ]
}; };

View File

@ -4,6 +4,7 @@ SELECT
t.shipped, t.shipped,
t.landed, t.landed,
t.kg, t.kg,
am.id AS agencyModeFk,
SUM(b.stickers) AS stickers, SUM(b.stickers) AS stickers,
CAST(SUM(i.density * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000 ) as DECIMAL(10,0)) as loadedKg, CAST(SUM(i.density * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000 ) as DECIMAL(10,0)) as loadedKg,
CAST(SUM(167.5 * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000 ) as DECIMAL(10,0)) as volumeKg CAST(SUM(167.5 * b.stickers * IF(pkg.volume, pkg.volume, pkg.width * pkg.depth * pkg.height) / 1000000 ) as DECIMAL(10,0)) as volumeKg