Merge branch 'dev' of https://git.verdnatura.es/salix into dev

This commit is contained in:
Joan Sanchez 2017-11-29 21:02:15 +01:00
commit ac84b37f32
35 changed files with 471 additions and 38 deletions

2
Jenkinsfile vendored
View File

@ -43,11 +43,13 @@ node
stage ("Stopping/Removing Docker")
{
env.TAG = "${env.BUILD_NUMBER}" - 1;
sh "docker-compose down --rmi 'all'"
}
stage ("Generar dockers")
{
env.TAG = "${env.BUILD_NUMBER}" + 1;
sh "docker-compose up -d --build"
}
}

View File

@ -26,7 +26,7 @@
"client": "$ctrl.client"
},
"menu": {
"description": "Datos básicos",
"description": "Basic data",
"icon": "person"
}
}, {
@ -37,7 +37,7 @@
"client": "$ctrl.client"
},
"menu": {
"description": "Datos fiscales",
"description": "Fiscal data",
"icon": "account_balance"
}
}, {
@ -64,7 +64,7 @@
"client": "$ctrl.client"
},
"menu": {
"description": "Consignatarios",
"description": "Addresses",
"icon": "local_shipping"
}
}, {
@ -83,7 +83,7 @@
"client": "$ctrl.client"
},
"menu": {
"description": "Acceso web",
"description": "Web access",
"icon": "language"
}
}, {
@ -99,13 +99,59 @@
"client": "$ctrl.client"
},
"menu": {
"description": "Notas",
"description": "Notes",
"icon": "insert_drive_file"
}
}, {
"url": "/create",
"state": "clientCard.notes.create",
"component": "vn-note-create"
}, {
"url": "/credit",
"abstract": true,
"state": "clientCard.credit",
"component": "ui-view"
}, {
"url": "/list",
"state": "clientCard.credit.list",
"component": "vn-client-credit-list",
"params": {
"client": "$ctrl.client"
},
"menu": {
"description": "Credit",
"icon": "credit_card"
}
}, {
"url": "/create",
"state": "clientCard.credit.create",
"component": "vn-client-credit-create",
"params": {
"client": "$ctrl.client"
}
}, {
"url": "/greuge",
"abstract": true,
"state": "clientCard.greuge",
"component": "ui-view"
}, {
"url": "/list",
"state": "clientCard.greuge.list",
"component": "vn-client-greuge-list",
"params": {
"client": "$ctrl.client"
},
"menu": {
"description": "Greuge",
"icon": "work"
}
}, {
"url": "/create",
"state": "clientCard.greuge.create",
"component": "vn-client-greuge-create",
"params": {
"client": "$ctrl.client"
}
}
]
}

View File

@ -1,4 +1,3 @@
{
"Addresses": "Consignatarios",
"Set as default": "Establecer como predeterminado"
}

View File

