From 2455a24b68b916b2a8d841ef60a5e5d68c4fb3c6 Mon Sep 17 00:00:00 2001 From: alexm Date: Tue, 25 Jan 2022 14:27:30 +0100 Subject: [PATCH 1/4] feat(client_defaulter): section and test --- db/dump/fixtures.sql | 10 +- e2e/helpers/selectors.js | 10 ++ e2e/paths/02-client/21_defaulter.spec.js | 73 ++++++++ .../client/back/methods/defaulter/filter.js | 87 +++++++++ .../methods/defaulter/specs/filter.spec.js | 63 +++++++ modules/client/back/models/defaulter.js | 3 + modules/client/back/models/defaulter.json | 3 + modules/client/front/defaulter/index.html | 169 ++++++++++++++++++ modules/client/front/defaulter/index.js | 62 +++++++ modules/client/front/defaulter/index.spec.js | 88 +++++++++ modules/client/front/defaulter/locale/es.yml | 5 + modules/client/front/index.js | 1 + modules/client/front/locale/es.yml | 1 + modules/client/front/routes.json | 15 +- 14 files changed, 588 insertions(+), 2 deletions(-) create mode 100644 e2e/paths/02-client/21_defaulter.spec.js create mode 100644 modules/client/back/methods/defaulter/filter.js create mode 100644 modules/client/back/methods/defaulter/specs/filter.spec.js create mode 100644 modules/client/back/models/defaulter.js create mode 100644 modules/client/front/defaulter/index.html create mode 100644 modules/client/front/defaulter/index.js create mode 100644 modules/client/front/defaulter/index.spec.js create mode 100644 modules/client/front/defaulter/locale/es.yml diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index efe7906ce9..83ba899376 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -2432,4 +2432,12 @@ INSERT INTO `vn`.`expeditionScan` (`id`, `expeditionFk`, `scanned`, `palletFk`) CALL `cache`.`last_buy_refresh`(FALSE); UPDATE `vn`.`item` SET `genericFk` = 9 - WHERE `id` = 2; \ No newline at end of file + WHERE `id` = 2; + +INSERT INTO `bs`.`defaulter` (`clientFk`, `amount`, `created`, `defaulterSinced`) + VALUES + (1101, 500, CURDATE(), CURDATE()), + (1102, 500, CURDATE(), CURDATE()), + (1103, 500, CURDATE(), CURDATE()), + (1107, 500, CURDATE(), CURDATE()), + (1109, 500, CURDATE(), CURDATE()); diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 2900a285ba..0172ca4e03 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -304,6 +304,16 @@ export default { saveNewInsuranceCredit: 'vn-client-credit-insurance-insurance-create button[type="submit"]', anyCreditInsuranceLine: 'vn-client-credit-insurance-insurance-index vn-tbody > vn-tr', }, + clientDefaulter: { + anyClient: 'vn-client-defaulter-index vn-tbody > vn-tr', + firstClientName: 'vn-client-defaulter-index vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(2) > span', + firstSalesPersonName: 'vn-client-defaulter-index vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(3) > span', + firstObservation: 'vn-client-defaulter-index vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(5) > vn-textarea[ng-model="defaulter.observation"]', + allDefaulterCheckbox: 'vn-client-defaulter-index vn-thead vn-multi-check', + addObservationButton: 'vn-client-defaulter-index vn-button[icon="icon-notes"]', + observation: '.vn-dialog.shown vn-textarea[ng-model="$ctrl.defaulter.observation"]', + saveButton: 'button[response="accept"]' + }, clientContacts: { addContactButton: 'vn-client-contact vn-icon[icon="add_circle"]', name: 'vn-client-contact vn-textfield[ng-model="contact.name"]', diff --git a/e2e/paths/02-client/21_defaulter.spec.js b/e2e/paths/02-client/21_defaulter.spec.js new file mode 100644 index 0000000000..406c802ab1 --- /dev/null +++ b/e2e/paths/02-client/21_defaulter.spec.js @@ -0,0 +1,73 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('Client defaulter path', () => { + let browser; + let page; + + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('insurance', 'client'); + await page.accessToSection('client.defaulter.index'); + }); + + afterAll(async() => { + await browser.close(); + }); + + it('should count the amount of clients in the turns section', async() => { + const result = await page.countElement(selectors.clientDefaulter.anyClient); + + expect(result).toEqual(5); + }); + + it('should check contain expected client', async() => { + const clientName = + await page.waitToGetProperty(selectors.clientDefaulter.firstClientName, 'innerText'); + const salesPersonName = + await page.waitToGetProperty(selectors.clientDefaulter.firstSalesPersonName, 'innerText'); + + expect(clientName).toEqual('Ororo Munroe'); + expect(salesPersonName).toEqual('salesPerson'); + }); + + it('should first observation not changed', async() => { + const expectedObservation = 'Madness, as you know, is like gravity, all it takes is a little push'; + const result = await page.waitToGetProperty(selectors.clientDefaulter.firstObservation, 'value'); + + expect(result).toEqual(expectedObservation); + }); + + it('should not add empty observation', async() => { + await page.waitToClick(selectors.clientDefaulter.allDefaulterCheckbox); + + await page.waitToClick(selectors.clientDefaulter.addObservationButton); + await page.write(selectors.clientDefaulter.observation, ''); + await page.waitToClick(selectors.clientDefaulter.saveButton); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain(`The message can't be empty`); + }); + + it('shoul checked all defaulters', async() => { + await page.loginAndModule('insurance', 'client'); + await page.accessToSection('client.defaulter.index'); + + await page.waitToClick(selectors.clientDefaulter.allDefaulterCheckbox); + }); + + it('should add observation for all clients', async() => { + await page.waitToClick(selectors.clientDefaulter.addObservationButton); + await page.write(selectors.clientDefaulter.observation, 'My new observation'); + await page.waitToClick(selectors.clientDefaulter.saveButton); + }); + + it('should first observation changed', async() => { + const result = await page.waitToGetProperty(selectors.clientDefaulter.firstObservation, 'value'); + const message = await page.waitForSnackbar(); + + expect(message.text).toContain('Observation saved!'); + expect(result).toEqual('My new observation'); + }); +}); diff --git a/modules/client/back/methods/defaulter/filter.js b/modules/client/back/methods/defaulter/filter.js new file mode 100644 index 0000000000..95e75040eb --- /dev/null +++ b/modules/client/back/methods/defaulter/filter.js @@ -0,0 +1,87 @@ + +const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; +const buildFilter = require('vn-loopback/util/filter').buildFilter; +const mergeFilters = require('vn-loopback/util/filter').mergeFilters; + +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'} + }, + { + arg: 'search', + type: 'string', + description: `If it's and integer searchs by id, otherwise it searchs by name` + } + ], + 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 where = buildFilter(ctx.args, (param, value) => { + switch (param) { + case 'search': + return {or: [ + {'d.clientFk': value}, + {'d.clientName': {like: `%${value}%`}} + ]}; + } + }); + + filter = mergeFilters(ctx.args.filter, {where}); + + const stmts = []; + + const stmt = new ParameterizedSQL( + `SELECT * + FROM ( + SELECT + DISTINCT c.id clientFk, + c.name clientName, + c.salesPersonFk, + u.name salesPersonName, + d.amount, + co.created, + co.text observation, + c.creditInsurance, + d.defaulterSinced + FROM vn.defaulter d + JOIN vn.client c ON c.id = d.clientFk + LEFT JOIN vn.clientObservation co ON co.clientFk = c.id + LEFT JOIN account.user u ON u.id = c.salesPersonFk + WHERE + d.created = CURDATE() + AND d.amount > 0 + ORDER BY co.created DESC) d` + ); + + stmt.merge(conn.makeWhere(filter.where)); + stmt.merge(`GROUP BY d.clientFk`); + stmt.merge(conn.makeOrderBy(filter.order)); + + const itemsIndex = stmts.push(stmt) - 1; + const sql = ParameterizedSQL.join(stmts, ';'); + const result = await conn.executeStmt(sql, myOptions); + + return itemsIndex === 0 ? result : result[itemsIndex]; + }; +}; diff --git a/modules/client/back/methods/defaulter/specs/filter.spec.js b/modules/client/back/methods/defaulter/specs/filter.spec.js new file mode 100644 index 0000000000..145bb51321 --- /dev/null +++ b/modules/client/back/methods/defaulter/specs/filter.spec.js @@ -0,0 +1,63 @@ +const models = require('vn-loopback/server/server').models; + +describe('defaulter filter()', () => { + const authUserId = 9; + it('should all return the tickets matching the filter', async() => { + const tx = await models.Defaulter.beginTransaction({}); + + try { + const options = {transaction: tx}; + const filter = {}; + const ctx = {req: {accessToken: {userId: authUserId}}, args: {filter: filter}}; + + const result = await models.Defaulter.filter(ctx, null, options); + const firstRow = result[0]; + + expect(firstRow.clientFk).toEqual(1101); + expect(result.length).toEqual(5); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should return the defaulter with id', async() => { + const tx = await models.Defaulter.beginTransaction({}); + + try { + const options = {transaction: tx}; + const ctx = {req: {accessToken: {userId: authUserId}}, args: {search: 1101}}; + + const result = await models.Defaulter.filter(ctx, null, options); + const firstRow = result[0]; + + expect(firstRow.clientFk).toEqual(1101); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should return the defaulter matching the client name', async() => { + const tx = await models.Defaulter.beginTransaction({}); + + try { + const options = {transaction: tx}; + const ctx = {req: {accessToken: {userId: authUserId}}, args: {search: 'bruce'}}; + + const result = await models.Defaulter.filter(ctx, null, options); + const firstRow = result[0]; + + expect(firstRow.clientName).toEqual('Bruce Wayne'); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); +}); diff --git a/modules/client/back/models/defaulter.js b/modules/client/back/models/defaulter.js new file mode 100644 index 0000000000..13bb1a6146 --- /dev/null +++ b/modules/client/back/models/defaulter.js @@ -0,0 +1,3 @@ +module.exports = Self => { + require('../methods/defaulter/filter')(Self); +}; diff --git a/modules/client/back/models/defaulter.json b/modules/client/back/models/defaulter.json index 8d50356f17..8293264359 100644 --- a/modules/client/back/models/defaulter.json +++ b/modules/client/back/models/defaulter.json @@ -8,6 +8,9 @@ } }, "properties": { + "id": { + "type": "Number" + }, "created": { "type": "Date" }, diff --git a/modules/client/front/defaulter/index.html b/modules/client/front/defaulter/index.html new file mode 100644 index 0000000000..6ab52dd4f7 --- /dev/null +++ b/modules/client/front/defaulter/index.html @@ -0,0 +1,169 @@ + + + + + + + +
+
+
Balance due
+ + +
+
+
+ + + + + + + + + + + + + + + + Client + Comercial + Credit + Last observation + Credit insurance + From + + + + + + + + + + + {{::defaulter.clientName}} + + + + + {{::defaulter.salesPersonName | dashIfEmpty}} + + + {{::defaulter.amount}} + + + + + {{::defaulter.creditInsurance}} + {{::defaulter.defaulterSinced | date: 'dd/MM/yyyy'}} + + + + + + + + + + + + + + + + + + + Filter by selection + + + Exclude selection + + + Remove filter + + + Remove all filters + + + Copy value + + + + + + + +
+
{{$ctrl.$t('Add observation to all selected clients', {total: $ctrl.checked.length})}}
+ + + + +
+
+ + + + +
diff --git a/modules/client/front/defaulter/index.js b/modules/client/front/defaulter/index.js new file mode 100644 index 0000000000..0cb029992d --- /dev/null +++ b/modules/client/front/defaulter/index.js @@ -0,0 +1,62 @@ +import ngModule from '../module'; +import Section from 'salix/components/section'; +import UserError from 'core/lib/user-error'; + +export default class Controller extends Section { + constructor($element, $) { + super($element, $); + this.defaulter = {}; + } + + get balanceDueTotal() { + let balanceDueTotal = 0; + + if (this.checked.length > 0) { + for (let defaulter of this.checked) + balanceDueTotal += defaulter.amount; + + return balanceDueTotal; + } + + return balanceDueTotal; + } + + get checked() { + const clients = this.$.model.data || []; + const checkedLines = []; + for (let defaulter of clients) { + if (defaulter.checked) + checkedLines.push(defaulter); + } + + return checkedLines; + } + + onResponse() { + if (!this.defaulter.observation) + throw new UserError(`The message can't be empty`); + + for (let defaulter of this.checked) { + const params = { + text: this.defaulter.observation, + clientFk: defaulter.clientFk + }; + this.$http.post(`ClientObservations`, params); + } + this.vnApp.showMessage(this.$t('Observation saved!')); + this.$state.reload(); + } + + exprBuilder(param, value) { + switch (param) { + case 'clientName': + case 'salesPersonFk': + return {[`d.${param}`]: value}; + } + } +} + +ngModule.vnComponent('vnClientDefaulterIndex', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/client/front/defaulter/index.spec.js b/modules/client/front/defaulter/index.spec.js new file mode 100644 index 0000000000..e0e7589062 --- /dev/null +++ b/modules/client/front/defaulter/index.spec.js @@ -0,0 +1,88 @@ +import './index'; +import crudModel from 'core/mocks/crud-model'; + +describe('client defaulter', () => { + describe('Component vnClientDefaulterIndex', () => { + let controller; + + beforeEach(ngModule('client')); + + beforeEach(inject($componentController => { + const $element = angular.element(''); + controller = $componentController('vnClientDefaulterIndex', {$element}); + controller.$.model = crudModel; + controller.$.model.data = [ + {clientFk: 1101, amount: 125}, + {clientFk: 1102, amount: 500}, + {clientFk: 1103, amount: 250} + ]; + })); + + describe('checked() getter', () => { + it('should return the checked lines', () => { + const data = controller.$.model.data; + data[1].checked = true; + data[2].checked = true; + + const checkedRows = controller.checked; + + const firstCheckedRow = checkedRows[0]; + const secondCheckedRow = checkedRows[1]; + + expect(firstCheckedRow.clientFk).toEqual(1102); + expect(secondCheckedRow.clientFk).toEqual(1103); + }); + }); + + describe('balanceDueTotal() getter', () => { + it('should return balance due total', () => { + const data = controller.$.model.data; + data[1].checked = true; + data[2].checked = true; + + const checkedRows = controller.checked; + const expectedAmount = checkedRows[0].amount + checkedRows[1].amount; + + const result = controller.balanceDueTotal; + + expect(result).toEqual(expectedAmount); + }); + }); + + describe('onResponse()', () => { + it('should return error for empty message', () => { + let error; + try { + controller.onResponse(); + } catch (e) { + error = e; + } + + expect(error).toBeDefined(); + expect(error.message).toBe(`The message can't be empty`); + }); + + it('should return saved message', () => { + controller.defaulter = {observation: 'asdasd'}; + jest.spyOn(controller.vnApp, 'showMessage'); + controller.onResponse(); + + expect(controller.vnApp.showMessage).toHaveBeenCalledWith('Observation saved!'); + }); + }); + + describe('exprBuilder()', () => { + it('should search by sales person', () => { + let expr = controller.exprBuilder('salesPersonFk', '5'); + + expect(expr).toEqual({'d.salesPersonFk': '5'}); + }); + + it('should search by client name', () => { + let expr = controller.exprBuilder('clientName', '1foo'); + + expect(expr).toEqual({'d.clientName': '1foo'}); + }); + }); + }); +}); diff --git a/modules/client/front/defaulter/locale/es.yml b/modules/client/front/defaulter/locale/es.yml new file mode 100644 index 0000000000..95184d06d8 --- /dev/null +++ b/modules/client/front/defaulter/locale/es.yml @@ -0,0 +1,5 @@ +Last observation: Última observación +Add observation: Añadir observación +Balance due total: Saldo vencido total +Search client: Buscar clientes +Add observation to all selected clients: Añadir observación a {{total}} cliente(s) seleccionado(s) \ No newline at end of file diff --git a/modules/client/front/index.js b/modules/client/front/index.js index 758b94e3f5..6b35d392a3 100644 --- a/modules/client/front/index.js +++ b/modules/client/front/index.js @@ -44,3 +44,4 @@ import './dms/create'; import './dms/edit'; import './consumption'; import './consumption-search-panel'; +import './defaulter'; diff --git a/modules/client/front/locale/es.yml b/modules/client/front/locale/es.yml index 1a5a570a7f..107931377a 100644 --- a/modules/client/front/locale/es.yml +++ b/modules/client/front/locale/es.yml @@ -33,6 +33,7 @@ Search client by id or name: Buscar clientes por identificador o nombre # Sections Clients: Clientes +Defaulter: Morosos New client: Nuevo cliente Fiscal data: Datos fiscales Billing data: Forma de pago diff --git a/modules/client/front/routes.json b/modules/client/front/routes.json index 765fbc6371..31a699e55c 100644 --- a/modules/client/front/routes.json +++ b/modules/client/front/routes.json @@ -6,7 +6,8 @@ "dependencies": ["worker", "invoiceOut"], "menus": { "main": [ - {"state": "client.index", "icon": "person"} + {"state": "client.index", "icon": "person"}, + {"state": "client.defaulter.index", "icon": "person"} ], "card": [ {"state": "client.card.basicData", "icon": "settings"}, @@ -360,6 +361,18 @@ "params": { "client": "$ctrl.client" } + }, + { + "url": "/defaulter", + "state": "client.defaulter", + "component": "ui-view", + "description": "Defaulter" + }, + { + "url": "/index?q", + "state": "client.defaulter.index", + "component": "vn-client-defaulter-index", + "description": "Defaulter" } ] } From 5970a6dfde331c525741dd4d32645bd7e26d2cac Mon Sep 17 00:00:00 2001 From: alexm Date: Wed, 26 Jan 2022 14:05:33 +0100 Subject: [PATCH 2/4] refactor(client_defaulter): title of columns --- .../client/back/methods/defaulter/filter.js | 2 ++ modules/client/front/defaulter/index.html | 22 +++++++++++-------- modules/client/front/defaulter/locale/es.yml | 5 +++-- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/modules/client/back/methods/defaulter/filter.js b/modules/client/back/methods/defaulter/filter.js index 95e75040eb..15a56fb63a 100644 --- a/modules/client/back/methods/defaulter/filter.js +++ b/modules/client/back/methods/defaulter/filter.js @@ -62,12 +62,14 @@ module.exports = Self => { d.amount, co.created, co.text observation, + uw.name workerName, c.creditInsurance, d.defaulterSinced FROM vn.defaulter d JOIN vn.client c ON c.id = d.clientFk LEFT JOIN vn.clientObservation co ON co.clientFk = c.id LEFT JOIN account.user u ON u.id = c.salesPersonFk + LEFT JOIN account.user uw ON uw.id = co.workerFk WHERE d.created = CURDATE() AND d.amount > 0 diff --git a/modules/client/front/defaulter/index.html b/modules/client/front/defaulter/index.html index 6ab52dd4f7..ed50ebad9c 100644 --- a/modules/client/front/defaulter/index.html +++ b/modules/client/front/defaulter/index.html @@ -18,9 +18,9 @@
-
Balance due
+
Total
@@ -51,17 +51,21 @@ Client Comercial - Credit + + Balance D + Last observation - Credit insurance + + Credit I + From - + diff --git a/modules/client/front/defaulter/locale/es.yml b/modules/client/front/defaulter/locale/es.yml index 95184d06d8..d0cca6e2ac 100644 --- a/modules/client/front/defaulter/locale/es.yml +++ b/modules/client/front/defaulter/locale/es.yml @@ -1,5 +1,6 @@ Last observation: Última observación Add observation: Añadir observación -Balance due total: Saldo vencido total Search client: Buscar clientes -Add observation to all selected clients: Añadir observación a {{total}} cliente(s) seleccionado(s) \ No newline at end of file +Add observation to all selected clients: Añadir observación a {{total}} cliente(s) seleccionado(s) +Credit I: Crédito A +Balance D: Saldo V \ No newline at end of file From 746cbede4bb37c0c4ca28c0f27a81373e1f617a0 Mon Sep 17 00:00:00 2001 From: alexm Date: Mon, 31 Jan 2022 08:17:15 +0100 Subject: [PATCH 3/4] feat(client_defaulter): move tool-bar up , add column author --- e2e/helpers/selectors.js | 2 +- e2e/paths/02-client/21_defaulter.spec.js | 4 +- .../client/back/methods/defaulter/filter.js | 3 +- modules/client/front/defaulter/index.html | 61 +++++++++++-------- modules/client/front/defaulter/locale/es.yml | 5 +- 5 files changed, 45 insertions(+), 30 deletions(-) diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 0172ca4e03..e757ca3859 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -308,7 +308,7 @@ export default { anyClient: 'vn-client-defaulter-index vn-tbody > vn-tr', firstClientName: 'vn-client-defaulter-index vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(2) > span', firstSalesPersonName: 'vn-client-defaulter-index vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(3) > span', - firstObservation: 'vn-client-defaulter-index vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(5) > vn-textarea[ng-model="defaulter.observation"]', + firstObservation: 'vn-client-defaulter-index vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(6) > vn-textarea[ng-model="defaulter.observation"]', allDefaulterCheckbox: 'vn-client-defaulter-index vn-thead vn-multi-check', addObservationButton: 'vn-client-defaulter-index vn-button[icon="icon-notes"]', observation: '.vn-dialog.shown vn-textarea[ng-model="$ctrl.defaulter.observation"]', diff --git a/e2e/paths/02-client/21_defaulter.spec.js b/e2e/paths/02-client/21_defaulter.spec.js index 406c802ab1..1d5fc8efb7 100644 --- a/e2e/paths/02-client/21_defaulter.spec.js +++ b/e2e/paths/02-client/21_defaulter.spec.js @@ -36,7 +36,7 @@ describe('Client defaulter path', () => { const expectedObservation = 'Madness, as you know, is like gravity, all it takes is a little push'; const result = await page.waitToGetProperty(selectors.clientDefaulter.firstObservation, 'value'); - expect(result).toEqual(expectedObservation); + expect(result).toContain(expectedObservation); }); it('should not add empty observation', async() => { @@ -68,6 +68,6 @@ describe('Client defaulter path', () => { const message = await page.waitForSnackbar(); expect(message.text).toContain('Observation saved!'); - expect(result).toEqual('My new observation'); + expect(result).toContain('My new observation'); }); }); diff --git a/modules/client/back/methods/defaulter/filter.js b/modules/client/back/methods/defaulter/filter.js index 15a56fb63a..c06d1c51b2 100644 --- a/modules/client/back/methods/defaulter/filter.js +++ b/modules/client/back/methods/defaulter/filter.js @@ -61,7 +61,8 @@ module.exports = Self => { u.name salesPersonName, d.amount, co.created, - co.text observation, + CONCAT(DATE(co.created), ' ', co.text) observation, + uw.id workerFk, uw.name workerName, c.creditInsurance, d.defaulterSinced diff --git a/modules/client/front/defaulter/index.html b/modules/client/front/defaulter/index.html index ed50ebad9c..121556df24 100644 --- a/modules/client/front/defaulter/index.html +++ b/modules/client/front/defaulter/index.html @@ -15,23 +15,21 @@ model="model"> - -
-
-
Total
- - -
-
-
+ class="vn-w-xl"> - - + +
+
+
Total
+ + +
+
+
- - +
+
@@ -53,20 +51,27 @@ Comercial - Balance D + vn-tooltip="Balance due" + number> + Balance D. - Last observation - Credit I + vn-tooltip="Worker who made the last observation" + shrink> + Author - From + Last observation + + Credit I. + + From - + @@ -89,11 +94,19 @@ {{::defaulter.amount}} + + + {{::defaulter.workerName | dashIfEmpty}} + + diff --git a/modules/client/front/defaulter/locale/es.yml b/modules/client/front/defaulter/locale/es.yml index d0cca6e2ac..172a3125dc 100644 --- a/modules/client/front/defaulter/locale/es.yml +++ b/modules/client/front/defaulter/locale/es.yml @@ -2,5 +2,6 @@ Last observation: Última observación Add observation: Añadir observación Search client: Buscar clientes Add observation to all selected clients: Añadir observación a {{total}} cliente(s) seleccionado(s) -Credit I: Crédito A -Balance D: Saldo V \ No newline at end of file +Credit I.: Crédito A. +Balance D.: Saldo V. +Worker who made the last observation: Trabajador que ha realizado la última observación \ No newline at end of file From 368498d7639d3650a45817eeab6761ec3d7a1d70 Mon Sep 17 00:00:00 2001 From: alexm Date: Tue, 1 Feb 2022 08:49:56 +0100 Subject: [PATCH 4/4] refactor(defaulter): array request --- e2e/paths/02-client/21_defaulter.spec.js | 2 +- modules/client/front/defaulter/index.js | 13 ++++++++----- modules/client/front/defaulter/index.spec.js | 14 ++++++++++++-- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/e2e/paths/02-client/21_defaulter.spec.js b/e2e/paths/02-client/21_defaulter.spec.js index 1d5fc8efb7..89b5c5761d 100644 --- a/e2e/paths/02-client/21_defaulter.spec.js +++ b/e2e/paths/02-client/21_defaulter.spec.js @@ -64,8 +64,8 @@ describe('Client defaulter path', () => { }); it('should first observation changed', async() => { - const result = await page.waitToGetProperty(selectors.clientDefaulter.firstObservation, 'value'); const message = await page.waitForSnackbar(); + const result = await page.waitToGetProperty(selectors.clientDefaulter.firstObservation, 'value'); expect(message.text).toContain('Observation saved!'); expect(result).toContain('My new observation'); diff --git a/modules/client/front/defaulter/index.js b/modules/client/front/defaulter/index.js index 0cb029992d..76afeb1605 100644 --- a/modules/client/front/defaulter/index.js +++ b/modules/client/front/defaulter/index.js @@ -36,15 +36,18 @@ export default class Controller extends Section { if (!this.defaulter.observation) throw new UserError(`The message can't be empty`); + const params = []; for (let defaulter of this.checked) { - const params = { + params.push({ text: this.defaulter.observation, clientFk: defaulter.clientFk - }; - this.$http.post(`ClientObservations`, params); + }); } - this.vnApp.showMessage(this.$t('Observation saved!')); - this.$state.reload(); + + this.$http.post(`ClientObservations`, params) .then(() => { + this.vnApp.showMessage(this.$t('Observation saved!')); + this.$state.reload(); + }); } exprBuilder(param, value) { diff --git a/modules/client/front/defaulter/index.spec.js b/modules/client/front/defaulter/index.spec.js index e0e7589062..6428952ec6 100644 --- a/modules/client/front/defaulter/index.spec.js +++ b/modules/client/front/defaulter/index.spec.js @@ -4,10 +4,12 @@ import crudModel from 'core/mocks/crud-model'; describe('client defaulter', () => { describe('Component vnClientDefaulterIndex', () => { let controller; + let $httpBackend; beforeEach(ngModule('client')); - beforeEach(inject($componentController => { + beforeEach(inject(($componentController, _$httpBackend_) => { + $httpBackend = _$httpBackend_; const $element = angular.element(''); controller = $componentController('vnClientDefaulterIndex', {$element}); controller.$.model = crudModel; @@ -63,9 +65,17 @@ describe('client defaulter', () => { }); it('should return saved message', () => { - controller.defaulter = {observation: 'asdasd'}; + const data = controller.$.model.data; + data[1].checked = true; + controller.defaulter = {observation: 'My new observation'}; + + const params = [{text: controller.defaulter.observation, clientFk: data[1].clientFk}]; + jest.spyOn(controller.vnApp, 'showMessage'); + $httpBackend.expect('POST', `ClientObservations`, params).respond(200, params); + controller.onResponse(); + $httpBackend.flush(); expect(controller.vnApp.showMessage).toHaveBeenCalledWith('Observation saved!'); });