add section Autonomous
gitea/salix/pipeline/head There was a failure building this commit
Details
gitea/salix/pipeline/head There was a failure building this commit
Details
This commit is contained in:
parent
90dc3bc5b7
commit
ade34c1e0a
|
@ -0,0 +1,2 @@
|
|||
INSERT INTO salix.ACL (id, model, property, accessType, permission, principalType, principalId)
|
||||
VALUES(301, 'Agency', '*', 'READ', 'ALLOW', 'ROLE', 'employee');
|
|
@ -0,0 +1,10 @@
|
|||
CREATE TABLE `vn`.`agencyTermConfig` (
|
||||
`expenceFk` varchar(10) DEFAULT NULL,
|
||||
`vatAccountSupported` varchar(15) DEFAULT NULL,
|
||||
`vatPercentage` decimal(28,10) DEFAULT NULL,
|
||||
`transaction` varchar(50) DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
INSERT INTO `vn`.`agencyTermConfig`
|
||||
(`expenceFk`, `vatAccountSupported`, `vatPercentage`, `transaction`)
|
||||
VALUES('6240000000', '4721000015', 21.0000000000, 'Adquisiciones intracomunitarias de servicios');
|
|
@ -167,9 +167,11 @@ INSERT INTO `vn`.`accountingType`(`id`, `description`, `receiptDescription`,`cod
|
|||
|
||||
INSERT INTO `vn`.`bank`(`id`, `bank`, `account`, `cash`, `entityFk`, `isActive`, `currencyFk`)
|
||||
VALUES
|
||||
(1, 'Pay on receipt', '5720000001', 3, 0, 1, 1),
|
||||
(2, 'Cash', '5700000001', 2, 0, 1, 1),
|
||||
(3, 'Compensation', '4000000000', 8, 0, 1, 1);
|
||||
(1, 'Pay on receipt', '5720000001', 3, 0, 1, 1),
|
||||
(2, 'Cash', '5700000001', 2, 0, 1, 1),
|
||||
(3, 'Compensation', '4000000000', 8, 0, 1, 1),
|
||||
(3117, 'Caixa Rural d''Algemesi', '5720000000', 8, 3117, 1, 1);
|
||||
|
||||
|
||||
INSERT INTO `vn`.`deliveryMethod`(`id`, `code`, `description`)
|
||||
VALUES
|
||||
|
@ -522,6 +524,8 @@ INSERT INTO `vn`.`expence`(`id`, `taxTypeFk`, `name`, `isWithheld`)
|
|||
(4751000000, 1, 'Retenciones', 1),
|
||||
(4751000000, 6, 'Retencion', 0),
|
||||
(6210000567, 0, 'Alquiler VNH', 0),
|
||||
(6240000000, 1, 'Transportes de ventas rutas', 0),
|
||||
(6240000000, 4, 'Transportes de ventas rutas', 0),
|
||||
(7001000000, 1, 'Mercaderia', 0),
|
||||
(7050000000, 1, 'Prestacion de servicios', 1);
|
||||
|
||||
|
@ -2465,4 +2469,4 @@ SET `invoiceInFk`=1
|
|||
WHERE `id`=1;
|
||||
UPDATE `vn`.`route`
|
||||
SET `invoiceInFk`=2
|
||||
WHERE `id`=2;
|
||||
WHERE `id`=2;
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethod('createInvoiceIn', {
|
||||
description: 'create a invoce in from a agency terms',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'rows',
|
||||
type: ['object'],
|
||||
required: true,
|
||||
description: `the rows from which the invoice in will be created`,
|
||||
},
|
||||
{
|
||||
arg: 'dms',
|
||||
type: ['object'],
|
||||
required: true,
|
||||
description: 'The dms files'
|
||||
}],
|
||||
returns: {
|
||||
},
|
||||
http: {
|
||||
path: `/createInvoiceIn`,
|
||||
verb: 'POST'
|
||||
}
|
||||
});
|
||||
|
||||
Self.createInvoiceIn = async(rows, dms, options) => {
|
||||
const models = Self.app.models;
|
||||
const myOptions = {};
|
||||
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
const [firstRow] = rows;
|
||||
const [firstDms] = dms;
|
||||
|
||||
const [reference] = await Self.rawSql(`SELECT reference FROM vn.dms WHERE id = ?`, [firstDms.id]);
|
||||
|
||||
const newInvoiceIn = await models.InvoiceIn.create({
|
||||
supplierFk: firstRow.supplierFk,
|
||||
supplierRef: reference.value,
|
||||
issued: firstRow.created,
|
||||
booked: firstRow.created,
|
||||
operated: firstRow.created,
|
||||
bookEntried: firstRow.created,
|
||||
gestdoc_id: firstDms.id
|
||||
});
|
||||
|
||||
const [expence] = await Self.rawSql(`SELECT expenceFk value FROM vn.agencyTermConfig`);
|
||||
|
||||
const [taxTypeSage] = await Self.rawSql(`
|
||||
SELECT IFNULL(s.taxTypeSageFk, CodigoIva) value
|
||||
FROM vn.supplier s
|
||||
JOIN sage.TiposIva ti ON TRUE
|
||||
JOIN vn.agencyTermConfig atg
|
||||
WHERE s.id = ?
|
||||
AND ti.CuentaIvaSoportado = atg.vatAccountSupported
|
||||
AND ti.PorcentajeIva = atg.vatPercentage
|
||||
`, [firstRow.supplierFk]);
|
||||
|
||||
const [transactionTypeSage] = await Self.rawSql(`
|
||||
SELECT IFNULL(s.transactionTypeSageFk, tt.CodigoTransaccion) value
|
||||
FROM vn.supplier s
|
||||
JOIN sage.TiposTransacciones tt ON TRUE
|
||||
JOIN vn.agencyTermConfig atg
|
||||
WHERE s.id = ?
|
||||
AND tt.Transaccion = atg.transaction
|
||||
`, [firstRow.supplierFk]);
|
||||
|
||||
await models.InvoiceInTax.create({
|
||||
invoiceInFk: newInvoiceIn.id,
|
||||
taxableBase: firstRow.totalPrice,
|
||||
expenseFk: expence.value,
|
||||
taxTypeSageFk: taxTypeSage.value,
|
||||
transactionTypeSageFk: transactionTypeSage.value
|
||||
});
|
||||
|
||||
await Self.rawSql(`CALL invoiceInDueDay_calculate(?)`, [newInvoiceIn.id]);
|
||||
|
||||
for (let agencyTerm of rows) {
|
||||
const route = await models.Route.findById(agencyTerm.routeFk);
|
||||
await Self.rawSql(`
|
||||
UPDATE vn.route SET invoiceInFk = ? WHERE id = ?
|
||||
`, [newInvoiceIn.id, route.id]);
|
||||
}
|
||||
};
|
||||
};
|
|
@ -1,7 +1,4 @@
|
|||
|
||||
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||
const buildFilter = require('vn-loopback/util/filter').buildFilter;
|
||||
const mergeFilters = require('vn-loopback/util/filter').mergeFilters;
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('filter', {
|
||||
|
@ -13,54 +10,6 @@ module.exports = Self => {
|
|||
type: 'object',
|
||||
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'search',
|
||||
type: 'string',
|
||||
description: 'Searchs the route by id',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'agencyModeFk',
|
||||
type: 'integer',
|
||||
description: 'The agencyMode id',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'to',
|
||||
type: 'date',
|
||||
description: 'The to date filter',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'from',
|
||||
type: 'date',
|
||||
description: 'The to date filter',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'vehicleFk',
|
||||
type: 'integer',
|
||||
description: 'The vehicle id',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'm3',
|
||||
type: 'number',
|
||||
description: 'The m3 filter',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'warehouseFk',
|
||||
type: 'number',
|
||||
description: 'The warehouse filter',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'description',
|
||||
type: 'string',
|
||||
description: 'The description filter',
|
||||
http: {source: 'query'}
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
|
@ -73,70 +22,52 @@ module.exports = Self => {
|
|||
}
|
||||
});
|
||||
|
||||
Self.filter = async(ctx, filter) => {
|
||||
let conn = Self.dataSource.connector;
|
||||
|
||||
let where = buildFilter(ctx.args, (param, value) => {
|
||||
switch (param) {
|
||||
case 'search':
|
||||
return {'r.id': value};
|
||||
case 'from':
|
||||
return {'r.created': {gte: value}};
|
||||
case 'to':
|
||||
return {'r.created': {lte: value}};
|
||||
case 'm3':
|
||||
return {'r.m3': value};
|
||||
case 'description':
|
||||
return {'r.description': {like: `%${value}%`}};
|
||||
case 'warehouseFk':
|
||||
param = `v.${param}`;
|
||||
return {[param]: value};
|
||||
case 'vehicleFk':
|
||||
case 'agencyModeFk':
|
||||
param = `r.${param}`;
|
||||
return {[param]: value};
|
||||
}
|
||||
});
|
||||
|
||||
filter = mergeFilters(ctx.args.filter, {where});
|
||||
Self.filter = async(ctx, filter, options) => {
|
||||
const conn = Self.dataSource.connector;
|
||||
|
||||
let stmts = [];
|
||||
let stmt;
|
||||
|
||||
stmt = new ParameterizedSQL(
|
||||
`SELECT
|
||||
r.id routeFk,
|
||||
r.created,
|
||||
r.agencyModeFk,
|
||||
am.name agencyModeName,
|
||||
am.agencyFk,
|
||||
a.name agencyAgreement,
|
||||
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) )
|
||||
AS DECIMAL(10,2)) price,
|
||||
r.invoiceInFk,
|
||||
a.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
|
||||
GROUP BY r.id;`
|
||||
`SELECT *
|
||||
FROM (
|
||||
SELECT r.id routeFk,
|
||||
r.created,
|
||||
r.agencyModeFk,
|
||||
am.name agencyModeName,
|
||||
am.agencyFk,
|
||||
a.name agencyAgreement,
|
||||
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) )
|
||||
AS DECIMAL(10,2)) price,
|
||||
r.invoiceInFk,
|
||||
a.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
|
||||
GROUP BY r.id
|
||||
) a`
|
||||
);
|
||||
|
||||
stmt.merge(conn.makeSuffix(filter));
|
||||
let agencyTerm = stmts.push(stmt) - 1;
|
||||
|
||||
let agencyTerm = stmts.push(stmt) - 1;
|
||||
let sql = ParameterizedSQL.join(stmts, ';');
|
||||
let result = await conn.executeStmt(sql);
|
||||
|
||||
const models = Self.app.models;
|
||||
for (let agencyTerm of result)
|
||||
agencyTerm.route = await models.Route.findById(agencyTerm.routeFk);
|
||||
|
||||
return agencyTerm === 0 ? result : result[agencyTerm];
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
module.exports = Self => {
|
||||
require('../methods/agency-term/filter')(Self);
|
||||
require('../methods/agency-term/createInvoiceIn')(Self);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
<mg-ajax path="dms/upload" options="vnPost"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.dms">
|
||||
</vn-watcher>
|
||||
<vn-crud-model
|
||||
auto-load="true"
|
||||
url="Companies"
|
||||
data="companies"
|
||||
order="code">
|
||||
</vn-crud-model>
|
||||
<vn-crud-model
|
||||
auto-load="true"
|
||||
url="Warehouses"
|
||||
data="warehouses"
|
||||
order="name">
|
||||
</vn-crud-model>
|
||||
<vn-crud-model
|
||||
auto-load="true"
|
||||
url="DmsTypes"
|
||||
data="dmsTypes"
|
||||
order="name">
|
||||
</vn-crud-model>
|
||||
<form
|
||||
name="form"
|
||||
ng-submit="$ctrl.onSubmit()"
|
||||
class="vn-ma-md"
|
||||
enctype="multipart/form-data">
|
||||
<div class="vn-w-md">
|
||||
<vn-card class="vn-pa-lg">
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
vn-focus
|
||||
label="Reference"
|
||||
ng-model="$ctrl.dms.reference"
|
||||
rule>
|
||||
</vn-textfield>
|
||||
<vn-autocomplete vn-one
|
||||
label="Company"
|
||||
ng-model="$ctrl.dms.companyId"
|
||||
data="companies"
|
||||
show-field="code"
|
||||
value-field="id">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete vn-one
|
||||
label="Warehouse"
|
||||
ng-model="$ctrl.dms.warehouseId"
|
||||
data="warehouses"
|
||||
show-field="name"
|
||||
value-field="id">
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete vn-one
|
||||
label="Type"
|
||||
ng-model="$ctrl.dms.dmsTypeId"
|
||||
data="dmsTypes"
|
||||
show-field="name"
|
||||
value-field="id">
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textarea
|
||||
vn-one
|
||||
label="Description"
|
||||
ng-model="$ctrl.dms.description"
|
||||
rule>
|
||||
</vn-textarea>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-input-file
|
||||
vn-one
|
||||
label="File"
|
||||
ng-model="$ctrl.dms.files"
|
||||
on-change="$ctrl.onFileChange($files)"
|
||||
accept="{{$ctrl.allowedContentTypes}}"
|
||||
required="true"
|
||||
multiple="true">
|
||||
<append>
|
||||
<vn-icon vn-none
|
||||
color-marginal
|
||||
title="{{$ctrl.contentTypesInfo}}"
|
||||
icon="info">
|
||||
</vn-icon>
|
||||
</append>
|
||||
</vn-input-file>
|
||||
</vn-horizontal>
|
||||
<vn-vertical>
|
||||
<vn-check
|
||||
label="Generate identifier for original file"
|
||||
ng-model="$ctrl.dms.hasFile">
|
||||
</vn-check>
|
||||
</vn-vertical>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit
|
||||
disabled="!watcher.dataChanged()"
|
||||
label="Upload">
|
||||
</vn-submit>
|
||||
<vn-button
|
||||
class="cancel"
|
||||
label="Cancel"
|
||||
ui-sref="client.card.dms.index">
|
||||
</vn-button>
|
||||
</vn-button-bar>
|
||||
</div>
|
||||
</form>
|
|
@ -0,0 +1,123 @@
|
|||
import ngModule from '../../module';
|
||||
import Section from 'salix/components/section';
|
||||
import './style.scss';
|
||||
|
||||
class Controller extends Section {
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
this.dms = {
|
||||
files: [],
|
||||
hasFile: false,
|
||||
hasFileAttached: false
|
||||
};
|
||||
this.addedDms;
|
||||
}
|
||||
|
||||
get route() {
|
||||
return this._route;
|
||||
}
|
||||
|
||||
set route(value) {
|
||||
this._route = value;
|
||||
|
||||
this.setDefaultParams();
|
||||
this.getAllowedContentTypes();
|
||||
}
|
||||
|
||||
$onChanges() {
|
||||
if (this.$params && this.$params.q)
|
||||
this.params = JSON.parse(this.$params.q);
|
||||
}
|
||||
|
||||
getAllowedContentTypes() {
|
||||
this.$http.get('DmsContainers/allowedContentTypes').then(res => {
|
||||
const contentTypes = res.data.join(', ');
|
||||
this.allowedContentTypes = contentTypes;
|
||||
});
|
||||
}
|
||||
|
||||
get contentTypesInfo() {
|
||||
return this.$t('ContentTypesInfo', {
|
||||
allowedContentTypes: this.allowedContentTypes
|
||||
});
|
||||
}
|
||||
|
||||
setDefaultParams() {
|
||||
const params = {filter: {
|
||||
where: {code: 'invoiceIn'}
|
||||
}};
|
||||
this.$http.get('DmsTypes/findOne', {params}).then(res => {
|
||||
const dmsType = res.data && res.data;
|
||||
const companyId = this.vnConfig.companyFk;
|
||||
const warehouseId = this.vnConfig.warehouseFk;
|
||||
const defaultParams = {
|
||||
warehouseId: warehouseId,
|
||||
companyId: companyId,
|
||||
dmsTypeId: dmsType.id,
|
||||
description: this.params.supplierName
|
||||
};
|
||||
|
||||
this.dms = Object.assign(this.dms, defaultParams);
|
||||
});
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
const query = `dms/uploadFile`;
|
||||
const options = {
|
||||
method: 'POST',
|
||||
url: query,
|
||||
params: this.dms,
|
||||
headers: {
|
||||
'Content-Type': undefined
|
||||
},
|
||||
transformRequest: files => {
|
||||
const formData = new FormData();
|
||||
|
||||
for (let i = 0; i < files.length; i++)
|
||||
formData.append(files[i].name, files[i]);
|
||||
|
||||
return formData;
|
||||
},
|
||||
data: this.dms.files
|
||||
};
|
||||
this.$http(options).then(res => {
|
||||
if (res) {
|
||||
let addedDms = res.data;
|
||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||
this.$.watcher.updateOriginalData();
|
||||
|
||||
const params = {
|
||||
rows: this.params.rows,
|
||||
dms: addedDms
|
||||
};
|
||||
|
||||
this.$http.post('AgencyTerms/createInvoiceIn', params)
|
||||
.then(() => {
|
||||
this.$state.go('route.agencyTerm.index');
|
||||
this.vnApp.showSuccess(this.$t('InvoiceIn created'));
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onFileChange(files) {
|
||||
let hasFileAttached = false;
|
||||
|
||||
if (files.length > 0)
|
||||
hasFileAttached = true;
|
||||
|
||||
this.$.$applyAsync(() => {
|
||||
this.dms.hasFileAttached = hasFileAttached;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope'];
|
||||
|
||||
ngModule.vnComponent('vnAgencyTermCreateInvoiceIn', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
route: '<'
|
||||
}
|
||||
});
|
|
@ -0,0 +1,74 @@
|
|||
import './index';
|
||||
|
||||
describe('Client', () => {
|
||||
describe('Component vnClientDmsCreate', () => {
|
||||
let controller;
|
||||
let $scope;
|
||||
let $httpBackend;
|
||||
let $httpParamSerializer;
|
||||
|
||||
beforeEach(ngModule('client'));
|
||||
|
||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_, _$httpParamSerializer_) => {
|
||||
$scope = $rootScope.$new();
|
||||
$httpBackend = _$httpBackend_;
|
||||
$httpParamSerializer = _$httpParamSerializer_;
|
||||
const $element = angular.element('<vn-client-create></vn-client-create>');
|
||||
controller = $componentController('vnClientDmsCreate', {$element, $scope});
|
||||
controller._client = {id: 1101, name: 'Bruce wayne'};
|
||||
}));
|
||||
|
||||
describe('client() setter', () => {
|
||||
it('should set the client data and then call setDefaultParams() and getAllowedContentTypes()', () => {
|
||||
jest.spyOn(controller, 'setDefaultParams');
|
||||
jest.spyOn(controller, 'getAllowedContentTypes');
|
||||
controller.client = {
|
||||
id: 15,
|
||||
name: 'Bruce wayne'
|
||||
};
|
||||
|
||||
expect(controller.client).toBeDefined();
|
||||
expect(controller.setDefaultParams).toHaveBeenCalledWith();
|
||||
expect(controller.getAllowedContentTypes).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('setDefaultParams()', () => {
|
||||
it('should perform a GET query and define the dms property on controller', () => {
|
||||
const params = {filter: {
|
||||
where: {code: 'paymentsLaw'}
|
||||
}};
|
||||
let serializedParams = $httpParamSerializer(params);
|
||||
$httpBackend.expect('GET', `DmsTypes/findOne?${serializedParams}`).respond({id: 12, code: 'paymentsLaw'});
|
||||
controller.setDefaultParams();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.dms).toBeDefined();
|
||||
expect(controller.dms.reference).toEqual(1101);
|
||||
expect(controller.dms.dmsTypeId).toEqual(12);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onFileChange()', () => {
|
||||
it('should set dms hasFileAttached property to true if has any files', () => {
|
||||
const files = [{id: 1, name: 'MyFile'}];
|
||||
controller.onFileChange(files);
|
||||
$scope.$apply();
|
||||
|
||||
expect(controller.dms.hasFileAttached).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAllowedContentTypes()', () => {
|
||||
it('should make an HTTP GET request to get the allowed content types', () => {
|
||||
const expectedResponse = ['image/png', 'image/jpg'];
|
||||
$httpBackend.expect('GET', `DmsContainers/allowedContentTypes`).respond(expectedResponse);
|
||||
controller.getAllowedContentTypes();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.allowedContentTypes).toBeDefined();
|
||||
expect(controller.allowedContentTypes).toEqual('image/png, image/jpg');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,7 @@
|
|||
vn-ticket-request {
|
||||
.vn-textfield {
|
||||
margin: 0!important;
|
||||
max-width: 100px;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
import ngModule from '../module';
|
||||
import Section from 'salix/components/section';
|
||||
import './style.scss';
|
||||
|
||||
class Controller extends Section {
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
|
||||
this.smartTableOptions = {
|
||||
activeButtons: {
|
||||
search: false,
|
||||
shownColumns: false,
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
field: 'agencyFk',
|
||||
autocomplete: {
|
||||
url: 'ItemCategories',
|
||||
valueField: 'name',
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'origin',
|
||||
autocomplete: {
|
||||
url: 'Origins',
|
||||
showField: 'code',
|
||||
valueField: 'code'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'typeFk',
|
||||
autocomplete: {
|
||||
url: 'ItemTypes',
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'intrastat',
|
||||
autocomplete: {
|
||||
url: 'Intrastats',
|
||||
showField: 'description',
|
||||
valueField: 'description'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'buyerFk',
|
||||
autocomplete: {
|
||||
url: 'Workers/activeWithRole',
|
||||
where: `{role: {inq: ['logistic', 'buyer']}}`,
|
||||
searchFunction: '{firstName: $search}',
|
||||
showField: 'nickname',
|
||||
valueField: 'id',
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'active',
|
||||
searchable: false
|
||||
},
|
||||
{
|
||||
field: 'landed',
|
||||
searchable: false
|
||||
},
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
exprBuilder(param, value) {
|
||||
switch (param) {
|
||||
case 'category':
|
||||
return {'ic.name': value};
|
||||
case 'buyerFk':
|
||||
return {'it.workerFk': value};
|
||||
case 'grouping':
|
||||
return {'b.grouping': value};
|
||||
case 'packing':
|
||||
return {'b.packing': value};
|
||||
case 'origin':
|
||||
return {'ori.code': value};
|
||||
case 'typeFk':
|
||||
return {'i.typeFk': value};
|
||||
case 'intrastat':
|
||||
return {'intr.description': value};
|
||||
case 'name':
|
||||
return {'i.name': {like: `%${value}%`}};
|
||||
case 'producer':
|
||||
return {'pr.name': {like: `%${value}%`}};
|
||||
case 'id':
|
||||
case 'size':
|
||||
case 'subname':
|
||||
case 'isActive':
|
||||
case 'density':
|
||||
case 'stemMultiplier':
|
||||
case 'stems':
|
||||
return {[`i.${param}`]: value};
|
||||
}
|
||||
}
|
||||
|
||||
get checked() {
|
||||
const routes = this.$.model.data || [];
|
||||
const checkedRoutes = [];
|
||||
for (let route of routes) {
|
||||
if (route.checked)
|
||||
checkedRoutes.push(route);
|
||||
}
|
||||
|
||||
return checkedRoutes;
|
||||
}
|
||||
|
||||
get totalChecked() {
|
||||
return this.checked.length;
|
||||
}
|
||||
|
||||
preview(route) {
|
||||
this.routeSelected = route;
|
||||
this.$.summary.show();
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnAgencyTerm', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -10,6 +10,17 @@
|
|||
model="model"
|
||||
options="$ctrl.smartTableOptions"
|
||||
expr-builder="$ctrl.exprBuilder(param, value)">
|
||||
<slot-actions>
|
||||
<div>
|
||||
<div class="totalBox" style="text-align: center;">
|
||||
<h6 translate>Total</h6>
|
||||
<vn-label-value
|
||||
label="Price"
|
||||
value="{{$ctrl.totalPrice | currency: 'EUR': 2}}">
|
||||
</vn-label-value>
|
||||
</div>
|
||||
</div>
|
||||
</slot-actions>
|
||||
<slot-table>
|
||||
<table>
|
||||
<thead>
|
||||
|
@ -19,7 +30,7 @@
|
|||
model="model">
|
||||
</vn-multi-check>
|
||||
</th>
|
||||
<th field="routeFk">
|
||||
<th shrink field="routeFk">
|
||||
<span translate>Id</span>
|
||||
</th>
|
||||
<th field="created">
|
||||
|
@ -82,7 +93,6 @@
|
|||
{{::agencyTerm.invoiceInFk}}
|
||||
</span>
|
||||
</td>
|
||||
<!-- <td>{{::agencyTerm.invoiceInFk | dashIfEmpty}}</td> -->
|
||||
<td>
|
||||
<span
|
||||
class="link"
|
||||
|
@ -92,7 +102,7 @@
|
|||
</td>
|
||||
<td>
|
||||
<vn-icon-button
|
||||
vn-click-stop="$ctrl.preview(agencyTerm.routeFk)"
|
||||
vn-click-stop="$ctrl.preview(agencyTerm.route)"
|
||||
vn-tooltip="Preview"
|
||||
icon="preview">
|
||||
</vn-icon-button>
|
||||
|
@ -120,30 +130,14 @@
|
|||
vn-id="invoiceInDescriptor">
|
||||
</vn-invoice-in-descriptor-popover>
|
||||
|
||||
<vn-contextmenu
|
||||
vn-id="contextmenu"
|
||||
targets="['smart-table']"
|
||||
model="model"
|
||||
expr-builder="$ctrl.exprBuilder(param, value)">
|
||||
<slot-menu>
|
||||
<vn-item translate
|
||||
ng-if="contextmenu.isFilterAllowed()"
|
||||
ng-click="contextmenu.filterBySelection()">
|
||||
Filter by selection
|
||||
</vn-item>
|
||||
<vn-item translate
|
||||
ng-if="contextmenu.isFilterAllowed()"
|
||||
ng-click="contextmenu.excludeSelection()">
|
||||
Exclude selection
|
||||
</vn-item>
|
||||
<vn-item translate
|
||||
ng-if="contextmenu.isFilterAllowed()"
|
||||
ng-click="contextmenu.removeFilter()">
|
||||
Remove filter
|
||||
</vn-item>
|
||||
<vn-item translate
|
||||
ng-click="contextmenu.removeAllFilters()">
|
||||
Remove all filters
|
||||
</vn-item>
|
||||
</slot-menu>
|
||||
</vn-contextmenu>
|
||||
<div fixed-bottom-right>
|
||||
<vn-vertical style="align-items: center;">
|
||||
<vn-button class="round sm vn-mb-sm"
|
||||
icon="icon-invoice-in-create"
|
||||
ng-show="$ctrl.totalChecked > 0"
|
||||
ng-click="$ctrl.createInvoiceIn()"
|
||||
vn-tooltip="Create invoiceIn"
|
||||
tooltip-position="left">
|
||||
</vn-button>
|
||||
</vn-vertical>
|
||||
</div>
|
|
@ -0,0 +1,127 @@
|
|||
import ngModule from '../../module';
|
||||
import Section from 'salix/components/section';
|
||||
import './style.scss';
|
||||
|
||||
class Controller extends Section {
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
|
||||
this.smartTableOptions = {
|
||||
activeButtons: {
|
||||
search: true
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
field: 'agencyFk',
|
||||
autocomplete: {
|
||||
url: 'AgencyModes',
|
||||
showField: 'name',
|
||||
valueField: 'name'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'agencyAgreement',
|
||||
autocomplete: {
|
||||
url: 'Agencies',
|
||||
showField: 'name',
|
||||
valueField: 'name'
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'supplierFk',
|
||||
autocomplete: {
|
||||
url: 'Suppliers',
|
||||
showField: 'name',
|
||||
valueField: 'name',
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
exprBuilder(param, value) {
|
||||
switch (param) {
|
||||
case 'routeFk':
|
||||
return {'a.routeFk': value};
|
||||
case 'created':
|
||||
return {'a.created': value};
|
||||
case 'agencyFk':
|
||||
return {'a.agencyModeName': value};
|
||||
case 'agencyAgreement':
|
||||
return {'a.agencyAgreement': value};
|
||||
case 'packages':
|
||||
return {'a.packages': value};
|
||||
case 'm3':
|
||||
return {'a.m3': value};
|
||||
case 'kmTotal':
|
||||
return {'a.kmTotal': value};
|
||||
case 'price':
|
||||
return {'a.price': value};
|
||||
case 'invoiceInFk':
|
||||
return {'a.invoiceInFk': value};
|
||||
case 'supplierFk':
|
||||
return {'a.supplierName': value};
|
||||
}
|
||||
}
|
||||
|
||||
get checked() {
|
||||
const agencyTerms = this.$.model.data || [];
|
||||
const checkedAgencyTerms = [];
|
||||
for (let agencyTerm of agencyTerms) {
|
||||
if (agencyTerm.checked)
|
||||
checkedAgencyTerms.push(agencyTerm);
|
||||
}
|
||||
|
||||
return checkedAgencyTerms;
|
||||
}
|
||||
|
||||
get totalChecked() {
|
||||
return this.checked.length;
|
||||
}
|
||||
|
||||
get totalPrice() {
|
||||
let totalPrice = 0;
|
||||
|
||||
if (this.checked.length > 0) {
|
||||
for (let agencyTerm of this.checked)
|
||||
totalPrice += agencyTerm.price;
|
||||
|
||||
return totalPrice;
|
||||
}
|
||||
|
||||
return totalPrice;
|
||||
}
|
||||
|
||||
preview(route) {
|
||||
this.routeSelected = route;
|
||||
this.$.summary.show();
|
||||
}
|
||||
|
||||
createInvoiceIn() {
|
||||
const rowsToCreateInvoiceIn = [];
|
||||
const supplier = this.checked[0].supplierFk;
|
||||
|
||||
for (let agencyTerm of this.checked) {
|
||||
if (supplier == agencyTerm.supplierFk) {
|
||||
rowsToCreateInvoiceIn.push({
|
||||
routeFk: agencyTerm.routeFk,
|
||||
supplierFk: agencyTerm.supplierFk,
|
||||
created: agencyTerm.created,
|
||||
totalPrice: this.totalPrice});
|
||||
} else {
|
||||
this.vnApp.showError(this.$t('Two autonomous cannot be counted at the same time'));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const params = JSON.stringify({
|
||||
supplierName: this.checked[0].supplierName,
|
||||
rows: rowsToCreateInvoiceIn
|
||||
});
|
||||
this.$state.go('route.agencyTerm.createInvoiceIn', {q: params});
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.vnComponent('vnAgencyTermIndex', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -1,11 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 21.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 30 24" style="enable-background:new 0 0 30 24;" xml:space="preserve" width="24px" heigth="24px">
|
||||
<g>
|
||||
<path d="M27,0H3C1.4,0,0,1.3,0,3v18c0,1.7,1.4,3,3,3h24c1.6,0,3-1.3,3-3V3C30,1.3,28.6,0,27,0z M27.9,19.8c0,1.4-1.2,2.6-2.6,2.6
|
||||
H4.6c-1.4,0-2.6-1.2-2.6-2.6V4.2c0-1.4,1.2-2.6,2.6-2.6h20.7c1.4,0,2.6,1.2,2.6,2.6V19.8z"/>
|
||||
<path d="M24.6,2.9H5.4c-1,0-1.9,0.8-1.9,1.9v14.4c0,1,0.8,1.9,1.9,1.9h19.1c1,0,1.9-0.8,1.9-1.9V4.8C26.4,3.8,25.6,2.9,24.6,2.9z"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 750 B |
|
@ -11,4 +11,5 @@ import './create';
|
|||
import './basic-data';
|
||||
import './log';
|
||||
import './tickets';
|
||||
import './agency-term';
|
||||
import './agency-term/index';
|
||||
import './agency-term/createInvoiceIn';
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
"name": "Routes",
|
||||
"icon": "icon-delivery",
|
||||
"validations" : true,
|
||||
"dependencies": ["client", "worker", "ticket"],
|
||||
"dependencies": ["client", "worker", "ticket", "supplier", "invoiceIn"],
|
||||
"menus": {
|
||||
"main": [
|
||||
{"state": "route.index", "icon": "icon-delivery"},
|
||||
{"state": "route.agencyTerm", "icon": "icon-delivery"}
|
||||
{"state": "route.agencyTerm.index", "icon": "icon-delivery"}
|
||||
],
|
||||
"card": [
|
||||
{"state": "route.card.basicData", "icon": "settings"},
|
||||
|
@ -39,11 +39,25 @@
|
|||
"abstract": true,
|
||||
"component": "vn-route-card"
|
||||
}, {
|
||||
"url" : "/agency-term?q",
|
||||
"url": "/agency-term",
|
||||
"abstract": true,
|
||||
"state": "route.agencyTerm",
|
||||
"component": "vn-agency-term",
|
||||
"component": "ui-view"
|
||||
}, {
|
||||
"url": "/index",
|
||||
"state": "route.agencyTerm.index",
|
||||
"component": "vn-agency-term-index",
|
||||
"description": "Autonomous",
|
||||
"acl": ["administrative"]
|
||||
},{
|
||||
"url": "/createInvoiceIn?q",
|
||||
"state": "route.agencyTerm.createInvoiceIn",
|
||||
"component": "vn-agency-term-create-invoice-in",
|
||||
"description": "Create invoiceIn",
|
||||
"params": {
|
||||
"route": "$ctrl.route"
|
||||
},
|
||||
"acl": ["administrative"]
|
||||
}, {
|
||||
"url": "/summary",
|
||||
"state": "route.card.summary",
|
||||
|
|
Loading…
Reference in New Issue