3604-route_agencyTerm #893
|
@ -9,35 +9,35 @@ module.exports = Self => {
|
|||
accepts: [
|
||||
{
|
||||
arg: 'warehouseId',
|
||||
type: 'Number',
|
||||
type: 'number',
|
||||
description: 'The warehouse id',
|
||||
required: true
|
||||
}, {
|
||||
arg: 'companyId',
|
||||
type: 'Number',
|
||||
type: 'number',
|
||||
description: 'The company id',
|
||||
required: true
|
||||
}, {
|
||||
arg: 'dmsTypeId',
|
||||
type: 'Number',
|
||||
type: 'number',
|
||||
description: 'The dms type id',
|
||||
required: true
|
||||
}, {
|
||||
arg: 'reference',
|
||||
type: 'String',
|
||||
type: 'string',
|
||||
required: true
|
||||
}, {
|
||||
arg: 'description',
|
||||
type: 'String',
|
||||
type: 'string',
|
||||
required: true
|
||||
}, {
|
||||
arg: 'hasFile',
|
||||
type: 'Boolean',
|
||||
type: 'boolean',
|
||||
description: 'True if has an attached file',
|
||||
required: true
|
||||
}],
|
||||
returns: {
|
||||
type: 'Object',
|
||||
type: 'object',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
|
|
|
@ -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,2 @@
|
|||
INSERT INTO salix.ACL (model,property,accessType,principalId)
|
||||
VALUES ('AgencyTerm','*','*','administrative');
|
|
@ -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');
|
|
@ -169,7 +169,9 @@ INSERT INTO `vn`.`bank`(`id`, `bank`, `account`, `cash`, `entityFk`, `isActive`,
|
|||
VALUES
|
||||
(1, 'Pay on receipt', '5720000001', 3, 0, 1, 1),
|
||||
(2, 'Cash', '5700000001', 2, 0, 1, 1),
|
||||
(3, 'Compensation', '4000000000', 8, 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);
|
||||
|
||||
|
@ -2453,6 +2457,28 @@ 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`=2;
|
||||
UPDATE `vn`.`agency`
|
||||
SET `supplierFk`=2
|
||||
WHERE `id`=3;
|
||||
|
||||
UPDATE `vn`.`route`
|
||||
SET `invoiceInFk`=1
|
||||
WHERE `id`=1;
|
||||
UPDATE `vn`.`route`
|
||||
SET `invoiceInFk`=2
|
||||
WHERE `id`=2;
|
||||
INSERT INTO `bs`.`salesPerson` (`workerFk`, `year`, `month`, `portfolioWeight`)
|
||||
VALUES
|
||||
(18, YEAR(CURDATE()), MONTH(CURDATE()), 807.23),
|
||||
|
|
|
@ -219,5 +219,6 @@
|
|||
"You can not modify is pay method checked": "No se puede modificar el campo método de pago validado",
|
||||
"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 item is required": "El artículo es requerido",
|
||||
"reference duplicated": "Referencia duplicada"
|
||||
}
|
|
@ -79,7 +79,6 @@
|
|||
</vn-autocomplete>
|
||||
<vn-input-number
|
||||
vn-one
|
||||
min="0"
|
||||
step="0.1"
|
||||
label="Commission"
|
||||
ng-model="$ctrl.entry.commission"
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
"menus": {
|
||||
"main": [
|
||||
{"state": "entry.index", "icon": "icon-entry"},
|
||||
{"state": "entry.latestBuys", "icon": "icon-lastBuy"}
|
||||
{"state": "entry.latestBuys", "icon": "contact_support"}
|
||||
],
|
||||
"card": [
|
||||
{"state": "entry.card.basicData", "icon": "settings"},
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethod('createInvoiceIn', {
|
||||
description: 'Creates an invoiceIn from one or more agency terms',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'rows',
|
||||
type: ['object'],
|
||||
required: true,
|
||||
description: `The rows from which the invoiceIn will be created`,
|
||||
},
|
||||
{
|
||||
arg: 'dms',
|
||||
type: ['object'],
|
||||
required: true,
|
||||
description: 'The dms file attached'
|
||||
}],
|
||||
returns: {
|
||||
type: 'object',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/createInvoiceIn`,
|
||||
verb: 'POST'
|
||||
}
|
||||
});
|
||||
|
||||
Self.createInvoiceIn = async(rows, dms, options) => {
|
||||
const models = Self.app.models;
|
||||
|
||||
let tx;
|
||||
const myOptions = {};
|
||||
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
if (!myOptions.transaction) {
|
||||
tx = await Self.beginTransaction({});
|
||||
myOptions.transaction = tx;
|
||||
}
|
||||
|
||||
try {
|
||||
const [firstRow] = rows;
|
||||
const [firstDms] = dms;
|
||||
|
||||
const reference = await models.Dms.findById([firstDms.id], null, myOptions);
|
||||
|
||||
const newInvoiceIn = await models.InvoiceIn.create({
|
||||
supplierFk: firstRow.supplierFk,
|
||||
supplierRef: reference.reference,
|
||||
issued: firstRow.created,
|
||||
booked: firstRow.created,
|
||||
operated: firstRow.created,
|
||||
bookEntried: firstRow.created,
|
||||
dmsFk: firstDms.id,
|
||||
}, myOptions);
|
||||
|
||||
const expence = await models.AgencyTermConfig.findOne(null, myOptions);
|
||||
|
||||
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], myOptions);
|
||||
|
||||
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], myOptions);
|
||||
|
||||
await models.InvoiceInTax.create({
|
||||
invoiceInFk: newInvoiceIn.id,
|
||||
taxableBase: firstRow.totalPrice,
|
||||
expenseFk: expence.expenceFk,
|
||||
taxTypeSageFk: taxTypeSage.value,
|
||||
transactionTypeSageFk: transactionTypeSage.value
|
||||
}, myOptions);
|
||||
|
||||
await Self.rawSql(`CALL invoiceInDueDay_calculate(?)`, [newInvoiceIn.id], myOptions);
|
||||
|
||||
for (let agencyTerm of rows) {
|
||||
const route = await models.Route.findById(agencyTerm.routeFk, null, myOptions);
|
||||
await Self.rawSql(`
|
||||
UPDATE vn.route SET invoiceInFk = ? WHERE id = ?
|
||||
`, [newInvoiceIn.id, route.id], myOptions);
|
||||
vicent marked this conversation as resolved
|
||||
}
|
||||
|
||||
if (tx) await tx.commit();
|
||||
|
||||
return newInvoiceIn;
|
||||
} catch (e) {
|
||||
if (tx) await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
};
|
|
@ -0,0 +1,77 @@
|
|||
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('filter', {
|
||||
description: 'Find all instances of the model matched by filter from the data source.',
|
||||
accessType: 'READ',
|
||||
accepts: [
|
||||
{
|
||||
arg: 'filter',
|
||||
type: 'object',
|
||||
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
|
||||
http: {source: 'query'}
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: ['object'],
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/filter`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.filter = async(ctx, filter, options) => {
|
||||
const conn = Self.dataSource.connector;
|
||||
const myOptions = {};
|
||||
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
const stmts = [];
|
||||
const stmt = new ParameterizedSQL(
|
||||
`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));
|
||||
|
||||
const agencyTerm = stmts.push(stmt) - 1;
|
||||
const sql = ParameterizedSQL.join(stmts, ';');
|
||||
const result = await conn.executeStmt(sql, myOptions);
|
||||
|
||||
const models = Self.app.models;
|
||||
for (let agencyTerm of result)
|
||||
agencyTerm.route = await models.Route.findById(agencyTerm.routeFk);
|
||||
|
||||
return agencyTerm === 0 ? result : result[agencyTerm];
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
// Include after #3638 export database
|
||||
xdescribe('AgencyTerm createInvoiceIn()', () => {
|
||||
const rows = [
|
||||
{
|
||||
routeFk: 2,
|
||||
supplierFk: 1,
|
||||
created: '2022-03-02T23:00:00.000Z',
|
||||
totalPrice: 165
|
||||
}
|
||||
];
|
||||
const dms = [
|
||||
{
|
||||
id: 6
|
||||
}
|
||||
];
|
||||
|
||||
it('should make an invoiceIn', async() => {
|
||||
const tx = await models.AgencyTerm.beginTransaction({});
|
||||
const options = {transaction: tx};
|
||||
|
||||
try {
|
||||
const invoiceInId = 10;
|
||||
const invoiceInDueDayId = 11;
|
||||
const invoiceInTaxId = 12;
|
||||
|
||||
const oldInvoiceIn = await models.InvoiceIn.findById(invoiceInId, null, options);
|
||||
const oldInvoiceInDueDay = await models.InvoiceInDueDay.findById(invoiceInDueDayId, null, options);
|
||||
const oldInvoiceInTax = await models.InvoiceInTax.findById(invoiceInTaxId, null, options);
|
||||
|
||||
await models.AgencyTerm.createInvoiceIn(rows, dms, options);
|
||||
|
||||
const [newInvoiceIn] = await models.InvoiceIn.rawSql('SELECT MAX(id) id FROM invoiceIn', null, options);
|
||||
const [newInvoiceInDueDay] = await models.InvoiceInDueDay.rawSql('SELECT MAX(id) id FROM invoiceInDueDay', null, options);
|
||||
const [newInvoiceInTax] = await models.InvoiceInTax.rawSql('SELECT MAX(id) id FROM invoiceInTax', null, options);
|
||||
|
||||
expect(newInvoiceIn.id).toBeGreaterThan(oldInvoiceIn.id);
|
||||
expect(newInvoiceInDueDay.id).toBeGreaterThan(oldInvoiceInDueDay.id);
|
||||
expect(newInvoiceInTax.id).toBeGreaterThan(oldInvoiceInTax.id);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
|
@ -0,0 +1,26 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
describe('AgencyTerm filter()', () => {
|
||||
const authUserId = 9;
|
||||
|
||||
it('should return all the tickets matching the filter', async() => {
|
||||
const tx = await models.AgencyTerm.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
const filter = {};
|
||||
const ctx = {req: {accessToken: {userId: authUserId}}};
|
||||
|
||||
const agencyTerms = await models.AgencyTerm.filter(ctx, filter, options);
|
||||
const firstAgencyTerm = agencyTerms[0];
|
||||
|
||||
expect(firstAgencyTerm.routeFk).toEqual(1);
|
||||
expect(agencyTerms.length).toEqual(3);
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
|
@ -1,4 +1,10 @@
|
|||
{
|
||||
"AgencyTerm": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"AgencyTermConfig": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"Route": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "AgencyTermConfig",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "agencyTermConfig"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"expenceFk": {
|
||||
"type": "string",
|
||||
"id": true
|
||||
},
|
||||
"vatAccountSupported": {
|
||||
"type": "string"
|
||||
},
|
||||
"vatPercentage": {
|
||||
"type": "number"
|
||||
},
|
||||
"transaction": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
module.exports = Self => {
|
||||
require('../methods/agency-term/filter')(Self);
|
||||
require('../methods/agency-term/createInvoiceIn')(Self);
|
||||
};
|
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"name": "AgencyTerm",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "agencyTerm"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"agencyFk": {
|
||||
"type": "number",
|
||||
"id": true,
|
||||
"description": "Identifier"
|
||||
},
|
||||
"minimumPackages": {
|
||||
"type": "number"
|
||||
},
|
||||
"kmPrice": {
|
||||
"type": "number"
|
||||
},
|
||||
"packagePrice": {
|
||||
"type": "number"
|
||||
},
|
||||
"routePrice": {
|
||||
"type": "number"
|
||||
},
|
||||
"minimumKm": {
|
||||
"type": "number"
|
||||
},
|
||||
"minimumM3": {
|
||||
"type": "number"
|
||||
},
|
||||
"m3Price": {
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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,120 @@
|
|||
import ngModule from '../../module';
|
||||
import Section from 'salix/components/section';
|
||||
import './style.scss';
|
||||
import UserError from 'core/lib/user-error';
|
||||
|
||||
class Controller extends Section {
|
||||
constructor($element, $) {
|
||||
super($element, $);
|
||||
this.dms = {
|
||||
files: [],
|
||||
hasFile: false,
|
||||
hasFileAttached: false
|
||||
};
|
||||
}
|
||||
|
||||
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() {
|
||||
if (this.dms.files.length > 1) throw new UserError('You cannot attach more than one document');
|
||||
const query = `dms/uploadFile`;
|
||||
const options = {
|
||||
method: 'POST',
|
||||
url: query,
|
||||
params: this.dms,
|
||||
headers: {
|
||||
'Content-Type': undefined
|
||||
},
|
||||
transformRequest: files => {
|
||||
const formData = new FormData();
|
||||
formData.append(files[0].name, files[0]);
|
||||
return formData;
|
||||
},
|
||||
data: this.dms.files
|
||||
};
|
||||
this.$http(options).then(res => {
|
||||
if (res) {
|
||||
const addedDms = res.data;
|
||||
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('Data saved!'));
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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,107 @@
|
|||
import './index';
|
||||
import watcher from 'core/mocks/watcher.js';
|
||||
|
||||
describe('AgencyTerm', () => {
|
||||
describe('Component vnAgencyTermCreateInvoiceIn', () => {
|
||||
let controller;
|
||||
let $scope;
|
||||
let $httpBackend;
|
||||
let $httpParamSerializer;
|
||||
|
||||
beforeEach(ngModule('route'));
|
||||
|
||||
beforeEach(inject(($componentController, $rootScope, _$httpBackend_, _$httpParamSerializer_) => {
|
||||
$scope = $rootScope.$new();
|
||||
$httpBackend = _$httpBackend_;
|
||||
$httpParamSerializer = _$httpParamSerializer_;
|
||||
const $element = angular.element('<vn-agency-term-create-invoice-in></vn-agency-term-create-invoice-in>');
|
||||
controller = $componentController('vnAgencyTermCreateInvoiceIn', {$element});
|
||||
controller._route = {
|
||||
id: 1
|
||||
};
|
||||
}));
|
||||
|
||||
describe('$onChanges()', () => {
|
||||
it('should update the params data when $params.q is defined', () => {
|
||||
controller.$params = {q: '{"supplierName": "Plants SL","rows": null}'};
|
||||
|
||||
const params = {q: '{"supplierName": "Plants SL", "rows": null}'};
|
||||
const json = JSON.parse(params.q);
|
||||
|
||||
controller.$onChanges();
|
||||
|
||||
expect(controller.params).toEqual(json);
|
||||
});
|
||||
});
|
||||
|
||||
describe('route() setter', () => {
|
||||
it('should set the ticket data and then call setDefaultParams() and getAllowedContentTypes()', () => {
|
||||
jest.spyOn(controller, 'setDefaultParams');
|
||||
jest.spyOn(controller, 'getAllowedContentTypes');
|
||||
controller.route = {
|
||||
id: 1
|
||||
};
|
||||
|
||||
expect(controller.route).toBeDefined();
|
||||
expect(controller.setDefaultParams).toHaveBeenCalledWith();
|
||||
expect(controller.getAllowedContentTypes).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
||||
describe('setDefaultParams()', () => {
|
||||
it('should perform a GET query and define the dms property on controller', () => {
|
||||
const params = {filter: {
|
||||
where: {code: 'invoiceIn'}
|
||||
}};
|
||||
const serializedParams = $httpParamSerializer(params);
|
||||
$httpBackend.expect('GET', `DmsTypes/findOne?${serializedParams}`).respond({id: 1, code: 'invoiceIn'});
|
||||
controller.params = {supplierName: 'Plants SL'};
|
||||
controller.setDefaultParams();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.dms).toBeDefined();
|
||||
expect(controller.dms.dmsTypeId).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onSubmit()', () => {
|
||||
it('should make an HTTP POST request to save the form data', () => {
|
||||
controller.$.watcher = watcher;
|
||||
|
||||
jest.spyOn(controller.$.watcher, 'updateOriginalData');
|
||||
const files = [{id: 1, name: 'MyFile'}];
|
||||
controller.dms = {files};
|
||||
const serializedParams = $httpParamSerializer(controller.dms);
|
||||
const query = `dms/uploadFile?${serializedParams}`;
|
||||
controller.params = {rows: null};
|
||||
|
||||
$httpBackend.expect('POST', query).respond({});
|
||||
$httpBackend.expect('POST', 'AgencyTerms/createInvoiceIn').respond({});
|
||||
controller.onSubmit();
|
||||
$httpBackend.flush();
|
||||
});
|
||||
});
|
||||
|
||||
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();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,7 @@
|
|||
vn-ticket-request {
|
||||
.vn-textfield {
|
||||
margin: 0!important;
|
||||
max-width: 100px;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="AgencyTerms/filter"
|
||||
filter="::$ctrl.filter"
|
||||
data="agencyTerms"
|
||||
auto-load="true">
|
||||
</vn-crud-model>
|
||||
<vn-card>
|
||||
<smart-table
|
||||
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>
|
||||
<tr>
|
||||
<th shrink>
|
||||
<vn-multi-check
|
||||
model="model">
|
||||
</vn-multi-check>
|
||||
</th>
|
||||
<th shrink field="routeFk">
|
||||
<span translate>Id</span>
|
||||
</th>
|
||||
<th field="created">
|
||||
<span translate>Date</span>
|
||||
</th>
|
||||
<th field="agencyFk">
|
||||
<span translate>Agency route</span>
|
||||
</th>
|
||||
<th field="agencyAgreement">
|
||||
<span translate>Agency Agreement</span>
|
||||
</th>
|
||||
<th field="packages">
|
||||
<span translate>Packages</span>
|
||||
</th>
|
||||
<th field="m3">
|
||||
<span translate>M3</span>
|
||||
</th>
|
||||
<th field="kmTotal">
|
||||
<span translate>Km</span>
|
||||
</th>
|
||||
<th field="price">
|
||||
<span translate>Price</span>
|
||||
</th>
|
||||
<th field="invoiceInFk">
|
||||
<span translate>Received</span>
|
||||
</th>
|
||||
<th field="supplierFk">
|
||||
<span translate>Autonomous</span>
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="agencyTerm in agencyTerms">
|
||||
<td shrink>
|
||||
<vn-check
|
||||
ng-model="agencyTerm.checked"
|
||||
vn-click-stop>
|
||||
</vn-check>
|
||||
</td>
|
||||
<td>
|
||||
<span
|
||||
title="{{::agencyTerm.id}}"
|
||||
vn-click-stop="routeDescriptor.show($event, agencyTerm.routeFk)"
|
||||
class="link">
|
||||
{{::agencyTerm.routeFk}}
|
||||
</span>
|
||||
</td>
|
||||
<td shrink-date>{{::agencyTerm.created | date:'dd/MM/yyyy'}}</td>
|
||||
<td>{{::agencyTerm.agencyModeName | dashIfEmpty}}</td>
|
||||
<td>{{::agencyTerm.agencyAgreement | dashIfEmpty}}</td>
|
||||
<td>{{::agencyTerm.packages | dashIfEmpty}}</td>
|
||||
<td>{{::agencyTerm.m3 | dashIfEmpty}}</td>
|
||||
<td>{{::agencyTerm.kmTotal | dashIfEmpty}}</td>
|
||||
<td>{{::agencyTerm.price | dashIfEmpty}}</td>
|
||||
<td>
|
||||
<span
|
||||
vn-click-stop="invoiceInDescriptor.show($event, agencyTerm.invoiceInFk)"
|
||||
class="link">
|
||||
{{::agencyTerm.invoiceInFk}}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span
|
||||
class="link"
|
||||
vn-click-stop="supplierDescriptor.show($event, agencyTerm.supplierFk)">
|
||||
{{::agencyTerm.supplierName}}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<vn-icon-button
|
||||
vn-click-stop="$ctrl.preview(agencyTerm.route)"
|
||||
vn-tooltip="Preview"
|
||||
icon="preview">
|
||||
</vn-icon-button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</slot-table>
|
||||
</smart-table>
|
||||
</vn-card>
|
||||
|
||||
<vn-popup vn-id="summary">
|
||||
<vn-route-summary
|
||||
route="$ctrl.routeSelected">
|
||||
</vn-route-summary>
|
||||
</vn-popup>
|
||||
|
||||
<vn-route-descriptor-popover
|
||||
vn-id="routeDescriptor">
|
||||
</vn-route-descriptor-popover>
|
||||
<vn-supplier-descriptor-popover
|
||||
vn-id="supplierDescriptor">
|
||||
</vn-supplier-descriptor-popover>
|
||||
<vn-invoice-in-descriptor-popover
|
||||
vn-id="invoiceInDescriptor">
|
||||
</vn-invoice-in-descriptor-popover>
|
||||
|
||||
<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,122 @@
|
|||
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) {
|
||||
vicent marked this conversation as resolved
carlosjr
commented
The following approach requires less code for same functionality
The following approach requires less code for same functionality
```
exprBuilder(param, value) {
switch (param) {
case 'agencyFk':
return {'a.agencyModeName': value};
case 'supplierFk':
return {'a.supplierName': value};
case 'routeFk':
case 'created':
case 'agencyAgreement':
case 'packages':
case 'm3':
case 'kmTotal':
case 'price':
case 'invoiceInFk':
return {[`a.${param}`]: value};
}
}
```
|
||||
switch (param) {
|
||||
case 'agencyFk':
|
||||
return {'a.agencyModeName': value};
|
||||
case 'supplierFk':
|
||||
return {'a.supplierName': value};
|
||||
case 'routeFk':
|
||||
return {'a.routeFk': value};
|
||||
case 'created':
|
||||
case 'agencyAgreement':
|
||||
case 'packages':
|
||||
case 'm3':
|
||||
case 'kmTotal':
|
||||
case 'price':
|
||||
case 'invoiceInFk':
|
||||
return {[`a.${param}`]: 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 supplierFk = this.checked[0].supplierFk;
|
||||
|
||||
for (let agencyTerm of this.checked) {
|
||||
let hasSameSupplier = supplierFk == agencyTerm.supplierFk;
|
||||
if (hasSameSupplier) {
|
||||
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
|
||||
});
|
|
@ -0,0 +1,94 @@
|
|||
import './index.js';
|
||||
import crudModel from 'core/mocks/crud-model';
|
||||
|
||||
describe('AgencyTerm', () => {
|
||||
describe('Component vnAgencyTermIndex', () => {
|
||||
let controller;
|
||||
let $window;
|
||||
|
||||
beforeEach(ngModule('route'));
|
||||
|
||||
beforeEach(inject(($componentController, _$window_) => {
|
||||
$window = _$window_;
|
||||
const $element = angular.element('<vn-agency-term-index></vn-agency-term-index>');
|
||||
controller = $componentController('vnAgencyTermIndex', {$element});
|
||||
controller.$.model = crudModel;
|
||||
controller.$.model.data = [
|
||||
{supplierFk: 1, totalPrice: null},
|
||||
{supplierFk: 1},
|
||||
{supplierFk: 2}
|
||||
];
|
||||
}));
|
||||
|
||||
describe('checked() getter', () => {
|
||||
it('should return the checked lines', () => {
|
||||
const data = controller.$.model.data;
|
||||
data[0].checked = true;
|
||||
|
||||
const checkedRows = controller.checked;
|
||||
|
||||
const firstCheckedRow = checkedRows[0];
|
||||
|
||||
expect(firstCheckedRow.supplierFk).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('totalCheked() getter', () => {
|
||||
it('should return the total checked lines', () => {
|
||||
const data = controller.$.model.data;
|
||||
data[0].checked = true;
|
||||
|
||||
const checkedRows = controller.totalChecked;
|
||||
|
||||
expect(checkedRows).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('preview()', () => {
|
||||
it('should show the summary dialog', () => {
|
||||
controller.$.summary = {show: () => {}};
|
||||
jest.spyOn(controller.$.summary, 'show');
|
||||
|
||||
let event = new MouseEvent('click', {
|
||||
view: $window,
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
});
|
||||
const route = {id: 1};
|
||||
|
||||
controller.preview(event, route);
|
||||
|
||||
expect(controller.$.summary.show).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
|
||||
describe('createInvoiceIn()', () => {
|
||||
it('should throw an error if more than one autonomous are checked', () => {
|
||||
jest.spyOn(controller.vnApp, 'showError');
|
||||
const data = controller.$.model.data;
|
||||
data[0].checked = true;
|
||||
data[2].checked = true;
|
||||
|
||||
controller.createInvoiceIn();
|
||||
|
||||
expect(controller.vnApp.showError).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call the function go() on $state to go to the file management', () => {
|
||||
jest.spyOn(controller.$state, 'go');
|
||||
const data = controller.$.model.data;
|
||||
data[0].checked = true;
|
||||
|
||||
controller.createInvoiceIn();
|
||||
|
||||
delete data[0].checked;
|
||||
const params = JSON.stringify({
|
||||
supplierName: data[0].supplierName,
|
||||
rows: [data[0]]
|
||||
});
|
||||
|
||||
expect(controller.$state.go).toHaveBeenCalledWith('route.agencyTerm.createInvoiceIn', {q: params});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,32 @@
|
|||
@import "variables";
|
||||
|
||||
vn-item-product {
|
||||
display: block;
|
||||
|
||||
.id {
|
||||
background-color: $color-main;
|
||||
color: $color-font-dark;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.image {
|
||||
height: 112px;
|
||||
width: 112px;
|
||||
|
||||
& > img {
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
border-radius: 3px;
|
||||
}
|
||||
}
|
||||
vn-label-value:first-of-type section{
|
||||
margin-top: 9px;
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
img {
|
||||
border-radius: 50%;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
Agency route: Agencia ruta
|
||||
vicent marked this conversation as resolved
carlosjr
commented
the word picture should be capitalised. Also some of the translations don't seem to be used at all. please double check their use on your templates. the word picture should be capitalised.
Also some of the translations don't seem to be used at all. please double check their use on your templates.
|
||||
Agency Agreement: Acuerdo agencia
|
||||
Autonomous: Autónomos
|
||||
Two autonomous cannot be counted at the same time: Dos autonónomos no pueden ser contabilizados al mismo tiempo
|
||||
You cannot attach more than one document: No puedes adjuntar más de un documento
|
|
@ -11,4 +11,6 @@ import './create';
|
|||
import './basic-data';
|
||||
import './log';
|
||||
import './tickets';
|
||||
import './agency-term/index';
|
||||
import './agency-term/createInvoiceIn';
|
||||
import './ticket-popup';
|
||||
|
|
|
@ -3,10 +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.index", "icon": "icon-delivery"},
|
||||
{"state": "route.agencyTerm.index", "icon": "contact_support"}
|
||||
],
|
||||
"card": [
|
||||
{"state": "route.card.basicData", "icon": "settings"},
|
||||
|
@ -37,6 +38,26 @@
|
|||
"state": "route.card",
|
||||
"abstract": true,
|
||||
"component": "vn-route-card"
|
||||
}, {
|
||||
"url": "/agency-term",
|
||||
"abstract": true,
|
||||
"state": "route.agencyTerm",
|
||||
"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": "File management",
|
||||
"params": {
|
||||
"route": "$ctrl.route"
|
||||
},
|
||||
"acl": ["administrative"]
|
||||
}, {
|
||||
"url": "/summary",
|
||||
"state": "route.card.summary",
|
||||
|
|
Loading…
Reference in New Issue
Maybe you want the endpoint to return the created invoiceIn.