From d03ca01b73f2899c80a14972bd7de43794d5df5e Mon Sep 17 00:00:00 2001 From: vicent Date: Tue, 11 Apr 2023 14:57:56 +0200 Subject: [PATCH] =?UTF-8?q?refs=20#5128=20a=C3=B1adida=20subseccion=20"Ges?= =?UTF-8?q?ti=C3=B3n=20de=20cr=C3=A9dito"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db/changes/231401/00-aclClientInforma.sql | 3 + db/changes/231401/00-clientInforma.sql | 16 ++ modules/client/back/model-config.json | 3 + .../client/back/models/client-informa.json | 42 +++++ modules/client/back/models/client.js | 56 ++++++- modules/client/back/models/client.json | 8 +- .../client/front/credit-management/index.html | 91 +++++++++++ .../client/front/credit-management/index.js | 32 ++++ .../front/credit-management/index.spec.js | 38 +++++ .../front/credit-management/locale/es.yml | 2 + modules/client/front/index.js | 2 + modules/client/front/locale/es.yml | 1 + modules/client/front/routes.json | 13 +- modules/client/front/summary/index.html | 145 ++++++++++-------- modules/client/front/summary/locale/es.yml | 3 + 15 files changed, 383 insertions(+), 72 deletions(-) create mode 100644 db/changes/231401/00-aclClientInforma.sql create mode 100644 db/changes/231401/00-clientInforma.sql create mode 100644 modules/client/back/models/client-informa.json create mode 100644 modules/client/front/credit-management/index.html create mode 100644 modules/client/front/credit-management/index.js create mode 100644 modules/client/front/credit-management/index.spec.js create mode 100644 modules/client/front/credit-management/locale/es.yml diff --git a/db/changes/231401/00-aclClientInforma.sql b/db/changes/231401/00-aclClientInforma.sql new file mode 100644 index 000000000..6222d2632 --- /dev/null +++ b/db/changes/231401/00-aclClientInforma.sql @@ -0,0 +1,3 @@ +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) +VALUES ('ClientInforma', '*', 'READ', 'ALLOW', 'ROLE', 'employee'), + ('ClientInforma', '*', 'WRITE', 'ALLOW', 'ROLE', 'financial'); diff --git a/db/changes/231401/00-clientInforma.sql b/db/changes/231401/00-clientInforma.sql new file mode 100644 index 000000000..25405ef4d --- /dev/null +++ b/db/changes/231401/00-clientInforma.sql @@ -0,0 +1,16 @@ +ALTER TABLE `vn`.`client` ADD rating INT UNSIGNED DEFAULT NULL NULL COMMENT 'información proporcionada por Informa'; +ALTER TABLE `vn`.`client` ADD recommendedCredit INT UNSIGNED DEFAULT NULL NULL COMMENT 'información proporcionada por Informa'; + +CREATE TABLE `vn`.`clientInforma` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `clientFk` int(11) NOT NULL, + `rating` int(10) unsigned DEFAULT NULL, + `recommendedCredit` int(10) unsigned DEFAULT NULL, + `workerFk` int(10) unsigned NOT NULL, + `created` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`id`), + KEY `informaWorkers_fk_idx` (`workerFk`), + KEY `informaClientFk` (`clientFk`), + CONSTRAINT `informa_ClienteFk` FOREIGN KEY (`clientFk`) REFERENCES `client` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `informa_workers_fk` FOREIGN KEY (`workerFk`) REFERENCES `worker` (`id`) ON DELETE RESTRICT ON UPDATE CASCADE +) ENGINE=InnoDB CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; diff --git a/modules/client/back/model-config.json b/modules/client/back/model-config.json index b466aa5a1..1e06ea1c0 100644 --- a/modules/client/back/model-config.json +++ b/modules/client/back/model-config.json @@ -32,6 +32,9 @@ "ClientConsumptionQueue": { "dataSource": "vn" }, + "ClientInforma": { + "dataSource": "vn" + }, "ClientLog": { "dataSource": "vn" }, diff --git a/modules/client/back/models/client-informa.json b/modules/client/back/models/client-informa.json new file mode 100644 index 000000000..0c652484e --- /dev/null +++ b/modules/client/back/models/client-informa.json @@ -0,0 +1,42 @@ +{ + "name": "ClientInforma", + "base": "Loggable", + "log": { + "model":"ClientLog", + "relation": "client", + "showField": "clientFk" + }, + "options": { + "mysql": { + "table": "clientInforma" + } + }, + "properties": { + "id": { + "type": "number", + "id": true, + "description": "Identifier" + }, + "rating": { + "type": "number" + }, + "recommendedCredit": { + "type": "number" + }, + "created": { + "type": "date" + } + }, + "relations": { + "worker": { + "type": "belongsTo", + "model": "Worker", + "foreignKey": "workerFk" + }, + "client": { + "type": "belongsTo", + "model": "Client", + "foreignKey": "clientFk" + } + } +} diff --git a/modules/client/back/models/client.js b/modules/client/back/models/client.js index c41085b79..579c6a8d4 100644 --- a/modules/client/back/models/client.js +++ b/modules/client/back/models/client.js @@ -280,6 +280,10 @@ module.exports = Self => { if (changes.credit !== undefined) await Self.changeCredit(ctx, finalState, changes); + // Credit management changes + if (orgData.rating != changes.rating || orgData.recommendedCredit != changes.recommendedCredit) + await Self.changeCreditManagement(ctx, finalState, changes); + const oldInstance = {}; if (!ctx.isNewInstance) { const newProps = Object.keys(changes); @@ -441,6 +445,55 @@ module.exports = Self => { }, ctx.options); }; + Self.changeCreditManagement = async function changeCreditManagement(ctx, finalState, changes) { + const models = Self.app.models; + const userId = ctx.options.accessToken.userId; + + // const isFinancialBoss = await models.Account.hasRole(userId, 'financialBoss', ctx.options); + // if (!isFinancialBoss) { + // const lastCredit = await models.ClientCredit.findOne({ + // where: { + // clientFk: finalState.id + // }, + // order: 'id DESC' + // }, ctx.options); + + // const lastAmount = lastCredit && lastCredit.amount; + // const lastWorkerId = lastCredit && lastCredit.workerFk; + // const lastWorkerIsFinancialBoss = await models.Account.hasRole(lastWorkerId, 'financialBoss', ctx.options); + + // if (lastAmount == 0 && lastWorkerIsFinancialBoss) + // throw new UserError(`You can't change the credit set to zero from a financialBoss`); + + // const creditLimits = await models.ClientCreditLimit.find({ + // fields: ['roleFk'], + // where: { + // maxAmount: {gte: changes.credit} + // } + // }, ctx.options); + + // const requiredRoles = []; + // for (limit of creditLimits) + // requiredRoles.push(limit.roleFk); + + // const userRequiredRoles = await models.RoleMapping.count({ + // roleId: {inq: requiredRoles}, + // principalType: 'USER', + // principalId: userId + // }, ctx.options); + + // if (userRequiredRoles <= 0) + // throw new UserError(`You don't have enough privileges to set this credit amount`); + // } + + await models.ClientInforma.create({ + clientFk: finalState.id, + rating: changes.rating, + recommendedCredit: changes.recommendedCredit, + workerFk: userId + }, ctx.options); + }; + const app = require('vn-loopback/server/server'); app.on('started', function() { const account = app.models.Account; @@ -474,7 +527,8 @@ module.exports = Self => { oldInstance: {name: oldData.name, active: oldData.active}, newInstance: {name: changes.name, active: changes.active} }; - await Self.app.models.ClientLog.create(logRecord); + console.log(logRecord); + // await Self.app.models.ClientLog.create(logRecord); } } }); diff --git a/modules/client/back/models/client.json b/modules/client/back/models/client.json index 21db28eaf..6ad617687 100644 --- a/modules/client/back/models/client.json +++ b/modules/client/back/models/client.json @@ -145,6 +145,12 @@ }, "hasElectronicInvoice": { "type": "boolean" + }, + "rating": { + "type": "number" + }, + "recommendedCredit": { + "type": "number" } }, @@ -260,4 +266,4 @@ } } } -} \ No newline at end of file +} diff --git a/modules/client/front/credit-management/index.html b/modules/client/front/credit-management/index.html new file mode 100644 index 000000000..78cc6edb5 --- /dev/null +++ b/modules/client/front/credit-management/index.html @@ -0,0 +1,91 @@ + + + +
+ + + + + + + + + + + + + + +
+ + + + + + + + + Since + Employee + Rating + Recommended credit + + + + + {{::clientInforma.created | date:'dd/MM/yyyy HH:mm'}} + + + {{::clientInforma.worker.user.nickname}} + + + {{::clientInforma.rating}} + {{::clientInforma.recommendedCredit}} + + + + + + + + + diff --git a/modules/client/front/credit-management/index.js b/modules/client/front/credit-management/index.js new file mode 100644 index 000000000..856acd27b --- /dev/null +++ b/modules/client/front/credit-management/index.js @@ -0,0 +1,32 @@ +import ngModule from '../module'; +import Section from 'salix/components/section'; + +export default class Controller extends Section { + constructor($element, $) { + super($element, $); + + this.filter = { + include: [{ + relation: 'worker', + scope: { + fields: ['userFk'], + include: { + relation: 'user', + scope: { + fields: ['nickname'] + } + } + } + }], + }; + } + onSubmit() { + this.$.watcher.submit() + .then(() => this.$state.reload()); + } +} + +ngModule.vnComponent('vnClientCreditManagement', { + template: require('./index.html'), + controller: Controller +}); diff --git a/modules/client/front/credit-management/index.spec.js b/modules/client/front/credit-management/index.spec.js new file mode 100644 index 000000000..0f6460a03 --- /dev/null +++ b/modules/client/front/credit-management/index.spec.js @@ -0,0 +1,38 @@ +import './index'; + +describe('client unpaid', () => { + describe('Component vnClientUnpaid', () => { + let controller; + + beforeEach(ngModule('client')); + + beforeEach(inject($componentController => { + const $element = angular.element(''); + controller = $componentController('vnClientUnpaid', {$element}); + })); + + describe('setDefaultDate()', () => { + it(`should not set today date if has dated`, () => { + const hasData = true; + const yesterday = Date.vnNew(); + yesterday.setDate(yesterday.getDate() - 1); + + controller.clientUnpaid = { + dated: yesterday + }; + controller.setDefaultDate(hasData); + + expect(controller.clientUnpaid.dated).toEqual(yesterday); + }); + + it(`should set today if not has dated`, () => { + const hasData = true; + + controller.clientUnpaid = {}; + controller.setDefaultDate(hasData); + + expect(controller.clientUnpaid.dated).toBeDefined(); + }); + }); + }); +}); diff --git a/modules/client/front/credit-management/locale/es.yml b/modules/client/front/credit-management/locale/es.yml new file mode 100644 index 000000000..8743a1fb9 --- /dev/null +++ b/modules/client/front/credit-management/locale/es.yml @@ -0,0 +1,2 @@ +Recommended credit: Crédito recomendado +Rating: Clasificación diff --git a/modules/client/front/index.js b/modules/client/front/index.js index ff767bc9e..c7e39ea5d 100644 --- a/modules/client/front/index.js +++ b/modules/client/front/index.js @@ -47,3 +47,5 @@ import './defaulter'; import './notification'; import './unpaid'; import './extended-list'; +import './credit-management'; + diff --git a/modules/client/front/locale/es.yml b/modules/client/front/locale/es.yml index adbca8dbf..f14070f9e 100644 --- a/modules/client/front/locale/es.yml +++ b/modules/client/front/locale/es.yml @@ -64,3 +64,4 @@ Compensation Account: Cuenta para compensar Amount to return: Cantidad a devolver Delivered amount: Cantidad entregada Unpaid: Impagado +Credit management: Gestión de crédito diff --git a/modules/client/front/routes.json b/modules/client/front/routes.json index 406ca07d7..1a9b963e9 100644 --- a/modules/client/front/routes.json +++ b/modules/client/front/routes.json @@ -34,7 +34,8 @@ {"state": "client.card.contact", "icon": "contact_phone"}, {"state": "client.card.webPayment", "icon": "icon-onlinepayment"}, {"state": "client.card.dms.index", "icon": "cloud_upload"}, - {"state": "client.card.unpaid", "icon": "icon-defaulter"} + {"state": "client.card.unpaid", "icon": "icon-defaulter"}, + {"state": "client.card.creditManagement", "icon": "contact_support"} ] } ] @@ -416,7 +417,8 @@ "state": "client.notification", "component": "vn-client-notification", "description": "Notifications" - }, { + }, + { "url": "/unpaid", "state": "client.card.unpaid", "component": "vn-client-unpaid", @@ -428,6 +430,13 @@ "state": "client.extendedList", "component": "vn-client-extended-list", "description": "Extended list" + }, + { + "url": "/credit-management", + "state": "client.card.creditManagement", + "component": "vn-client-credit-management", + "acl": ["financial"], + "description": "Credit management" } ] } diff --git a/modules/client/front/summary/index.html b/modules/client/front/summary/index.html index ed4b89ee4..b8f88fa3c 100644 --- a/modules/client/front/summary/index.html +++ b/modules/client/front/summary/index.html @@ -22,75 +22,75 @@

