diff --git a/back/model-config.json b/back/model-config.json index 323e5f233..dc5cde217 100644 --- a/back/model-config.json +++ b/back/model-config.json @@ -2,6 +2,9 @@ "Account": { "dataSource": "vn" }, + "AccountingType": { + "dataSource": "vn" + }, "Bank": { "dataSource": "vn" }, diff --git a/back/models/accounting-type.json b/back/models/accounting-type.json new file mode 100644 index 000000000..796793342 --- /dev/null +++ b/back/models/accounting-type.json @@ -0,0 +1,30 @@ +{ + "name": "AccountingType", + "base": "VnModel", + "options": { + "mysql": { + "table": "accountingType" + } + }, + "properties": { + "id": { + "type": "Number", + "id": true, + "description": "Identifier" + }, + "description": { + "type": "String", + "required": true + }, + "receiptDescription": { + "type": "String", + "required": true + } + }, + "acls": [{ + "accessType": "READ", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + }] +} \ No newline at end of file diff --git a/back/models/bank.json b/back/models/bank.json index 119ea9743..33a2637d6 100644 --- a/back/models/bank.json +++ b/back/models/bank.json @@ -2,39 +2,49 @@ "name": "Bank", "base": "VnModel", "options": { - "mysql": { - "table": "bank" - } + "mysql": { + "table": "bank" + } }, "properties": { - "id": { - "type": "Number", - "id": true, - "description": "Identifier" - }, - "bank": { - "type": "string", - "required": true - }, - "account": { - "type": "string", - "required": true - }, - "cash": { - "type": "string", - "required": true - }, - "entityFk": { - "type": "string", - "required": true - }, - "isActive": { - "type": "string", - "required": true - }, - "currencyFk": { - "type": "string", - "required": true - } + "id": { + "type": "Number", + "id": true, + "description": "Identifier" + }, + "bank": { + "type": "String", + "required": true + }, + "account": { + "type": "String", + "required": true + }, + "accountingTypeFk": { + "type": "Number", + "required": true, + "mysql": { + "columnName": "cash" + } + }, + "entityFk": { + "type": "Number", + "required": true + }, + "isActive": { + "type": "Boolean", + "required": true + }, + "currencyFk": { + "type": "Number", + "required": true + } + }, + "relations": { + "accountingType": { + "type": "belongsTo", + "model": "AccountingType", + "foreignKey": "accountingTypeFk" + } } - } \ No newline at end of file +} \ No newline at end of file diff --git a/db/changes/10210-summer/00-accountingType.sql b/db/changes/10210-summer/00-accountingType.sql new file mode 100644 index 000000000..1dbe29952 --- /dev/null +++ b/db/changes/10210-summer/00-accountingType.sql @@ -0,0 +1,2 @@ +ALTER TABLE `vn`.`accountingType` +ADD COLUMN `receiptDescription` VARCHAR(50) NULL AFTER `description`; diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 2b70cf2be..274d24139 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -116,13 +116,13 @@ INSERT INTO `vn`.`shelving` (`code`, `parkingFk`, `isPrinted`, `priority`, `park ('GVC', '1', '0', '1', '0', '106'), ('HEJ', '2', '0', '1', '0', '106'); -INSERT INTO `vn`.`accountingType`(`id`, `description`) +INSERT INTO `vn`.`accountingType`(`id`, `description`, `receiptDescription`) VALUES - (1, 'Digital money'), - (2, 'Cash'), - (3, 'Card'), - (4, 'Stolen Money'), - (5, 'Miscellaneous'); + (1, 'Digital money', ''), + (2, 'Cash', 'Cash'), + (3, 'Card', 'Pay on receipt'), + (4, 'Stolen Money', ''), + (5, 'Miscellaneous', ''); INSERT INTO `vn`.`currency`(`id`, `code`, `name`, `ratio`) VALUES @@ -133,8 +133,8 @@ INSERT INTO `vn`.`currency`(`id`, `code`, `name`, `ratio`) INSERT INTO `vn`.`bank`(`id`, `bank`, `account`, `cash`, `entityFk`, `isActive`, `currencyFk`) VALUES - (1, 'Pay on receipt', '0000000000', 4, 0, 1, 1), - (2, 'Cash', '1111111111', 1, 0, 1, 1); + (1, 'Pay on receipt', '0000000000', 3, 0, 1, 1), + (2, 'Cash', '1111111111', 2, 0, 1, 1); INSERT INTO `vn`.`deliveryMethod`(`id`, `code`, `description`) VALUES diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 6eca623bd..d93b72483 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -189,8 +189,9 @@ export default { newPaymentBank: '.vn-dialog.shown vn-autocomplete[ng-model="$ctrl.receipt.bankFk"]', newPaymentAmount: '.vn-dialog.shown vn-input-number[ng-model="$ctrl.receipt.amountPaid"]', saveButton: '.vn-dialog.shown [response="accept"]', - firstBalanceLine: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(8)' - + firstLineBalance: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(8)', + firstLineReference: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable', + firstLineReferenceInput: 'vn-client-balance-index vn-tbody > vn-tr:nth-child(1) > vn-td-editable > div > field > vn-textfield' }, webPayment: { confirmFirstPaymentButton: 'vn-client-web-payment vn-tr:nth-child(1) vn-icon-button[icon="done_all"]', diff --git a/e2e/paths/02-client/14_balance.spec.js b/e2e/paths/02-client/14_balance.spec.js index 108f76710..6c16d455d 100644 --- a/e2e/paths/02-client/14_balance.spec.js +++ b/e2e/paths/02-client/14_balance.spec.js @@ -53,15 +53,28 @@ describe('Client balance path', () => { expect(message.type).toBe('success'); }); - it('should check balance is now 0 and the company is now VNL becouse the user local settings were removed', async() => { + it('should edit the 1st line reference', async() => { + await page.waitToClick(selectors.clientBalance.firstLineReference); + await page.write(selectors.clientBalance.firstLineReferenceInput, 'Miscellaneous payment'); + await page.keyboard.press('Enter'); + const message = await page.waitForSnackbar(); + + expect(message.type).toBe('success'); + }); + + it('should check balance is now 0, the reference was saved and the company is now VNL becouse the user local settings were removed', async() => { await page.waitForSpinnerLoad(); let company = await page .waitToGetProperty(selectors.clientBalance.company, 'value'); + let reference = await page + .waitToGetProperty(selectors.clientBalance.firstLineReference, 'innerText'); + let firstBalanceLine = await page - .waitToGetProperty(selectors.clientBalance.firstBalanceLine, 'innerText'); + .waitToGetProperty(selectors.clientBalance.firstLineBalance, 'innerText'); expect(company).toEqual('VNL'); + expect(reference).toEqual('Miscellaneous payment'); expect(firstBalanceLine).toContain('0.00'); }); @@ -76,7 +89,7 @@ describe('Client balance path', () => { it('should check balance is now -100', async() => { let result = await page - .waitToGetProperty(selectors.clientBalance.firstBalanceLine, 'innerText'); + .waitToGetProperty(selectors.clientBalance.firstLineBalance, 'innerText'); expect(result).toContain('-€100.00'); }); @@ -92,7 +105,7 @@ describe('Client balance path', () => { it('should check balance is now 50', async() => { let result = await page - .waitToGetProperty(selectors.clientBalance.firstBalanceLine, 'innerText'); + .waitToGetProperty(selectors.clientBalance.firstLineBalance, 'innerText'); expect(result).toEqual('€50.00'); }); diff --git a/modules/client/back/methods/receipt/filter.js b/modules/client/back/methods/receipt/filter.js index 532d72811..b32249d4b 100644 --- a/modules/client/back/methods/receipt/filter.js +++ b/modules/client/back/methods/receipt/filter.js @@ -42,11 +42,11 @@ module.exports = Self => { r.workerFk, c.code company, r.created, - r.invoiceFk ref, + r.invoiceFk description, NULL debit, r.amountPaid credit, r.bankFk, - u.nickname userNickname, + u.name userName, r.clientFk, FALSE hasPdf, FALSE isInvoice diff --git a/modules/client/front/balance/create/index.html b/modules/client/front/balance/create/index.html index 506e86f4b..6cfdc0666 100644 --- a/modules/client/front/balance/create/index.html +++ b/modules/client/front/balance/create/index.html @@ -17,11 +17,17 @@ + fields="['accountingTypeFk']" + include="{relation: 'accountingType'}" + order="id" + ng-model="$ctrl.receipt.bankFk" + search-function="{or: [{id: $search}, {bank: {like: '%'+ $search +'%'}}]}" + selection="$ctrl.bankSelection"> + {{id}}: {{bank}} + + + + diff --git a/modules/client/front/balance/create/index.js b/modules/client/front/balance/create/index.js index 880774f55..8b01cab4a 100644 --- a/modules/client/front/balance/create/index.js +++ b/modules/client/front/balance/create/index.js @@ -50,6 +50,19 @@ class Controller extends Dialog { return this.receipt.description; } + get bankSelection() { + return this._bankSelection; + } + + set bankSelection(value) { + this._bankSelection = value; + + if (value) { + const accountingType = value.accountingType; + this.receipt.description = accountingType && accountingType.receiptDescription; + } + } + getAmountPaid() { const filter = { where: { diff --git a/modules/client/front/balance/create/index.spec.js b/modules/client/front/balance/create/index.spec.js new file mode 100644 index 000000000..11fdb1040 --- /dev/null +++ b/modules/client/front/balance/create/index.spec.js @@ -0,0 +1,76 @@ +import './index'; + +describe('Client', () => { + describe('Component vnClientBalancCreate', () => { + let controller; + let $httpBackend; + let $httpParamSerializer; + + beforeEach(ngModule('client')); + + beforeEach(inject(($componentController, $rootScope, _$httpBackend_, _$httpParamSerializer_) => { + $httpBackend = _$httpBackend_; + $httpParamSerializer = _$httpParamSerializer_; + let $scope = $rootScope.$new(); + const $element = angular.element(''); + const $transclude = { + $$boundTransclude: { + $$slots: [] + } + }; + controller = $componentController('vnClientBalanceCreate', {$element, $scope, $transclude}); + controller.receipt = { + clientFk: 101, + companyFk: 442 + }; + })); + + describe('bankSelection() setter', () => { + it('should set the receipt description property', () => { + controller.bankSelection = { + id: 1, + bank: 'Cash', + accountingType: { + id: 2, + receiptDescription: 'Cash' + } + }; + + expect(controller.receipt.description).toEqual('Cash'); + }); + }); + + describe('getAmountPaid()', () => { + it('should make an http GET query and then set the receipt amountPaid property', () => { + controller.$params = {id: 101}; + const receipt = controller.receipt; + const filter = { + where: { + clientFk: 101, + companyFk: 442 + } + }; + const serializedParams = $httpParamSerializer({filter}); + $httpBackend.expect('GET', `ClientRisks?${serializedParams}`,).respond([{amount: 20}]); + controller.getAmountPaid(); + $httpBackend.flush(); + + expect(receipt.amountPaid).toEqual(20); + }); + }); + + describe('responseHandler()', () => { + it('should make an http POST query and then call to the parent responseHandler() method', () => { + jest.spyOn(controller.vnApp, 'showSuccess'); + + controller.$params = {id: 101}; + + $httpBackend.expect('POST', `Receipts`,).respond({id: 1}); + controller.responseHandler('accept'); + $httpBackend.flush(); + + expect(controller.vnApp.showSuccess).toHaveBeenCalled(); + }); + }); + }); +}); diff --git a/modules/client/front/balance/index/index.html b/modules/client/front/balance/index/index.html index 1ad7efad9..cf0c07cfc 100644 --- a/modules/client/front/balance/index/index.html +++ b/modules/client/front/balance/index/index.html @@ -68,25 +68,33 @@ - {{::balance.userNickname}} + {{::balance.userName}} - -
- - {{'BILL' | translate: {ref: balance.ref} }} - - - {{::balance.ref}} - -
-
+ + +
+ + {{'BILL' | translate: {ref: balance.description} }} + + + {{balance.description}} + +
+
+ + + + +
{{::balance.bankFk}} {{::balance.debit | currency: 'EUR':2}} {{::balance.credit | currency: 'EUR':2}} diff --git a/modules/client/front/balance/index/index.js b/modules/client/front/balance/index/index.js index 8f5261176..7e09e018c 100644 --- a/modules/client/front/balance/index/index.js +++ b/modules/client/front/balance/index/index.js @@ -39,6 +39,10 @@ class Controller extends Section { this.getBalances(); } + get isAdministrative() { + return this.aclService.hasAny(['administrative']); + } + getData() { return this.$.model.applyFilter(null, { clientId: this.$params.id, @@ -58,7 +62,7 @@ class Controller extends Section { return balance.companyFk === selectedCompany; }); - return currentBalance.amount; + return currentBalance && currentBalance.amount; } getBalances() { @@ -79,6 +83,13 @@ class Controller extends Section { this.$.invoiceOutDescriptor.show(event.target, balance.id); } + + changeDescription(balance) { + const params = {description: balance.description}; + const endpoint = `Receipts/${balance.id}`; + this.$http.patch(endpoint, params) + .then(() => this.vnApp.showSuccess(this.$t('Data saved!'))); + } } Controller.$inject = ['$element', '$scope']; diff --git a/modules/client/front/balance/index/index.spec.js b/modules/client/front/balance/index/index.spec.js index 496407847..bdbea3846 100644 --- a/modules/client/front/balance/index/index.spec.js +++ b/modules/client/front/balance/index/index.spec.js @@ -3,10 +3,12 @@ import './index'; describe('Client', () => { describe('Component vnClientBalanceIndex', () => { let controller; + let $httpBackend; beforeEach(ngModule('client')); - beforeEach(inject(($componentController, $rootScope) => { + beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => { + $httpBackend = _$httpBackend_; let $scope = $rootScope.$new(); const $element = angular.element(''); controller = $componentController('vnClientBalanceIndex', {$element, $scope}); @@ -133,5 +135,21 @@ describe('Client', () => { expect(controller.getBalances).toHaveBeenCalledWith(); }); }); + + describe('changeDescription()', () => { + it('should make an http PATCH query', () => { + const expectedParams = {description: 'Web'}; + + $httpBackend.expect('PATCH', `Receipts/1`, expectedParams).respond(200); + controller.changeDescription({ + id: 1, + description: 'Web', + accountingType: { + description: 'Cash' + } + }); + $httpBackend.flush(); + }); + }); }); });