@ -1,5 +1,4 @@
{
"Basic data": "Datos básicos",
"Comercial Name": "Nombre comercial",
"Tax number": "NIF/CIF",
"Social name": "Razón social",

View File

@ -14,3 +14,7 @@ import './address-edit/address-edit';
import './notes/notes';
import './note-create/note-create';
import './web-access/web-access';
import './credit-list/credit-list';
import './credit-create/credit-create';
import './greuge-list/greuge-list';
import './greuge-create/greuge-create';

View File

@ -0,0 +1,23 @@
<mg-ajax path="/client/api/Clients/{{patch.params.id}}" options="vnPatch"></mg-ajax>
<vn-watcher
vn-id="watcher"
data="$ctrl.client"
form="form"
save="patch">
</vn-watcher>
<form name="form" ng-submit="watcher.submitGo('clientCard.credit.list')" pad-medium>
<vn-card >
<vn-vertical pad-large>
<vn-title>Add credit</vn-title>
<vn-horizontal>
<vn-textfield vn-one label="Credit" field="$ctrl.client.credit" type="number" vn-focus></vn-textfield>
<vn-one></vn-one>
</vn-horizontal>
</vn-vertical>
</vn-card>
<vn-button-bar>
<vn-submit label="Save"></vn-submit>
</vn-button-bar>
</form>

View File

@ -0,0 +1,8 @@
import ngModule from '../module';
ngModule.component('vnClientCreditCreate', {
template: require('./credit-create.html'),
bindings: {
client: '<'
}
});

View File

@ -0,0 +1,3 @@
{
"Add credit": "Añadir crédito"
}

View File

@ -0,0 +1,29 @@
<mg-ajax path="/client/api/clientCredits/filter" options="vnIndexNonAuto"></mg-ajax>
<vn-card pad-medium>
<vn-vertical pad-large>
<vn-title vn-one margin-large-bottom>Credit</vn-title>
<vn-grid-header on-order="$ctrl.onOrder(field, order)">
<vn-column-header vn-one pad-medium-h field="amount" text="Credit"></vn-column-header>
<vn-column-header vn-two pad-medium-h field="created" text="Since" default-order="ASC"></vn-column-header>
<vn-column-header vn-two pad-medium-h field="employee.name" text="Employee" order-locked></vn-column-header>
</vn-grid-header>
<vn-one class="list list-content">
<vn-horizontal
vn-one class="list list-element text-center"
pad-small-bottom
ng-repeat="credit in index.model.instances track by credit.id"
>
<vn-one pad-medium-h>{{::credit.amount | number:2}} €</vn-one>
<vn-two pad-medium-h>{{::credit.created | date:'dd/MM/yyyy HH:mm' }}</vn-two>
<vn-two pad-medium-h>{{::credit.employee.name}}</vn-two>
</vn-horizontal>
</vn-one>
<vn-one class="text-center" ng-if="index.model.count === 0" translate>No results</vn-one>
<vn-horizontal vn-one class="list list-footer"></vn-horizontal>
<vn-paging vn-one margin-large-top index="index" total="index.model.count"></vn-paging>
</vn-vertical>
</vn-card>
<a ui-sref="clientCard.credit.create" fixed-bottom-right>
<vn-float-button icon="add"></vn-float-button>
</a>

View File

@ -0,0 +1,45 @@
import ngModule from '../module';
class ClientCreditList {
constructor($scope, $timeout) {
this.$ = $scope;
this.$timeout = $timeout;
this.waitingMgCrud = 0;
}
onOrder(field, order) {
this.filter(`${field} ${order}`);
}
filter(order) {
if (this.$.index && this.client && this.client.id) {
this.waitingMgCrud = 0;
this.$.index.filter = {
page: 1,
size: 10,
clientFk: this.client.id
};
if (order) {
this.$.index.filter.order = order;
}
this.$.index.accept();
} else if (this.waitingMgCrud > 0) {
throw new Error('Magic Crud is not loaded');
} else {
this.waitingMgCrud++;
this.$timeout(() => {
this.filter(order);
}, 250);
}
}
}
ClientCreditList.$inject = ['$scope', '$timeout'];
ngModule.component('vnClientCreditList', {
template: require('./credit-list.html'),
controller: ClientCreditList,
bindings: {
client: '<'
}
});

View File

@ -0,0 +1,5 @@
{
"Since" : "Desde",
"Employee" : "Empleado",
"No results": "Sin resultados"
}

View File

@ -0,0 +1,17 @@
<vn-card pad-medium>
<vn-vertical pad-medium>
<vn-title vn-one margin-large-bottom>Add Greuge</vn-title>
<vn-horizontal>
<vn-textfield vn-one margin-small-right label="Importe" field="$ctrl.greuge.amount" type="number" vn-focus></vn-textfield>
<vn-date-picker vn-one label="Date" model="$ctrl.greuge.date"></vn-date-picker>
</vn-horizontal>
<vn-horizontal>
<vn-textfield vn-one margin-small-right label="Comment" field="$ctrl.greuge.description"></vn-textfield>
<vn-autocomplete vn-one
field="$ctrl.greuge.greugeTypeFk"
url="/client/api/greugeTypes"
label="Type">
</vn-autocomplete>
</vn-horizontal>
</vn-vertical>
</vn-card>

View File

@ -0,0 +1,8 @@
import ngModule from '../module';
ngModule.component('vnClientGreugeCreate', {
template: require('./greuge-create.html'),
bindings: {
client: '<'
}
});

View File

@ -0,0 +1,38 @@
<mg-ajax path="/client/api/greuges/filter" options="vnIndexNonAuto"></mg-ajax>
<mg-ajax path="/client/api/greuges/{{edit.params.id}}/sumAmount" options="mgEdit"></mg-ajax>
<vn-card pad-medium>
<vn-vertical pad-medium>
<vn-title vn-one margin-large-bottom>Greuge</vn-title>
<vn-grid-header on-order="$ctrl.onOrder(field, order)">
<vn-column-header vn-one pad-medium-h field="shipped" text="Date" default-order="ASC"></vn-column-header>
<vn-column-header vn-two pad-medium-h field="description" text="Comment"></vn-column-header>
<vn-column-header vn-one pad-medium-h field="amount" text="Amount"></vn-column-header>
<vn-column-header vn-one pad-medium-h field="greugeTypeFk" text="Type"></vn-column-header>
</vn-grid-header>
<vn-one class="list list-content">
<vn-horizontal
class="list list-element text-center"
pad-small-bottom
ng-repeat="greuge in index.model.instances track by greuge.id"
>
<vn-one pad-medium-h>{{::greuge.shipped | date:'dd/MM/yyyy HH:mm' }}</vn-one>
<vn-two pad-medium-h>{{::greuge.description}}</vn-two>
<vn-one pad-medium-h>{{::greuge.amount | number:2}} €</vn-one>
<vn-one pad-medium-h>{{::greuge.greugeType.name}}</vn-one>
</vn-horizontal>
</vn-one>
<vn-one class="text-center" ng-if="index.model.count === 0" translate>No results</vn-one>
<vn-horizontal vn-one class="list list-footer text-center">
<vn-one pad-medium-h></vn-one>
<vn-two pad-medium-h></vn-two>
<vn-one pad-medium-h ng-if="index.model.count > 0">{{edit.model.sumAmount | number:2}} €</vn-one>
<vn-one pad-medium-h></vn-one>
</vn-horizontal>
<vn-paging margin-large-top vn-one index="index" total="index.model.count"></vn-paging>
</vn-vertical>
</vn-card>
<a ui-sref="clientCard.greuge.create" fixed-bottom-right>
<vn-float-button icon="add"></vn-float-button>
</a>

View File

@ -0,0 +1,45 @@
import ngModule from '../module';
class ClientGreugeList {
constructor($scope, $timeout) {
this.$ = $scope;
this.$timeout = $timeout;
this.waitingMgCrud = 0;
}
onOrder(field, order) {
this.filter(`${field} ${order}`);
}
filter(order) {
if (this.$.index && this.client && this.client.id) {
this.waitingMgCrud = 0;
this.$.index.filter = {
page: 1,
size: 10,
clientFk: this.client.id
};
if (order) {
this.$.index.filter.order = order;
}
this.$.index.accept();
} else if (this.waitingMgCrud > 3) {
throw new Error('Magic Crud is not loaded');
} else {
this.waitingMgCrud++;
this.$timeout(() => {
this.filter(order);
}, 250);
}
}
}
ClientGreugeList.$inject = ['$scope', '$timeout'];
ngModule.component('vnClientGreugeList', {
template: require('./greuge-list.html'),
controller: ClientGreugeList,
bindings: {
client: '<'
}
});

View File

@ -0,0 +1,7 @@
{
"Date" : "Fecha",
"Comment" : "Comentario",
"Amount" : "Importe",
"Type": "Tipo",
"Add Greuge": "Añadir Greuge"
}

View File

@ -2,7 +2,11 @@
"Active": "Activo",
"Client": "Cliente",
"Clients": "Clientes",
"Basic data": "Datos básicos",
"Fiscal data": "Datos Fiscales",
"Addresses": "Consignatarios",
"Web access": "Acceso web",
"Notes": "Notas",
"Has to invoice": "Factura",
"Invoice by mail": "Factura impresa",
"Country": "País",
@ -12,5 +16,6 @@
"Province": "Provincia",
"Save": "Guardar",
"Pay method" : "Forma de pago",
"Address": "Consignatario"
"Address": "Consignatario",
"Credit" : "Crédito"
}