- Basic data

-

Basic data

- - - - - - {{$ctrl.summary.salesPersonUser.name}} -

- Fiscal address

-

Fiscal address

- - - - - -

- Fiscal data

-

Fiscal data

- Billing data

-

Billing data

- - -

- Address @@ -201,10 +201,10 @@ ng-show="!$ctrl.isEmployee"> Address

- -

- Web access

-

Web access

- @@ -236,52 +236,61 @@

Business data

- - - - -
-

Financial information

- + + Financial information + + + + info="Invoices minus payments plus orders not yet invoiced"> - - - - - + +
@@ -341,7 +350,7 @@ class="link"> {{::ticket.refFk}} - {{::ticket.ticketState.state.name}} @@ -355,8 +364,8 @@ - - @@ -397,4 +406,4 @@ ticket="$ctrl.selectedTicket" model="model"> - \ No newline at end of file + diff --git a/modules/client/front/summary/locale/es.yml b/modules/client/front/summary/locale/es.yml index b6233d4b3..ca6e96fef 100644 --- a/modules/client/front/summary/locale/es.yml +++ b/modules/client/front/summary/locale/es.yml @@ -20,3 +20,6 @@ Invoices minus payments: Facturas menos recibos Deviated invoices minus payments: Facturas fuera de plazo menos recibos Go to the client: Ir al cliente Latest tickets: Últimos tickets +Rating: Clasificación +Value from 1 to 20. The higher the better value: Valor del 1 al 20. Cuanto más alto mejor valoración +Go to grafana: Ir a grafana