diff --git a/client/client/routes.json b/client/client/routes.json index c938dd8a6..99c083ff3 100644 --- a/client/client/routes.json +++ b/client/client/routes.json @@ -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" + } } ] } diff --git a/client/client/src/addresses/locale/es.json b/client/client/src/addresses/locale/es.json index dc7a13c4a..ab0c0e4ca 100644 --- a/client/client/src/addresses/locale/es.json +++ b/client/client/src/addresses/locale/es.json @@ -1,4 +1,3 @@ { - "Addresses": "Consignatarios", "Set as default": "Establecer como predeterminado" } \ No newline at end of file diff --git a/client/client/src/basic-data/locale/es.json b/client/client/src/basic-data/locale/es.json index d0e654979..4594d683e 100644 --- a/client/client/src/basic-data/locale/es.json +++ b/client/client/src/basic-data/locale/es.json @@ -1,5 +1,4 @@ { - "Basic data": "Datos básicos", "Comercial Name": "Nombre comercial", "Tax number": "NIF/CIF", "Social name": "Razón social", diff --git a/client/client/src/billing-data/billing-data.html b/client/client/src/billing-data/billing-data.html index 19b961558..c46c00e98 100644 --- a/client/client/src/billing-data/billing-data.html +++ b/client/client/src/billing-data/billing-data.html @@ -21,10 +21,6 @@ - - - - diff --git a/client/client/src/billing-data/billing-data.js b/client/client/src/billing-data/billing-data.js index 51a411013..6bbb3705c 100644 --- a/client/client/src/billing-data/billing-data.js +++ b/client/client/src/billing-data/billing-data.js @@ -17,9 +17,6 @@ export default class Controller { this.billData.payMethodFk = this.client.payMethodFk; this.billData.iban = this.client.iban; this.billData.dueDay = this.client.dueDay; - this.billData.discount = this.client.discount; - this.billData.credit = this.client.credit; - this.billData.creditInsurance = this.client.creditInsurance; } } submit() { diff --git a/client/client/src/billing-data/billing-data.spec.js b/client/client/src/billing-data/billing-data.spec.js index df169b18c..85980aa80 100644 --- a/client/client/src/billing-data/billing-data.spec.js +++ b/client/client/src/billing-data/billing-data.spec.js @@ -25,9 +25,6 @@ describe('Client', () => { describe('copyData()', () => { it(`should define billData using client's data`, () => { controller.client = { - credit: 1000000000000, - creditInsurance: null, - discount: 99, dueDay: 0, iban: null, payMethodFk: 1 @@ -72,8 +69,8 @@ describe('Client', () => { describe('returnDialog()', () => { it('should request to send notification email', () => { controller.client = {id: '123'}; - $httpBackend.when('POST', `/mailer/manuscript/payment-update/${controller.client.id}`).respond('done'); - $httpBackend.expectPOST(`/mailer/manuscript/payment-update/${controller.client.id}`); + $httpBackend.when('POST', `/mailer/notification/payment-update/${controller.client.id}`).respond('done'); + $httpBackend.expectPOST(`/mailer/notification/payment-update/${controller.client.id}`); controller.returnDialog('ACCEPT'); $httpBackend.flush(); }); diff --git a/client/client/src/card/card.js b/client/client/src/card/card.js index b21c3f636..9660ce3ce 100644 --- a/client/client/src/card/card.js +++ b/client/client/src/card/card.js @@ -1,5 +1,4 @@ import ngModule from '../module'; -import './style.css'; export default class Controller { constructor() { diff --git a/client/client/src/card/style.css b/client/client/src/card/style.css deleted file mode 100644 index 30d68e782..000000000 --- a/client/client/src/card/style.css +++ /dev/null @@ -1,3 +0,0 @@ -vn-descriptor { - font-family: vn-font-bold; -} \ No newline at end of file diff --git a/client/client/src/client.js b/client/client/src/client.js index 6dc0de725..15bd2d8ec 100644 --- a/client/client/src/client.js +++ b/client/client/src/client.js @@ -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'; diff --git a/client/client/src/credit-create/credit-create.html b/client/client/src/credit-create/credit-create.html new file mode 100644 index 000000000..c02ff7167 --- /dev/null +++ b/client/client/src/credit-create/credit-create.html @@ -0,0 +1,23 @@ + + + +
+ + + Add credit + + + + + + + + + + + +
diff --git a/client/client/src/credit-create/credit-create.js b/client/client/src/credit-create/credit-create.js new file mode 100644 index 000000000..2d0bccf56 --- /dev/null +++ b/client/client/src/credit-create/credit-create.js @@ -0,0 +1,8 @@ +import ngModule from '../module'; + +ngModule.component('vnClientCreditCreate', { + template: require('./credit-create.html'), + bindings: { + client: '<' + } +}); diff --git a/client/client/src/credit-create/locale/es.json b/client/client/src/credit-create/locale/es.json new file mode 100644 index 000000000..7b0a22a1f --- /dev/null +++ b/client/client/src/credit-create/locale/es.json @@ -0,0 +1,3 @@ +{ + "Add credit": "Añadir crédito" +} \ No newline at end of file diff --git a/client/client/src/credit-list/credit-list.html b/client/client/src/credit-list/credit-list.html new file mode 100644 index 000000000..30a477cef --- /dev/null +++ b/client/client/src/credit-list/credit-list.html @@ -0,0 +1,29 @@ + + + + Credit + + + + + + + + + {{::credit.amount | number:2}} € + {{::credit.created | date:'dd/MM/yyyy HH:mm' }} + {{::credit.employee.name}} + + + No results + + + + + + + \ No newline at end of file diff --git a/client/client/src/credit-list/credit-list.js b/client/client/src/credit-list/credit-list.js new file mode 100644 index 000000000..c1d283e33 --- /dev/null +++ b/client/client/src/credit-list/credit-list.js @@ -0,0 +1,9 @@ +import ngModule from '../module'; +import FilterClientList from '../filterClientList'; + +class ClientCreditList extends FilterClientList {} + +ngModule.component('vnClientCreditList', { + template: require('./credit-list.html'), + controller: ClientCreditList +}); diff --git a/client/client/src/credit-list/locale/es.json b/client/client/src/credit-list/locale/es.json new file mode 100644 index 000000000..2c99e8b73 --- /dev/null +++ b/client/client/src/credit-list/locale/es.json @@ -0,0 +1,5 @@ +{ + "Since" : "Desde", + "Employee" : "Empleado", + "No results": "Sin resultados" +} \ No newline at end of file diff --git a/client/client/src/descriptor/descriptor.html b/client/client/src/descriptor/descriptor.html index 3157cf570..87a7a5492 100644 --- a/client/client/src/descriptor/descriptor.html +++ b/client/client/src/descriptor/descriptor.html @@ -1,14 +1,31 @@ - - + + - person + person +
{{::$ctrl.client.id}}
{{$ctrl.client.name}}
{{$ctrl.client.phone}}
-
+
+ + + Credit: + + + {{$ctrl.client.credit || 0}} € + + + + + Secured credit: + + + {{$ctrl.client.creditInsurance || 0}} € + +
diff --git a/client/client/src/filterClientList.js b/client/client/src/filterClientList.js new file mode 100644 index 000000000..3ad70cfc5 --- /dev/null +++ b/client/client/src/filterClientList.js @@ -0,0 +1,37 @@ +export default class FilterClientList { + constructor($scope, $timeout, $state) { + this.$ = $scope; + this.$timeout = $timeout; + this.$state = $state; + + this.waitingMgCrud = 0; + this.clientFk = $state.params.id; + } + onOrder(field, order) { + this.filter(`${field} ${order}`); + } + filter(order) { + if (this.$.index && this.clientFk) { + this.waitingMgCrud = 0; + this.$.index.filter = { + page: 1, + size: 10, + clientFk: this.clientFk + }; + + 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); + } + } +} +FilterClientList.$inject = ['$scope', '$timeout', '$state']; diff --git a/client/client/src/greuge-create/greuge-create.html b/client/client/src/greuge-create/greuge-create.html new file mode 100644 index 000000000..9bc8830dd --- /dev/null +++ b/client/client/src/greuge-create/greuge-create.html @@ -0,0 +1,30 @@ + + + +
+ + + Add Greuge + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/client/client/src/greuge-create/greuge-create.js b/client/client/src/greuge-create/greuge-create.js new file mode 100644 index 000000000..f48c3e61b --- /dev/null +++ b/client/client/src/greuge-create/greuge-create.js @@ -0,0 +1,23 @@ +import ngModule from '../module'; + +class ClientGreugeCreate { + constructor($scope, $state) { + this.$ = $scope; + this.$state = $state; + this.greuge = {}; + } + onSubmit() { + this.greuge.clientFk = this.$state.params.id; + this.$.watcher.submit().then( + () => { + this.$state.go('clientCard.greuge.list'); + } + ); + } +} +ClientGreugeCreate.$inject = ['$scope', '$state']; + +ngModule.component('vnClientGreugeCreate', { + template: require('./greuge-create.html'), + controller: ClientGreugeCreate +}); diff --git a/client/client/src/greuge-list/greuge-list.html b/client/client/src/greuge-list/greuge-list.html new file mode 100644 index 000000000..08c774890 --- /dev/null +++ b/client/client/src/greuge-list/greuge-list.html @@ -0,0 +1,38 @@ + + + + + Greuge + + + + + + + + + + {{::greuge.shipped | date:'dd/MM/yyyy HH:mm' }} + {{::greuge.description}} + {{::greuge.amount | number:2}} € + {{::greuge.greugeType.name}} + + + + No results + + + + {{edit.model.sumAmount | number:2}} € + + + + + + + + \ No newline at end of file diff --git a/client/client/src/greuge-list/greuge-list.js b/client/client/src/greuge-list/greuge-list.js new file mode 100644 index 000000000..a2e5bd33a --- /dev/null +++ b/client/client/src/greuge-list/greuge-list.js @@ -0,0 +1,9 @@ +import ngModule from '../module'; +import FilterClientList from '../filterClientList'; + +class ClientGreugeList extends FilterClientList {} + +ngModule.component('vnClientGreugeList', { + template: require('./greuge-list.html'), + controller: ClientGreugeList +}); diff --git a/client/client/src/greuge-list/locale/es.json b/client/client/src/greuge-list/locale/es.json new file mode 100644 index 000000000..7aa276bd0 --- /dev/null +++ b/client/client/src/greuge-list/locale/es.json @@ -0,0 +1,7 @@ +{ + "Date" : "Fecha", + "Comment" : "Comentario", + "Amount" : "Importe", + "Type": "Tipo", + "Add Greuge": "Añadir Greuge" +} \ No newline at end of file diff --git a/client/client/src/locale/es.json b/client/client/src/locale/es.json index ae0e1a52a..0c4cd2362 100644 --- a/client/client/src/locale/es.json +++ b/client/client/src/locale/es.json @@ -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,7 @@ "Province": "Provincia", "Save": "Guardar", "Pay method" : "Forma de pago", - "Address": "Consignatario" + "Address": "Consignatario", + "Credit" : "Crédito", + "Secured credit": "Crédito asegurado" } diff --git a/client/client/src/notes/locale/es.json b/client/client/src/notes/locale/es.json deleted file mode 100644 index 28b37f5a8..000000000 --- a/client/client/src/notes/locale/es.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "Notes": "Notas" -} \ No newline at end of file diff --git a/client/client/src/web-access/locale/es.json b/client/client/src/web-access/locale/es.json index 82652f89f..dd42d1c3a 100644 --- a/client/client/src/web-access/locale/es.json +++ b/client/client/src/web-access/locale/es.json @@ -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" diff --git a/client/core/src/column-header/column-header.html b/client/core/src/column-header/column-header.html index 435057a19..d5747fcfe 100644 --- a/client/core/src/column-header/column-header.html +++ b/client/core/src/column-header/column-header.html @@ -1,5 +1,5 @@
- + {{::$ctrl.text}} diff --git a/client/core/src/column-header/column-header.js b/client/core/src/column-header/column-header.js index 2f5f4d3c3..4c52e7e3d 100644 --- a/client/core/src/column-header/column-header.js +++ b/client/core/src/column-header/column-header.js @@ -1,19 +1,25 @@ 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.order === 'ASC') { - this.order = 'DESC'; - } else { - this.order = 'ASC'; + if (!this.orderLocked) { + if (this.order === 'ASC') { + this.order = 'DESC'; + } else { + this.order = 'ASC'; + } + this.gridHeader.selectColum(this); } - 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'), diff --git a/client/core/src/column-header/column-header.spec.js b/client/core/src/column-header/column-header.spec.js index 5c6d29d73..48954826e 100644 --- a/client/core/src/column-header/column-header.spec.js +++ b/client/core/src/column-header/column-header.spec.js @@ -3,6 +3,7 @@ import './column-header.js'; describe('Component vnColumnHeader', () => { let $componentController; let controller; + let $attrs; beforeEach(() => { angular.mock.module('client'); @@ -10,7 +11,8 @@ describe('Component vnColumnHeader', () => { beforeEach(angular.mock.inject(_$componentController_ => { $componentController = _$componentController_; - controller = $componentController('vnColumnHeader', {}); + $attrs = {}; + controller = $componentController('vnColumnHeader', {$attrs}); })); describe('onClick()', () => { diff --git a/client/core/src/datePicker/datePicker.html b/client/core/src/datePicker/datePicker.html index d91f0a53f..21839aa16 100644 --- a/client/core/src/datePicker/datePicker.html +++ b/client/core/src/datePicker/datePicker.html @@ -4,7 +4,8 @@ ng-focus="$ctrl.hasFocus = true" ng-blur="$ctrl.hasFocus = false" ng-mouseenter="$ctrl.hasMouseIn = true" - ng-mouseleave="$ctrl.hasMouseIn = false" + ng-mouseleave="$ctrl.hasMouseIn = false" + ng-click="$ctrl.onClick()" > { }); describe('$onChanges()', () => { - it(`should set the top css of the $element`, () => { - let argumentObject = {show: true, top: {currentValue: 100}}; - spyOn(controller.$element, 'css'); - controller.$onChanges(argumentObject); - - expect(controller.$element.css).toHaveBeenCalledWith('top', '100px'); - }); - it(`should set the width css of the $element`, () => { let argumentObject = {show: true, itemWidth: {currentValue: 100}}; spyOn(controller.$element, 'css'); @@ -295,26 +287,40 @@ describe('Component vnDropDown', () => { controller.selectItem(item); expect(controller.selected).toEqual(item); - expect(controller._show).toEqual(true); + expect(controller._show).not.toBeDefined(); }); }); describe('loadItems()', () => { - it(`should set controller._show to true`, () => { + it(`should set controller.show to true`, () => { + controller.show = false; + controller.itemsFiltered = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}]; controller.loadItems(); - expect(controller._show).toEqual(true); + expect(controller.show).toEqual(true); }); - it(`should call loadMore() and then set controller._show to true`, () => { + it(`should call loadMore() and then set controller._show to true if there are items`, () => { controller.showLoadMore = () => {}; controller.loadMore = () => {}; spyOn(controller, 'loadMore'); + controller.itemsFiltered = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}]; controller.loadItems(); expect(controller._show).toEqual(true); expect(controller.loadMore).toHaveBeenCalledWith(); }); + + it(`should call loadMore() and then set controller._show to undefined if there are not items`, () => { + controller.showLoadMore = () => {}; + controller.loadMore = () => {}; + spyOn(controller, 'loadMore'); + controller.itemsFiltered = []; + controller.loadItems(); + + expect(controller._show).not.toBeDefined(); + expect(controller.loadMore).toHaveBeenCalledWith(); + }); }); describe('$onInit()', () => { diff --git a/client/core/src/grid-header/style.scss b/client/core/src/grid-header/style.scss index cc983dcf1..324e488d1 100644 --- a/client/core/src/grid-header/style.scss +++ b/client/core/src/grid-header/style.scss @@ -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; diff --git a/client/core/src/watcher/watcher.js b/client/core/src/watcher/watcher.js index 2dbc5a2bc..d259f6f39 100644 --- a/client/core/src/watcher/watcher.js +++ b/client/core/src/watcher/watcher.js @@ -68,9 +68,9 @@ export default class Watcher extends Component { * * @param {String} state The state name */ - submitGo(state) { + submitGo(state, params) { return this.submit().then( - () => this.$state.go(state) + () => this.$state.go(state, params || {}) ); } /** diff --git a/client/core/src/watcher/watcher.spec.js b/client/core/src/watcher/watcher.spec.js index 0ed342e31..7cd629cd8 100644 --- a/client/core/src/watcher/watcher.spec.js +++ b/client/core/src/watcher/watcher.spec.js @@ -100,11 +100,11 @@ describe('Component vnWatcher', () => { it(`should call controller.$state.go() function after calling controllers submit() function`, done => { spyOn(controller, 'submit').and.returnValue(Promise.resolve()); spyOn(controller.$state, 'go'); - let state = 'the state'; + let state = 'the.State'; controller.submitGo(state) .then(() => { expect(controller.submit).toHaveBeenCalledWith(); - expect(controller.$state.go).toHaveBeenCalledWith(state); + expect(controller.$state.go).toHaveBeenCalledWith(state, {}); done(); }); }); diff --git a/client/salix/src/components/left-menu/actions.js b/client/salix/src/components/left-menu/actions.js index 4d4d6ee6d..30d379df1 100644 --- a/client/salix/src/components/left-menu/actions.js +++ b/client/salix/src/components/left-menu/actions.js @@ -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); diff --git a/client/salix/src/configroutes.js b/client/salix/src/configroutes.js index 1d79c5bc2..e5ab72fb8 100644 --- a/client/salix/src/configroutes.js +++ b/client/salix/src/configroutes.js @@ -47,9 +47,8 @@ function config($stateProvider, $urlRouterProvider, aclServiceProvider, modulesF for (let i = 0; i < count; i++) { let route = fileRoutes[i]; if (aclService.routeHasPermission(route)) { - $stateProvider.state(route.state, { + let configRoute = { url: route.url, - abstract: route.abstract || false, template: `<${route.component} ${getParams(route)}>`, resolve: { loader: loader(moduleName, validations) @@ -57,7 +56,13 @@ function config($stateProvider, $urlRouterProvider, aclServiceProvider, modulesF data: { routes: fileRoutes } - }); + }; + if (route.abstract) + configRoute.abstract = true; + if (route.routeParams) + configRoute.params = route.routeParams; + + $stateProvider.state(route.state, configRoute); } else if (route.state === mainModule.state) { break; } diff --git a/services/client/common/methods/client/before-save.js b/services/client/common/methods/client/before-save.js index 470b7ba3f..b761a71f1 100644 --- a/services/client/common/methods/client/before-save.js +++ b/services/client/common/methods/client/before-save.js @@ -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; } diff --git a/services/client/common/methods/greuge/filter.js b/services/client/common/methods/greuge/filter.js new file mode 100644 index 000000000..dba4e8ef6 --- /dev/null +++ b/services/client/common/methods/greuge/filter.js @@ -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"] + } + } + }; + } +}; diff --git a/services/client/common/methods/greuge/totalGreuge.js b/services/client/common/methods/greuge/totalGreuge.js new file mode 100644 index 000000000..849746493 --- /dev/null +++ b/services/client/common/methods/greuge/totalGreuge.js @@ -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); + }); + }; +}; diff --git a/services/client/common/models/client-credit.js b/services/client/common/models/client-credit.js new file mode 100644 index 000000000..7205be03e --- /dev/null +++ b/services/client/common/models/client-credit.js @@ -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; + } +}; diff --git a/services/client/common/models/client-credit.json b/services/client/common/models/client-credit.json index f6512bfc7..26a1733ad 100644 --- a/services/client/common/models/client-credit.json +++ b/services/client/common/models/client-credit.json @@ -1,5 +1,5 @@ { - "name": "ClientCredit", + "name": "clientCredit", "base": "VnModel", "validateUpsert": true, "properties": { diff --git a/services/client/common/models/greuge-type.json b/services/client/common/models/greuge-type.json new file mode 100644 index 000000000..151aea5a6 --- /dev/null +++ b/services/client/common/models/greuge-type.json @@ -0,0 +1,14 @@ +{ + "name": "greugeType", + "base": "VnModel", + "properties": { + "id": { + "id": true, + "type": "Number", + "description": "Identifier" + }, + "name": { + "type": "String" + } + } + } \ No newline at end of file diff --git a/services/client/common/models/greuge.js b/services/client/common/models/greuge.js new file mode 100644 index 000000000..7bacecc4e --- /dev/null +++ b/services/client/common/models/greuge.js @@ -0,0 +1,4 @@ +module.exports = function(Self) { + require('../methods/greuge/filter.js')(Self); + require('../methods/greuge/totalGreuge.js')(Self); +}; diff --git a/services/client/common/models/greuge.json b/services/client/common/models/greuge.json new file mode 100644 index 000000000..2c00f9f73 --- /dev/null +++ b/services/client/common/models/greuge.json @@ -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" + } + } + } \ No newline at end of file diff --git a/services/client/common/validations/validateDni.js b/services/client/common/validations/validateDni.js index ab9008605..94b595f09 100644 --- a/services/client/common/validations/validateDni.js +++ b/services/client/common/validations/validateDni.js @@ -1,4 +1,7 @@ module.exports = fi => { + if (fi === undefined || fi === null) { + return true; + } let dni = fi; let getLetterDni = dni => { const regExpDni = 'TRWAGMYFPDXBNJZSQVHLCKE'; diff --git a/services/client/server/model-config.json b/services/client/server/model-config.json index 3c9c2199d..c95fb15c7 100644 --- a/services/client/server/model-config.json +++ b/services/client/server/model-config.json @@ -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" } } diff --git a/services/loopback/common/models/vn-model.js b/services/loopback/common/models/vn-model.js index 3305cb67d..30f358204 100644 --- a/services/loopback/common/models/vn-model.js +++ b/services/loopback/common/models/vn-model.js @@ -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,8 +161,12 @@ module.exports = function(Self) { var response = {}; function returnValues() { - if (response.instances !== undefined && response.count !== undefined) - cb(null, response); + if (response.instances !== undefined && response.count !== undefined) { + if (filterResult) + cb(null, filterResult(response)); + else + cb(null, response); + } } function error() { diff --git a/services/print/application/config/datasources.json b/services/print/application/config/datasources.json index 92965aa5a..93a49479a 100644 --- a/services/print/application/config/datasources.json +++ b/services/print/application/config/datasources.json @@ -12,8 +12,12 @@ "database": "" }, "pdf": { + "format": "A4", + "header": { + "height": "120px" + }, "footer": { - "height": "100px" + "height": "130px" } } } \ No newline at end of file diff --git a/services/print/application/route/manuscript.js b/services/print/application/route/manuscript.js index 932d96c33..90662b646 100644 --- a/services/print/application/route/manuscript.js +++ b/services/print/application/route/manuscript.js @@ -54,4 +54,13 @@ router.get('/sepa-core/:clientId', function(request, response, next) { }); }); +router.get('/sepa-core-view/:clientId', function(request, response, next) { + template.get('sepa-core', {clientId: request.params.clientId}, (error, result) => { + if (error) + return response.status(400).json({message: error.message}); + + response.send(result.body); + }); + }); + module.exports = router; diff --git a/services/print/application/template/header/static/css/style.css b/services/print/application/template/header/static/css/style.css index d06163ee6..186ede66b 100644 --- a/services/print/application/template/header/static/css/style.css +++ b/services/print/application/template/header/static/css/style.css @@ -5,8 +5,8 @@ img { #pageHeader-first { border-bottom: 1px solid #DDD; font-family: arial, sans-serif; + padding-bottom: 10px; text-align: center; - padding: 10px 20px; font-size: 10px; color: #555 } diff --git a/services/print/application/template/sepa-core/index.html b/services/print/application/template/sepa-core/index.html index be79db11d..867da43d9 100644 --- a/services/print/application/template/sepa-core/index.html +++ b/services/print/application/template/sepa-core/index.html @@ -17,12 +17,11 @@

{{_.title}}

-
+
{{_.toCompleteBySupplier}}
{{_.orderReference}}
{{mandateCode}}
-
test descripcion
{{_.supplierIdentifier}}
@@ -46,10 +45,11 @@
-

{{_.bodyDescription}}

+

{{_.bodyDescription}}

+

{{_.clientAdvice}}

-

{{_.clientAdvice}}

+
{{_.toCompleteByClient}}
{{_.clientName}}
{{clientName}}
@@ -68,7 +68,7 @@
{{clientCountry}}
-
{{_.swift}}
+
{{_.swift}}
{{#swiftFields}}
@@ -83,12 +83,28 @@
{{/accountNumberFields}}
+
+
{{_.accountNumberFormat}}
+
-
{{_.paymentType}}
+
{{_.paymentType}}
-
X
- Recurrente +
+
+
+
X
+
+
{{_.recurrent}}
+
+
O
+
+
+
+
+
{{_.unique}}
+
+
@@ -100,10 +116,8 @@
- -
A cumplimentar por el deudor
-

TODOS LOS CAMPOS HAN DE SER CUMPLIMENTADOS OBLIGATORIAMENTE.

-

UNA VEZ FIRMADA ESTA ORDEN DE DOMICILIACIÓN DEBE SER ENVIADA AL ACREEDOR PARA SU CUSTODIA Y ES RECOMENDABLE FACILITAR UNA COPIA A SU ENTIDAD BANCARIA.

+

{{_.mandatoryFields}}

+

{{_.sendOrder}}

diff --git a/services/print/application/template/sepa-core/locale/es.json b/services/print/application/template/sepa-core/locale/es.json index ed126e57d..e5453e858 100644 --- a/services/print/application/template/sepa-core/locale/es.json +++ b/services/print/application/template/sepa-core/locale/es.json @@ -1,5 +1,7 @@ { "title": "Orden de domiciliación de adeudo directo SEPA CORE", + "toCompleteBySupplier": "A cumplimentar por el acreedor", + "toCompleteByClient": "A cumplimentar por el deudor", "bodyDescription": "Mediante la firma de esta orden de domiciliación, el deudor autoriza (A) al acreedor a enviar instrucciones a la entidad del deudor para adeudar su cuenta y (B) a la entidad para efectuar los adeudos en su cuenta siguiendo las instrucciones del acreedor.Como parte de sus derechos, el deudor está legitimado al reembolso por su entidad en los términos y condiciones del contrato suscrito con la misma. La solicitud de reembolso deberá efectuarse dentro de las ocho semanas que adeudo en cuenta. Puede obtener información adicional sobre sus derechos en su entidad financiera.", "orderReference": "Referencia de la orden de domiciliación", "supplierIdentifier": "Identificador del acreedor", @@ -15,10 +17,15 @@ "swift": "Swift BIC", "accountNumber": "Número de cuenta - IBAN", "accountHolder": "(Titular/es de la cuenta de cargo)", + "accountNumberFormat": "En España el IBAN consta de 24 posiciones comenzando siempre por ES", "paymentType": "Tipo de pago", + "recurrent": "Recurrente", + "unique": "Único", "signLocation": "Fecha - Localidad", "sign": "Firma del deudor y sello", - "fiscalAddress": "VERDNATURA LEVANTE SL, B97367486 Avda. Espioca, 100, 46460 Silla _ www.verdnatura.es _ clientes@verdnatura.es", + "mandatoryFields": "TODOS LOS CAMPOS HAN DE SER CUMPLIMENTADOS OBLIGATORIAMENTE.", + "sendOrder": "UNA VEZ FIRMADA ESTA ORDEN DE DOMICILIACIÓN DEBE SER ENVIADA AL ACREEDOR PARA SU CUSTODIA Y ES RECOMENDABLE FACILITAR UNA COPIA A SU ENTIDAD BANCARIA.", + "fiscalAddress": "VERDNATURA LEVANTE SL, B97367486 Avda. Espioca, 100, 46460 Silla · www.verdnatura.es · clientes@verdnatura.es", "privacy": "- AVISO - Este mensaje es privado y confidencial, y debe ser utilizado exclusivamente por la persona destinataria del mismo. Si usted ha recibido este mensaje por error, le rogamos lo comunique al remitente y borre dicho mensaje y cualquier documento adjunto que pudiera contener. Verdnatura Levante SL no renuncia a la confidencialidad ni a ningún privilegio por causa de transmisión errónea o mal funcionamiento. Igualmente no se hace responsable de los cambios, alteraciones, errores u omisiones que pudieran hacerse al mensaje una vez enviado.", "privacyLaw": "En cumplimiento de lo dispuesto en la Ley Orgánica 15/1999, de Protección de Datos de Carácter Personal, le comunicamos que los datos personales que facilite se incluirán en ficheros automatizados de VERDNATURA LEVANTE S.L., pudiendo en todo momento ejercitar los derechos de acceso, rectificación, cancelación y oposición, comunicándolo por escrito al domicilio social de la entidad. La finalidad del fichero es la gestión administrativa, contabilidad, y facturación." } \ No newline at end of file diff --git a/services/print/application/template/sepa-core/static/css/style.css b/services/print/application/template/sepa-core/static/css/style.css index 3ea38e189..5b1e628d6 100644 --- a/services/print/application/template/sepa-core/static/css/style.css +++ b/services/print/application/template/sepa-core/static/css/style.css @@ -7,7 +7,7 @@ img { max-width: 90%; margin: 0 auto; font-size: 14px; - color: #555 + color: #000 } body .title { diff --git a/services/print/static/css/component.css b/services/print/static/css/component.css index 6da33bee3..e7fc24b0a 100644 --- a/services/print/static/css/component.css +++ b/services/print/static/css/component.css @@ -1,14 +1,18 @@ +body { + margin: 0 auto; + width: 210mm +} + .panel { border: 1px solid #DDD; margin-bottom: 10px; + position: relative; padding:10px } .row { margin-bottom: 15px; - overflow: hidden; - content: ''; - clear: both + overflow: hidden } .row .text { @@ -21,14 +25,34 @@ box-sizing: border-box } +.row .text, .row .control { + overflow: hidden +} + .row .description { + position: relative; + padding-top: 2px; + overflow: hidden; font-size: 8px; + display: block; color: #999 } -.row .v-align { - padding-top: 5px; - line-height: 21px +.row .line { + border-bottom: 1px solid #DDD; + border-right: 1px solid #DDD; + border-left: 1px solid #DDD; + margin-top: 10px; + color: #999; + padding: 5px +} + +.row .description span { + background-color: #FFF; + margin: -5px 0 0 50px; + display: block; + padding: 5px; + float: left } .row:last-child { @@ -49,6 +73,11 @@ float: left } +.row.inline .description { + position: static; + overflow: visible +} + .box { border-top: 1px solid #CCC; border-right: 1px solid #CCC; @@ -62,6 +91,11 @@ float: left } +.box.crossed { + font-weight: 100; + font-size: 16px +} + .row .control .box:first-child { border-left: 1px solid #CCC; } @@ -70,6 +104,67 @@ p { text-align: justify } -p.small { +.font.small { font-size: 10px -} \ No newline at end of file +} + +.font.verticalAlign { + height: 27px; + line-height: 27px +} + +.font.centered { + height: 27px; + line-height: 27px; + text-align: center +} + +.verticalText { + -moz-transform: rotate(90deg); + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + position: absolute; + text-align: center; + font-size: .65em; + width: 200px; + right: -115px; + top: 50% +} + +.columns:after { + display: block; + content: ' '; + clear: both +} + +.columns .size100 { + width: 100%; + float: left +} + +.columns .size75 { + width: 75%; + float: left +} + +.columns .size50 { + width: 50%; + float: left +} + +.columns .size33 { + width: 33.33%; + float: left +} + +.columns .size25 { + width: 25%; + float: left +} + + + + + + +