View File

@ -1,3 +0,0 @@
{
"Notes": "Notas"
}

View File

@ -1,7 +1,6 @@
{
"User": "Usuario",
"Enable web access": "Habilitar acceso web",
"Web access": "Acceso web",
"New password": "Nueva contraseña",
"Repeat password": "Repetir contraseña",
"Change password": "Cambiar contraseña"

View File

@ -1,5 +1,5 @@
<div class="{{$ctrl.className}}" ng-mouseover="$ctrl.mouseIsOver = true" ng-mouseleave="$ctrl.mouseIsOver = false">
<vn-horizontal ng-if="$ctrl.text" class="orderly" ng-click="$ctrl.onClick()">
<vn-horizontal ng-if="$ctrl.text" class="orderly" ng-class="{'pointer' : !$ctrl.orderLocked}" ng-click="$ctrl.onClick()">
<vn-none class="title" translate>
{{::$ctrl.text}}
</vn-none>

View File

@ -1,11 +1,13 @@
import {module} from '../module';
export default class ColumnHeader {
constructor() {
constructor($attrs) {
this.order = undefined;
this.mouseIsOver = false;
this.orderLocked = ($attrs.orderLocked !== undefined);
}
onClick() {
if (!this.orderLocked) {
if (this.order === 'ASC') {
this.order = 'DESC';
} else {
@ -13,7 +15,11 @@ export default class ColumnHeader {
}
this.gridHeader.selectColum(this);
}
}
showArrow(type) {
if (this.orderLocked)
return false;
let showArrow = (this.gridHeader && this.gridHeader.currentColumn && this.gridHeader.currentColumn.field === this.field && this.order === type);
let showOther = (this.gridHeader && this.gridHeader.currentColumn && this.gridHeader.currentColumn.field === this.field && this.order !== type);
if (type === 'DESC' && this.mouseIsOver && !showOther) {
@ -22,13 +28,13 @@ export default class ColumnHeader {
return showArrow;
}
$onInit() {
if (this.defaultOrder) {
if (this.defaultOrder && !this.orderLocked) {
this.order = this.defaultOrder;
this.onClick();
}
}
}
ColumnHeader.$inject = [];
ColumnHeader.$inject = ['$attrs'];
module.component('vnColumnHeader', {
template: require('./column-header.html'),

View File

@ -2,7 +2,6 @@ vn-grid-header {
border-bottom: 3px solid #9D9D9D;
font-weight: bold;
.orderly{
cursor: pointer;
text-align: center;
white-space: nowrap;
justify-content: center;

View File

@ -13,6 +13,8 @@ export class ProductionTable {
},
model: []
};
this.filteredField = null;
this.filteredReverse = null;
}
get checkAll() {
return this._checkAll;
@ -21,7 +23,7 @@ export class ProductionTable {
this._checkAll = value;
}
set tickets(value) {
this._tickets = value;
this._tickets = this.filteredField ? this.$filter('orderBy')(value, this.filteredField, this.filteredReverse) : value;
this.totalFilter = this._tickets.length;
this.pageTable.filter.page = 1;
this.pageTickets();
@ -30,8 +32,9 @@ export class ProductionTable {
return this._tickets;
}
onOrder(field, order) {
let reverse = order === 'DESC';
this.tickets = this.$filter('orderBy')(this.tickets, field, reverse);
this.filteredField = field;
this.filteredReverse = order === 'DESC';
this.tickets = this.tickets; // call tickets setter
}
pageTickets() {
let init = (this.pageTable.filter.page - 1) * this.itemsDisplayedInList;

View File

@ -9,7 +9,7 @@ export default class MenuActions {
switchItem() {
if (!this.items || !this.items.length) return;
let stateName = this.$state.current.name.replace('create', 'list').replace('edit', 'list');
let stateName = this.$state.current.name.replace('.create', '.list').replace('.edit', '.list');
for (let i = 0; i < this.items.length; i++) {
this.items[i].active = (this.items[i].href === stateName);

View File

@ -116,12 +116,7 @@ module.exports = function(Client) {
}
function maxCb(_, instances) {
if (!instances) {
done(generateErrorCredit());
return;
}
if (instances.length !== 1 || instances[0].employeeFk == userId || instances[0].amount > 0) {
if (!instances || instances.length !== 1 || instances[0].employeeFk == userId || instances[0].amount > 0) {
done();
return;
}

View File

@ -0,0 +1,20 @@
module.exports = Self => {
Self.installMethod('filter', filterParams);
function filterParams(params) {
return {
where: {
clientFk: params.clientFk
},
skip: (params.page - 1) * params.size,
limit: params.size,
order: params.order || 'shipped DESC',
include: {
relation: "greugeType",
scope: {
fields: ["id", "name"]
}
}
};
}
};

View File

@ -0,0 +1,34 @@
module.exports = Self => {
Self.remoteMethod('sumAmount', {
description: 'returns sum greuge.ammount from client',
accessType: 'READ',
accepts: [{
arg: 'id',
type: 'number',
required: true,
description: 'clientFk',
http: {source: 'path'}
}],
returns: {
arg: 'sumAmount'
},
http: {
path: `/:id/sumAmount`,
verb: 'get'
}
});
Self.sumAmount = (clientFk, callback) => {
let query = `SELECT sum(amount) as sumAmount FROM vn.greuge WHERE clientFk = ?`;
Self.rawSql(query, [clientFk], callback).then(response => {
if (response.length) {
callback(null, response[0].sumAmount);
} else {
callback(null, 0);
}
})
.catch(reject => {
callback(reject, null);
});
};
};

View File

@ -0,0 +1,31 @@
module.exports = function(Self) {
Self.installMethod('filter', filterParams, filterResults);
function filterParams(params) {
return {
where: {
clientFk: params.clientFk
},
skip: (params.page - 1) * params.size,
limit: params.size,
order: params.order || 'created DESC',
include: {
relation: "employee",
scope: {
fields: ["id", "name", "surname"]
}
}
};
}
function filterResults(instances) {
let result = JSON.parse(JSON.stringify(instances));
if (result && result.instances && result.instances.length) {
result.instances.forEach((element, i) => {
result.instances[i].employee.name = `${element.employee.name} ${element.employee.surname}`;
delete result.instances[i].employee.surname;
});
}
return result;
}
};

View File

@ -1,5 +1,5 @@
{
"name": "ClientCredit",
"name": "clientCredit",
"base": "VnModel",
"validateUpsert": true,
"properties": {

View File

@ -0,0 +1,14 @@
{
"name": "greugeType",
"base": "VnModel",
"properties": {
"id": {
"id": true,
"type": "Number",
"description": "Identifier"
},
"name": {
"type": "String"
}
}
}

View File

@ -0,0 +1,4 @@
module.exports = function(Self) {
require('../methods/greuge/filter.js')(Self);
require('../methods/greuge/totalGreuge.js')(Self);
};

View File

@ -0,0 +1,35 @@
{
"name": "greuge",
"base": "VnModel",
"properties": {
"id": {
"id": true,
"type": "Number",
"description": "Identifier"
},
"description": {
"type": "String"
},
"amount": {
"type": "Number"
},
"shipped": {
"type": "date"
},
"created": {
"type": "date"
}
},
"relations": {
"client": {
"type": "belongsTo",
"model": "Client",
"foreignKey": "clientFk"
},
"greugeType": {
"type": "belongsTo",
"model": "greugeType",
"foreignKey": "greugeTypeFk"
}
}
}

View File

@ -1,4 +1,7 @@
module.exports = fi => {
if (fi === undefined || fi === null) {
return true;
}
let dni = fi;
let getLetterDni = dni => {
const regExpDni = 'TRWAGMYFPDXBNJZSQVHLCKE';

View File

@ -27,8 +27,8 @@
"Client": {
"dataSource": "vn"
},
"ClientCredit": {
"dataSource": "salix"
"clientCredit": {
"dataSource": "vn"
},
"ClientCreditLimit": {
"dataSource": "salix"
@ -59,5 +59,11 @@
},
"CreditClassification": {
"dataSource": "salix"
},
"greuge": {
"dataSource": "vn"
},
"greugeType": {
"dataSource": "vn"
}
}

View File

@ -130,7 +130,7 @@ module.exports = function(Self) {
};
};
Self.installMethod = function(methodName, filterCb) {
Self.installMethod = function(methodName, filterCb, filterResult) {
this.remoteMethod(methodName, {
description: 'List items using a filter',
accessType: 'READ',
@ -161,9 +161,13 @@ module.exports = function(Self) {
var response = {};
function returnValues() {
if (response.instances !== undefined && response.count !== undefined)
if (response.instances !== undefined && response.count !== undefined) {
if (filterResult)
cb(null, filterResult(response));
else
cb(null, response);
}
}
function error() {
cb(null, response);