diff --git a/db/dump/structure.sql b/db/dump/structure.sql index 7d79b45d3..8bc0aed8f 100644 --- a/db/dump/structure.sql +++ b/db/dump/structure.sql @@ -30193,7 +30193,7 @@ BEGIN NEW.currencyFk != OLD.currencyFk THEN - CALL vn2008.recibidaIvaDivisaUpdate(NEW.id); + -- CALL vn2008.recibidaIvaDivisaUpdate(NEW.id); END IF; diff --git a/modules/entry/back/methods/entry/filter.js b/modules/entry/back/methods/entry/filter.js index 42dbe3078..0148d866d 100644 --- a/modules/entry/back/methods/entry/filter.js +++ b/modules/entry/back/methods/entry/filter.js @@ -10,76 +10,81 @@ module.exports = Self => { accepts: [ { arg: 'filter', - type: 'Object', + type: 'object', description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string', http: {source: 'query'} }, { arg: 'search', - type: 'String', + type: 'string', description: 'Searchs the entry by id', http: {source: 'query'} }, { arg: 'id', - type: 'Integer', + type: 'integer', description: 'The entry id', http: {source: 'query'} }, { arg: 'created', - type: 'Date', + type: 'date', description: 'The created date to filter', http: {source: 'query'} }, { arg: 'travelFk', - type: 'Number', + type: 'number', description: 'The travel id to filter', http: {source: 'query'} }, { arg: 'companyFk', - type: 'Number', + type: 'number', description: 'The company to filter', http: {source: 'query'} }, { arg: 'isBooked', - type: 'Boolean', + type: 'boolean', description: 'The isBokked filter', http: {source: 'query'} }, { arg: 'isConfirmed', - type: 'Boolean', + type: 'boolean', description: 'The isConfirmed filter', http: {source: 'query'} }, { arg: 'isOrdered', - type: 'Boolean', + type: 'boolean', description: 'The isOrdered filter', http: {source: 'query'} }, { arg: 'ref', - type: 'String', + type: 'string', description: 'The ref filter', http: {source: 'query'} }, { arg: 'supplierFk', - type: 'Number', + type: 'number', description: 'The supplier id to filter', http: {source: 'query'} + }, { + arg: 'invoiceInFk', + type: 'number', + description: 'The invoiceIn id to filter', + http: {source: 'query'} }, { arg: 'currencyFk', - type: 'Number', + type: 'number', description: 'The currency id to filter', http: {source: 'query'} }, { arg: 'from', - type: 'Date', + type: 'date', description: `The from date filter` }, { arg: 'to', - type: 'Date', + type: 'date', description: `The to date filter` } ], returns: { - type: ['Object'], + type: ['object'], root: true }, http: { @@ -116,6 +121,7 @@ module.exports = Self => { case 'travelFk': case 'currencyFk': case 'supplierFk': + case 'invoiceInFk': param = `e.${param}`; return {[param]: value}; } diff --git a/modules/invoiceIn/back/methods/invoice-in/filter.js b/modules/invoiceIn/back/methods/invoice-in/filter.js index 20680f153..0b9825752 100644 --- a/modules/invoiceIn/back/methods/invoice-in/filter.js +++ b/modules/invoiceIn/back/methods/invoice-in/filter.js @@ -17,7 +17,7 @@ module.exports = Self => { { arg: 'search', type: 'string', - description: 'Searchs the invoiceOut by id', + description: 'Searchs the invoiceIn by id', http: {source: 'query'} }, { @@ -25,6 +25,11 @@ module.exports = Self => { type: 'string', description: 'The supplier reference' }, + { + arg: 'supplierFk', + type: 'number', + description: 'The supplier id' + }, { arg: 'fi', type: 'string', @@ -108,6 +113,7 @@ module.exports = Self => { case 'fi': return {[`s.${param}`]: value}; case 'supplierRef': + case 'supplierFk': case 'serialNumber': case 'serial': case 'issued': @@ -132,7 +138,7 @@ module.exports = Self => { ii.isBooked, ii.supplierRef, ii.docFk AS dmsFk, - s.id AS supplierFk, + ii.supplierFk, s.name AS supplierName, s.account, SUM(iid.amount) AS amount, diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/summary.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/summary.spec.js new file mode 100644 index 000000000..ff7a39ef5 --- /dev/null +++ b/modules/invoiceIn/back/methods/invoice-in/specs/summary.spec.js @@ -0,0 +1,9 @@ +const app = require('vn-loopback/server/server'); + +describe('invoiceIn summary()', () => { + it('should return a summary object containing data from one invoiceIn', async() => { + const summary = await app.models.InvoiceIn.summary(1); + + expect(summary.supplierRef).toEqual('1234'); + }); +}); diff --git a/modules/invoiceIn/back/methods/invoice-in/summary.js b/modules/invoiceIn/back/methods/invoice-in/summary.js new file mode 100644 index 000000000..c4101e4dc --- /dev/null +++ b/modules/invoiceIn/back/methods/invoice-in/summary.js @@ -0,0 +1,48 @@ +module.exports = Self => { + Self.remoteMethod('summary', { + description: 'The invoiceIn summary', + accessType: 'READ', + accepts: [{ + arg: 'id', + type: 'number', + required: true, + description: 'The invoiceIn id', + http: {source: 'path'} + }], + returns: { + type: 'object', + root: true + }, + http: { + path: `/:id/summary`, + verb: 'GET' + } + }); + + Self.summary = async id => { + const filter = { + include: [ + { + relation: 'company', + scope: { + fields: ['id', 'code'] + } + }, + { + relation: 'supplier', + scope: { + fields: ['id', 'name'] + } + }, + { + relation: 'sageWithholding', + scope: { + fields: ['withholding'] + } + } + ] + }; + + return Self.app.models.InvoiceIn.findById(id, filter); + }; +}; diff --git a/modules/invoiceIn/back/model-config.json b/modules/invoiceIn/back/model-config.json index 7f95924a4..88d227ba3 100644 --- a/modules/invoiceIn/back/model-config.json +++ b/modules/invoiceIn/back/model-config.json @@ -1,5 +1,8 @@ { "InvoiceIn": { "dataSource": "vn" + }, + "InvoiceInDueDay": { + "dataSource": "vn" } } diff --git a/modules/invoiceIn/back/models/invoice-in-due-day.json b/modules/invoiceIn/back/models/invoice-in-due-day.json new file mode 100644 index 000000000..6c27dcd6c --- /dev/null +++ b/modules/invoiceIn/back/models/invoice-in-due-day.json @@ -0,0 +1,33 @@ +{ + "name": "InvoiceInDueDay", + "base": "VnModel", + "options": { + "mysql": { + "table": "invoiceInDueDay" + } + }, + "properties": { + "id": { + "id": true, + "type": "number", + "description": "Identifier" + }, + "invoiceInFk": { + "type": "number" + }, + "dueDated": { + "type": "date" + }, + "bankFk": { + "type": "number" + }, + "amount": { + "type": "number" + }, + "created": { + "type": "date" + } + } +} + + diff --git a/modules/invoiceIn/back/models/invoice-in.js b/modules/invoiceIn/back/models/invoice-in.js index 278843428..7c5b16358 100644 --- a/modules/invoiceIn/back/models/invoice-in.js +++ b/modules/invoiceIn/back/models/invoice-in.js @@ -1,3 +1,4 @@ module.exports = Self => { require('../methods/invoice-in/filter')(Self); + require('../methods/invoice-in/summary')(Self); }; diff --git a/modules/invoiceIn/back/models/invoice-in.json b/modules/invoiceIn/back/models/invoice-in.json index 3310c4346..ad14fb511 100644 --- a/modules/invoiceIn/back/models/invoice-in.json +++ b/modules/invoiceIn/back/models/invoice-in.json @@ -18,6 +18,9 @@ "serial": { "type": "string" }, + "supplierRef": { + "type": "string" + }, "issued": { "type": "date" }, @@ -27,12 +30,18 @@ "isBooked": { "type": "boolean" }, + "isVatDeductible": { + "type": "boolean" + }, "booked": { "type": "date" }, "operated": { "type": "date" }, + "bookEntried": { + "type": "date" + }, "dmsFk": { "type": "number", "mysql": { @@ -41,6 +50,16 @@ } }, "relations": { + "invoiceInDueDay": { + "type": "hasMany", + "model": "InvoiceInDueDay", + "foreignKey": "invoiceInFk" + }, + "sageWithholding": { + "type": "belongsTo", + "model": "SageWithholding", + "foreignKey": "withholdingSageFk" + }, "company": { "type": "belongsTo", "model": "Company", diff --git a/modules/invoiceIn/front/basic-data/index.html b/modules/invoiceIn/front/basic-data/index.html new file mode 100644 index 000000000..15052c5fe --- /dev/null +++ b/modules/invoiceIn/front/basic-data/index.html @@ -0,0 +1,93 @@ + + + +
+ + + + + + + + + + + {{::id}} - {{::nickname}} + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/modules/invoiceIn/front/basic-data/index.js b/modules/invoiceIn/front/basic-data/index.js new file mode 100644 index 000000000..6a39f35cd --- /dev/null +++ b/modules/invoiceIn/front/basic-data/index.js @@ -0,0 +1,10 @@ +import ngModule from '../module'; +import Section from 'salix/components/section'; + +ngModule.vnComponent('vnInvoiceInBasicData', { + template: require('./index.html'), + controller: Section, + bindings: { + invoiceIn: '<' + } +}); diff --git a/modules/invoiceIn/front/card/index.js b/modules/invoiceIn/front/card/index.js index 8c53ea8b8..c669e5f7f 100644 --- a/modules/invoiceIn/front/card/index.js +++ b/modules/invoiceIn/front/card/index.js @@ -3,10 +3,27 @@ import ModuleCard from 'salix/components/module-card'; class Controller extends ModuleCard { reload() { - const filter = {}; + const filter = { + include: [ + { + relation: 'supplier' + }, + { + relation: 'invoiceInDueDay' + }, + { + relation: 'company' + } + ]}; this.$http.get(`InvoiceIns/${this.$params.id}`, {filter}) - .then(res => this.invoiceIn = res.data); + .then(res => { + this.invoiceIn = res.data; + this.invoiceIn.amount = res.data.invoiceInDueDay.reduce( + (accumulator, currentValue) => { + return accumulator + (currentValue['amount'] || 0); + }, 0); + }); } } diff --git a/modules/invoiceIn/front/card/index.spec.js b/modules/invoiceIn/front/card/index.spec.js index 70f10f6b1..128f2334f 100644 --- a/modules/invoiceIn/front/card/index.spec.js +++ b/modules/invoiceIn/front/card/index.spec.js @@ -3,7 +3,12 @@ import './index.js'; describe('vnInvoiceIn', () => { let controller; let $httpBackend; - let data = {id: 1, name: 'fooName'}; + const expectedAmount = 99; + const data = { + id: 1, + name: 'fooName', + invoiceInDueDay: [{amount: expectedAmount}] + }; beforeEach(ngModule('invoiceIn')); @@ -21,7 +26,8 @@ describe('vnInvoiceIn', () => { controller.reload(); $httpBackend.flush(); - expect(controller.invoiceIn).toEqual(data); + expect(controller.invoiceIn).toBeDefined(); + expect(controller.invoiceIn.amount).toEqual(expectedAmount); }); }); diff --git a/modules/invoiceIn/front/descriptor/index.html b/modules/invoiceIn/front/descriptor/index.html index e69de29bb..42a946913 100644 --- a/modules/invoiceIn/front/descriptor/index.html +++ b/modules/invoiceIn/front/descriptor/index.html @@ -0,0 +1,49 @@ + + + + Delete Invoice + + + +
+ + + + + + + + + {{$ctrl.invoiceIn.supplier.nickname}} + + +
+ +
+
+ + + + diff --git a/modules/invoiceIn/front/descriptor/index.js b/modules/invoiceIn/front/descriptor/index.js index 6b22dd62b..be507e0d4 100644 --- a/modules/invoiceIn/front/descriptor/index.js +++ b/modules/invoiceIn/front/descriptor/index.js @@ -10,6 +10,26 @@ class Controller extends Descriptor { this.entity = value; } + get entryFilter() { + if (this.invoiceIn) + return JSON.stringify({invoiceInFk: this.invoiceIn.id}); + + return null; + } + + get invoiceInFilter() { + if (this.invoiceIn) + return JSON.stringify({supplierFk: this.invoiceIn.supplierFk}); + + return null; + } + + deleteInvoiceIn() { + return this.$http.delete(`InvoiceIns/${this.id}`) + .then(() => this.$state.go('invoiceIn.index')) + .then(() => this.vnApp.showSuccess(this.$t('InvoiceIn deleted'))); + } + loadData() { const filter = { include: [ diff --git a/modules/invoiceIn/front/index.js b/modules/invoiceIn/front/index.js index acb341c50..6c175d9a0 100644 --- a/modules/invoiceIn/front/index.js +++ b/modules/invoiceIn/front/index.js @@ -6,3 +6,5 @@ import './search-panel'; import './card'; import './descriptor'; import './descriptor-popover'; +import './summary'; +import './basic-data'; diff --git a/modules/invoiceIn/front/index/index.html b/modules/invoiceIn/front/index/index.html index d3d1f820e..3d9b787d9 100644 --- a/modules/invoiceIn/front/index/index.html +++ b/modules/invoiceIn/front/index/index.html @@ -22,26 +22,28 @@ - + {{::invoiceIn.id}} {{::invoiceIn.supplierName}} - + {{::invoiceIn.supplierRef | dashIfEmpty}} - {{::invoiceIn.serialNumber}} - {{::invoiceIn.serial}} - {{::invoiceIn.account}} + {{::invoiceIn.serialNumber}} + {{::invoiceIn.serial}} + {{::invoiceIn.account}} {{::invoiceIn.issued | date:'dd/MM/yyyy' | dashIfEmpty}} - + {{::invoiceIn.awbCode}} {{::invoiceIn.amount | currency:'EUR'}} @@ -67,38 +69,6 @@ + invoice-in="$ctrl.selectedInvoiceIn"> - - - - - - - Filter by selection - - - Exclude selection - - - Remove filter - - - Remove all filters - - - Copy value - - - + \ No newline at end of file diff --git a/modules/invoiceIn/front/index/index.js b/modules/invoiceIn/front/index/index.js index 4bb0fd6a4..c6fc14c25 100644 --- a/modules/invoiceIn/front/index/index.js +++ b/modules/invoiceIn/front/index/index.js @@ -34,6 +34,11 @@ export default class Controller extends Section { return [minHour, maxHour]; } + + preview(invoiceIn) { + this.selectedInvoiceIn = invoiceIn; + this.$.summary.show(); + } } ngModule.vnComponent('vnInvoiceInIndex', { diff --git a/modules/invoiceIn/front/locale/es.yml b/modules/invoiceIn/front/locale/es.yml index 02501b14a..2d8dc02da 100644 --- a/modules/invoiceIn/front/locale/es.yml +++ b/modules/invoiceIn/front/locale/es.yml @@ -1,2 +1,5 @@ InvoiceIn: Facturas recibidas -Search invoices in by reference: Buscar facturas recibidas por referencia \ No newline at end of file +Search invoices in by reference: Buscar facturas recibidas por referencia +Entries list: Listado de entradas +Invoice list: Listado de entradas +InvoiceIn deleted: Factura eliminada \ No newline at end of file diff --git a/modules/invoiceIn/front/routes.json b/modules/invoiceIn/front/routes.json index 84f713c5c..05eff347b 100644 --- a/modules/invoiceIn/front/routes.json +++ b/modules/invoiceIn/front/routes.json @@ -7,6 +7,12 @@ "menus": { "main": [ {"state": "invoiceIn.index", "icon": "icon-invoiceIn"} + ], + "card": [ + { + "state": "invoiceIn.card.basicData", + "icon": "settings" + } ] }, "routes": [ @@ -36,9 +42,18 @@ "component": "vn-invoice-in-summary", "description": "Summary", "params": { - "invoice-In": "$ctrl.invoiceIn" + "invoice-in": "$ctrl.invoiceIn" }, - "acl": ["developer"] + "acl": ["administrative"] + }, + { + "url": "/basic-data", + "state": "invoiceIn.card.basicData", + "component": "vn-invoice-in-basic-data", + "description": "Basic data", + "params": { + "invoice-in": "$ctrl.invoiceIn" + } } ] } \ No newline at end of file diff --git a/modules/invoiceIn/front/summary/index.html b/modules/invoiceIn/front/summary/index.html new file mode 100644 index 000000000..360ef8014 --- /dev/null +++ b/modules/invoiceIn/front/summary/index.html @@ -0,0 +1,52 @@ + +
+ + + + {{$ctrl.summary.id}} - {{$ctrl.summary.supplier.name}} +
+ + +

Basic data

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + \ No newline at end of file diff --git a/modules/invoiceIn/front/summary/index.js b/modules/invoiceIn/front/summary/index.js new file mode 100644 index 000000000..54b5bcd00 --- /dev/null +++ b/modules/invoiceIn/front/summary/index.js @@ -0,0 +1,28 @@ +import ngModule from '../module'; +import Summary from 'salix/components/summary'; +import './style.scss'; + +class Controller extends Summary { + set invoiceIn(value) { + this._invoiceIn = value; + if (value && value.id) + this.getSummary(); + } + + get invoiceIn() { + return this._invoiceIn; + } + + getSummary() { + return this.$http.get(`InvoiceIns/${this.invoiceIn.id}/summary`) + .then(res => this.summary = res.data); + } +} + +ngModule.vnComponent('vnInvoiceInSummary', { + template: require('./index.html'), + controller: Controller, + bindings: { + invoiceIn: '<' + } +}); diff --git a/modules/invoiceIn/front/summary/index.spec.js b/modules/invoiceIn/front/summary/index.spec.js new file mode 100644 index 000000000..56bfe9f4a --- /dev/null +++ b/modules/invoiceIn/front/summary/index.spec.js @@ -0,0 +1,29 @@ +import './index.js'; + +describe('InvoiceIn', () => { + describe('Component summary', () => { + let controller; + let $httpBackend; + let $scope; + + beforeEach(ngModule('invoiceIn')); + + beforeEach(inject(($componentController, _$httpBackend_, $rootScope) => { + $httpBackend = _$httpBackend_; + $scope = $rootScope.$new(); + const $element = angular.element(''); + controller = $componentController('vnInvoiceInSummary', {$element, $scope}); + controller.invoiceIn = {id: 1}; + })); + + describe('getSummary()', () => { + it('should perform a query to set summary', () => { + $httpBackend.when('GET', `InvoiceIns/1/summary`).respond(200, 'the data you are looking for'); + controller.getSummary(); + $httpBackend.flush(); + + expect(controller.summary).toEqual('the data you are looking for'); + }); + }); + }); +}); diff --git a/modules/invoiceIn/front/summary/locale/es.yml b/modules/invoiceIn/front/summary/locale/es.yml new file mode 100644 index 000000000..29bed3f9c --- /dev/null +++ b/modules/invoiceIn/front/summary/locale/es.yml @@ -0,0 +1,10 @@ +Go to the Invoice In: Ir a la factura recibida +Expedition date: Fecha expedición +Operation date: Fecha operación +Supplier ref: Ref. proveedor +Entry date: Fecha asiento +Booked date: Fecha contable +Accounted date: Fecha contable +Doc number: Numero documento +Sage withholding: Retención sage +Deductible: Deducible \ No newline at end of file diff --git a/modules/invoiceIn/front/summary/style.scss b/modules/invoiceIn/front/summary/style.scss new file mode 100644 index 000000000..f7ddb2cb7 --- /dev/null +++ b/modules/invoiceIn/front/summary/style.scss @@ -0,0 +1,5 @@ +@import "variables"; + +vn-invoice-in-summary .summary { + width: $width-lg; +} \ No newline at end of file