feat: refs #6636 Modified updateClaim, model and tests #2256

Merged
guillermo merged 10 commits from 6636-pickup into dev 2024-04-09 08:01:28 +00:00
18 changed files with 480 additions and 393 deletions

View File

@ -1880,7 +1880,7 @@ INSERT INTO `vn`.`claimRatio`(`clientFk`, `yearSale`, `claimAmount`, `claimingRa
INSERT INTO `vn`.`claimLog` (`originFk`, userFk, `action`, changedModel, oldInstance, newInstance, changedModelId, `description`) INSERT INTO `vn`.`claimLog` (`originFk`, userFk, `action`, changedModel, oldInstance, newInstance, changedModelId, `description`)
VALUES VALUES
(1, 18, 'update', 'Claim', '{"hasToPickUp":false}', '{"hasToPickUp":true}', 1, NULL), (1, 18, 'update', 'Claim', '{"pickup":null}', '{"pickup":"agency"}', 1, NULL),
(1, 18, 'update', 'ClaimObservation', '{}', '{"claimFk":1,"text":"Waiting for customer"}', 1, NULL), (1, 18, 'update', 'ClaimObservation', '{}', '{"claimFk":1,"text":"Waiting for customer"}', 1, NULL),
(1, 18, 'insert', 'ClaimBeginning', '{}', '{"claimFk":1,"saleFk":1,"quantity":10}', 1, NULL), (1, 18, 'insert', 'ClaimBeginning', '{}', '{"claimFk":1,"saleFk":1,"quantity":10}', 1, NULL),
(1, 18, 'insert', 'ClaimDms', '{}', '{"claimFk":1,"dmsFk":1}', 1, NULL); (1, 18, 'insert', 'ClaimDms', '{}', '{"claimFk":1,"dmsFk":1}', 1, NULL);

View File

@ -0,0 +1,15 @@
CREATE OR REPLACE TEMPORARY TABLE tmp.claimsWithHasToPickUp
SELECT id
FROM vn.claim
WHERE hasToPickUp;
ALTER TABLE vn.claim CHANGE hasToPickUp pickup ENUM('agency', 'delivery') DEFAULT NULL;
UPDATE vn.claim c
JOIN tmp.claimsWithHasToPickUp tmp ON tmp.id = c.id
SET c.pickup = 'delivery';
DROP TEMPORARY TABLE tmp.claimsWithHasToPickUp;
INSERT INTO salix.ACL (model,property,accessType,principalId)
VALUES ('Application','getEnumValues','*','employee');

View File

@ -762,7 +762,6 @@ export default {
claimBasicData: { claimBasicData: {
claimState: 'vn-claim-basic-data vn-autocomplete[ng-model="$ctrl.claim.claimStateFk"]', claimState: 'vn-claim-basic-data vn-autocomplete[ng-model="$ctrl.claim.claimStateFk"]',
packages: 'vn-input-number[ng-model="$ctrl.claim.packages"]', packages: 'vn-input-number[ng-model="$ctrl.claim.packages"]',
hasToPickUpCheckbox: 'vn-claim-basic-data vn-check[ng-model="$ctrl.claim.hasToPickUp"]',
saveButton: `button[type=submit]` saveButton: `button[type=submit]`
}, },
claimDetail: { claimDetail: {

View File

@ -36,7 +36,6 @@ describe('Claim edit basic data path', () => {
it('should check the "Pick up" checkbox', async() => { it('should check the "Pick up" checkbox', async() => {
await page.reloadSection('claim.card.basicData'); await page.reloadSection('claim.card.basicData');
await page.waitToClick(selectors.claimBasicData.hasToPickUpCheckbox);
await page.waitToClick(selectors.claimBasicData.saveButton); await page.waitToClick(selectors.claimBasicData.saveButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
@ -51,12 +50,6 @@ describe('Claim edit basic data path', () => {
expect(result).toEqual('Resuelto'); expect(result).toEqual('Resuelto');
}); });
it('should confirm the "is paid with mana" and "Pick up" checkbox are checked', async() => {
const hasToPickUpCheckbox = await page.checkboxState(selectors.claimBasicData.hasToPickUpCheckbox);
expect(hasToPickUpCheckbox).toBe('checked');
});
it('should confirm the claim packages was edited', async() => { it('should confirm the claim packages was edited', async() => {
const result = await page const result = await page
.waitToGetProperty(selectors.claimBasicData.packages, 'value'); .waitToGetProperty(selectors.claimBasicData.packages, 'value');

View File

@ -0,0 +1,56 @@
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
guillermo marked this conversation as resolved
Review

Igual si que tiraria en falta algun test

Igual si que tiraria en falta algun test
Review

Clar, pero en quin faig el test per a no crear dependencia?

O cree una taula en una columna en un enum per als tests?

Clar, pero en quin faig el test per a no crear dependencia? O cree una taula en una columna en un enum per als tests?
Review
@alexm
Review

Pots ferte un rawSql on te crees una taula per al test (i desferla en rollbacks)
Paregut a aço: loopback/common/methods/application/spec/execute.spec.js

Pots ferte un rawSql on te crees una taula per al test (i desferla en rollbacks) Paregut a aço: `loopback/common/methods/application/spec/execute.spec.js`
Self.remoteMethod('getEnumValues', {
description: 'Return enum values of column',
accessType: 'EXECUTE',
accepts: [
{
arg: 'schema',
type: 'string',
description: 'The schema of db',
required: true,
},
{
arg: 'table',
type: 'string',
description: 'The table of schema',
required: true,
},
{
arg: 'column',
type: 'string',
description: 'The column of table',
required: true,
},
],
returns: {
type: 'any',
root: true
},
http: {
path: `/get-enum-values`,
verb: 'GET'
}
});
Self.getEnumValues = async(schema, table, column) => {
guillermo marked this conversation as resolved
Review

Per a traure els tipos del enum valdria la pena comprovar si tens access a ixe camp? (En la funcio que fe carlosap, myUser_hasPriv) @jgallego

Per a traure els tipos del enum valdria la pena comprovar si tens access a ixe camp? (En la funcio que fe carlosap, `myUser_hasPriv`) @jgallego
Review

ahi no poden haver dades sensibles, jo crec que no cal.

ahi no poden haver dades sensibles, jo crec que no cal.
const stmt = new ParameterizedSQL(`
SELECT COLUMN_TYPE
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = ?
AND TABLE_NAME = ?
AND COLUMN_NAME = ?
AND DATA_TYPE = 'enum';`,
[schema, table, column]);
const conn = Self.dataSource.connector;
const [result] = await conn.executeStmt(stmt);
if (!result) throw new UserError(`No results found`);
const regex = /'([^']*)'/g;
return result.COLUMN_TYPE.match(regex).map(match => match.slice(1, -1));
guillermo marked this conversation as resolved
Review

Per curiositat aci com ho retorna, vuic dir com venen les dades en el result per a que fasa falta fer un .match

Per curiositat aci com ho retorna, vuic dir com venen les dades en el result per a que fasa falta fer un `.match`
Review

Retorna enum('valor1', 'valor2', 'valor3', ...), ho faig per a que meu splite, de forma que tinc array['valor1', 'valor2', ...]

Retorna `enum('valor1', 'valor2', 'valor3', ...)`, ho faig per a que meu splite, de forma que tinc array['valor1', 'valor2', ...]
};
};

View File

@ -0,0 +1,35 @@
const models = require('vn-loopback/server/server').models;
describe('Application getEnumValues()', () => {
let tx;
beforeEach(async() => {
tx = await models.Application.beginTransaction({});
const options = {transaction: tx};
await models.Application.rawSql(`
CREATE TABLE tableWithEnum (
direction enum('in', 'out', 'middle'),
PRIMARY KEY (direction)
) ENGINE=InnoDB;
`, null, options);
});
it('should return three if is ok', async() => {
try {
const options = {transaction: tx};
const response = await models.Application.getEnumValues(
'vn',
'tableWithEnum',
'direction',
options
);
expect(response.length).toEqual(3);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -5,4 +5,5 @@ module.exports = function(Self) {
require('../methods/application/execute')(Self); require('../methods/application/execute')(Self);
require('../methods/application/executeProc')(Self); require('../methods/application/executeProc')(Self);
require('../methods/application/executeFunc')(Self); require('../methods/application/executeFunc')(Self);
require('../methods/application/getEnumValues')(Self);
}; };

View File

@ -68,7 +68,7 @@
"Changed client paymethod": "I have changed the pay method for client [{{clientName}} ({{clientId}})]({{{url}}})", "Changed client paymethod": "I have changed the pay method for client [{{clientName}} ({{clientId}})]({{{url}}})",
"Sent units from ticket": "I sent *{{quantity}}* units of [{{concept}} ({{itemId}})]({{{itemUrl}}}) to *\"{{nickname}}\"* coming from ticket id [{{ticketId}}]({{{ticketUrl}}})", "Sent units from ticket": "I sent *{{quantity}}* units of [{{concept}} ({{itemId}})]({{{itemUrl}}}) to *\"{{nickname}}\"* coming from ticket id [{{ticketId}}]({{{ticketUrl}}})",
"Change quantity": "{{concept}} change of {{oldQuantity}} to {{newQuantity}}", "Change quantity": "{{concept}} change of {{oldQuantity}} to {{newQuantity}}",
"Claim will be picked": "The product from the claim [({{claimId}})]({{{claimUrl}}}) from the client *{{clientName}}* will be picked", "Claim will be picked": "The product from the claim [({{claimId}})]({{{claimUrl}}}) from the client *{{clientName}}* will be picked, with the pickup type *{{claimPickup}}*",
"Claim state has changed to": "The state of the claim [({{claimId}})]({{{claimUrl}}}) from client *{{clientName}}* has changed to *{{newState}}*", "Claim state has changed to": "The state of the claim [({{claimId}})]({{{claimUrl}}}) from client *{{clientName}}* has changed to *{{newState}}*",
"Customs agent is required for a non UEE member": "Customs agent is required for a non UEE member", "Customs agent is required for a non UEE member": "Customs agent is required for a non UEE member",
"Incoterms is required for a non UEE member": "Incoterms is required for a non UEE member", "Incoterms is required for a non UEE member": "Incoterms is required for a non UEE member",
@ -89,6 +89,8 @@
"landed": "Landed", "landed": "Landed",
"addressFk": "Address", "addressFk": "Address",
"companyFk": "Company", "companyFk": "Company",
"agency": "Agency",
"delivery": "Delivery",
"You need to fill sage information before you check verified data": "You need to fill sage information before you check verified data", "You need to fill sage information before you check verified data": "You need to fill sage information before you check verified data",
"The social name cannot be empty": "The social name cannot be empty", "The social name cannot be empty": "The social name cannot be empty",
"The nif cannot be empty": "The nif cannot be empty", "The nif cannot be empty": "The nif cannot be empty",

View File

@ -135,7 +135,7 @@
"Changed client paymethod": "He cambiado la forma de pago del cliente [{{clientName}} ({{clientId}})]({{{url}}})", "Changed client paymethod": "He cambiado la forma de pago del cliente [{{clientName}} ({{clientId}})]({{{url}}})",
"Sent units from ticket": "Envio *{{quantity}}* unidades de [{{concept}} ({{itemId}})]({{{itemUrl}}}) a *\"{{nickname}}\"* provenientes del ticket id [{{ticketId}}]({{{ticketUrl}}})", "Sent units from ticket": "Envio *{{quantity}}* unidades de [{{concept}} ({{itemId}})]({{{itemUrl}}}) a *\"{{nickname}}\"* provenientes del ticket id [{{ticketId}}]({{{ticketUrl}}})",
"Change quantity": "{{concept}} cambia de {{oldQuantity}} a {{newQuantity}}", "Change quantity": "{{concept}} cambia de {{oldQuantity}} a {{newQuantity}}",
"Claim will be picked": "Se recogerá el género de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}*", "Claim will be picked": "Se recogerá el género de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}*, con el tipo de recogida *{{claimPickup}}*",
"Claim state has changed to": "Se ha cambiado el estado de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}* a *{{newState}}*", "Claim state has changed to": "Se ha cambiado el estado de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}* a *{{newState}}*",
"Client checked as validated despite of duplication": "Cliente comprobado a pesar de que existe el cliente id {{clientId}}", "Client checked as validated despite of duplication": "Cliente comprobado a pesar de que existe el cliente id {{clientId}}",
"ORDER_ROW_UNAVAILABLE": "No hay disponibilidad de este producto", "ORDER_ROW_UNAVAILABLE": "No hay disponibilidad de este producto",
@ -168,6 +168,8 @@
"landed": "F. entrega", "landed": "F. entrega",
"addressFk": "Consignatario", "addressFk": "Consignatario",
"companyFk": "Empresa", "companyFk": "Empresa",
"agency": "Agencia",
"delivery": "Reparto",
"The social name cannot be empty": "La razón social no puede quedar en blanco", "The social name cannot be empty": "La razón social no puede quedar en blanco",
"The nif cannot be empty": "El NIF no puede quedar en blanco", "The nif cannot be empty": "El NIF no puede quedar en blanco",
"You need to fill sage information before you check verified data": "Debes rellenar la información de sage antes de marcar datos comprobados", "You need to fill sage information before you check verified data": "Debes rellenar la información de sage antes de marcar datos comprobados",
@ -349,5 +351,6 @@
"The address of the customer must have information about Incoterms and Customs Agent": "El consignatario del cliente debe tener informado Incoterms y Agente de aduanas", "The address of the customer must have information about Incoterms and Customs Agent": "El consignatario del cliente debe tener informado Incoterms y Agente de aduanas",
"The line could not be marked": "La linea no puede ser marcada", "The line could not be marked": "La linea no puede ser marcada",
"This password can only be changed by the user themselves": "Esta contraseña solo puede ser modificada por el propio usuario", "This password can only be changed by the user themselves": "Esta contraseña solo puede ser modificada por el propio usuario",
"They're not your subordinate": "No es tu subordinado/a." "They're not your subordinate": "No es tu subordinado/a.",
"No results found": "No se han encontrado resultados"
} }

View File

@ -6,7 +6,6 @@ columns:
isChargedToMana: charged to mana isChargedToMana: charged to mana
created: created created: created
responsibility: responsibility responsibility: responsibility
hasToPickUp: has to pickUp
ticketFk: ticket ticketFk: ticket
claimStateFk: claim state claimStateFk: claim state
workerFk: worker workerFk: worker

View File

@ -6,7 +6,6 @@ columns:
isChargedToMana: cargado al maná isChargedToMana: cargado al maná
created: creado created: creado
responsibility: responsabilidad responsibility: responsabilidad
hasToPickUp: es recogida
ticketFk: ticket ticketFk: ticket
claimStateFk: estado reclamación claimStateFk: estado reclamación
workerFk: trabajador workerFk: trabajador

View File

@ -11,7 +11,7 @@ describe('claim log()', () => {
model: 'Claim', model: 'Claim',
action: 'update', action: 'update',
changes: [ changes: [
{property: 'hasToPickUp', before: false, after: true} {property: 'pickup', before: null, after: 'agency'}
] ]
}; };

View File

@ -86,7 +86,7 @@ describe('Update Claim', () => {
args: { args: {
observation: 'valid observation', observation: 'valid observation',
claimStateFk: pendingState, claimStateFk: pendingState,
hasToPickUp: false pickup: null
} }
}; };
ctx.req.__ = i18n.__; ctx.req.__ = i18n.__;
@ -124,7 +124,7 @@ describe('Update Claim', () => {
args: { args: {
observation: 'valid observation', observation: 'valid observation',
claimStateFk: canceledState, claimStateFk: canceledState,
hasToPickUp: false pickup: null
} }
}; };
ctx.req.__ = i18n.__; ctx.req.__ = i18n.__;
@ -163,7 +163,7 @@ describe('Update Claim', () => {
claimStateFk: 3, claimStateFk: 3,
workerFk: 5, workerFk: 5,
observation: 'another valid observation', observation: 'another valid observation',
hasToPickUp: true pickup: 'agency'
} }
}; };
ctx.req.__ = i18n.__; ctx.req.__ = i18n.__;

View File

@ -27,8 +27,8 @@ module.exports = Self => {
type: 'string' type: 'string'
}, },
{ {
arg: 'hasToPickUp', arg: 'pickup',
type: 'boolean' type: 'any'
guillermo marked this conversation as resolved
Review

any es molt genèric, en addTimeEntry esta direction que es un enum i s'ha gastat 'string'

any es molt genèric, en addTimeEntry esta direction que es un enum i s'ha gastat 'string'
Review

He tingut que ficar any, perque tame puc pasar-lo a null, i si ho fique com a string dona error.

He tingut que ficar any, perque tame puc pasar-lo a null, i si ho fique com a string dona error.
}, },
{ {
arg: 'packages', arg: 'packages',
@ -72,9 +72,7 @@ module.exports = Self => {
// Get sales person from claim client // Get sales person from claim client
const salesPerson = claim.client().salesPersonUser(); const salesPerson = claim.client().salesPersonUser();
let changedHasToPickUp = false; const changedPickup = args.pickup != claim.pickup;
guillermo marked this conversation as resolved Outdated
Outdated
Review

Les 3 linies se poden refactoritzar per const changedPickup = args.pickup != claim.pickup

Les 3 linies se poden refactoritzar per `const changedPickup = args.pickup != claim.pickup`

Muy bien visto

Muy bien visto
if (args.hasToPickUp)
changedHasToPickUp = true;
// Validate when claimState has been changed // Validate when claimState has been changed
if (args.claimStateFk) { if (args.claimStateFk) {
@ -82,15 +80,15 @@ module.exports = Self => {
const canEditNewState = await models.ClaimState.isEditable(ctx, args.claimStateFk, myOptions); const canEditNewState = await models.ClaimState.isEditable(ctx, args.claimStateFk, myOptions);
const canEditState = await models.ACL.checkAccessAcl(ctx, 'Claim', 'editState', 'WRITE'); const canEditState = await models.ACL.checkAccessAcl(ctx, 'Claim', 'editState', 'WRITE');
if (!canEditOldState || !canEditNewState || changedHasToPickUp && !canEditState) if (!canEditOldState || !canEditNewState || changedPickup && !canEditState)
throw new UserError(`You don't have enough privileges to change that field`); throw new UserError(`You don't have enough privileges to change that field`);
} }
delete args.ctx; delete args.ctx;
const updatedClaim = await claim.updateAttributes(args, myOptions); const updatedClaim = await claim.updateAttributes(args, myOptions);
// When hasToPickUp has been changed // When pickup has been changed
if (salesPerson && changedHasToPickUp && updatedClaim.hasToPickUp) if (salesPerson && changedPickup && updatedClaim.pickup)
await notifyPickUp(ctx, salesPerson.id, claim); await notifyPickUp(ctx, salesPerson.id, claim);
// When claimState has been changed // When claimState has been changed
@ -132,7 +130,8 @@ module.exports = Self => {
const message = $t('Claim will be picked', { const message = $t('Claim will be picked', {
claimId: claim.id, claimId: claim.id,
clientName: claim.client().name, clientName: claim.client().name,
claimUrl: `${url}claim/${claim.id}/summary` claimUrl: `${url}claim/${claim.id}/summary`,
claimPickup: $t(claim.pickup)
}); });
await models.Chat.sendCheckingPresence(ctx, workerId, message); await models.Chat.sendCheckingPresence(ctx, workerId, message);
} }

View File

@ -31,8 +31,8 @@
"responsibility": { "responsibility": {
"type": "number" "type": "number"
}, },
"hasToPickUp": { "pickup": {
"type": "boolean" "type": "string"
}, },
"ticketFk": { "ticketFk": {
"type": "number" "type": "number"
guillermo marked this conversation as resolved Outdated

No se si cuando es ENUM, poneis eso o no...

No se si cuando es ENUM, poneis eso o no...

View File

@ -85,7 +85,7 @@ describe('claim', () => {
it('should perform a patch query and show a success message', () => { it('should perform a patch query and show a success message', () => {
jest.spyOn(controller.vnApp, 'showSuccess'); jest.spyOn(controller.vnApp, 'showSuccess');
const data = {hasToPickUp: true}; const data = {pickup: 'agency'};
$httpBackend.expect('PATCH', `Claims/1/updateClaimAction`, data).respond({}); $httpBackend.expect('PATCH', `Claims/1/updateClaimAction`, data).respond({});
controller.save(data); controller.save(data);
$httpBackend.flush(); $httpBackend.flush();

View File

@ -49,13 +49,6 @@
label="Packages received" label="Packages received"
ng-model="$ctrl.claim.packages"> ng-model="$ctrl.claim.packages">
</vn-input-number> </vn-input-number>
<vn-check
class="vn-mr-md"
label="Pick up"
ng-model="$ctrl.claim.hasToPickUp"
vn-acl="claimManager"
title="{{'When checked will notify to the salesPerson' | translate}}">
</vn-check>
</vn-horizontal> </vn-horizontal>
</vn-card> </vn-card>
<vn-button-bar> <vn-button-bar>

View File

@ -49,13 +49,6 @@
label="Attended by" label="Attended by"
value="{{$ctrl.summary.claim.worker.user.nickname}}"> value="{{$ctrl.summary.claim.worker.user.nickname}}">
</vn-label-value> </vn-label-value>
<vn-check
class="vn-mr-md"
label="Pick up"
ng-model="$ctrl.summary.claim.hasToPickUp"
title="{{'When checked will notify to the salesPerson' | translate}}"
disabled="true">
</vn-check>
</vn-auto> </vn-auto>
<vn-auto> <vn-auto>
<h4 ng-show="$ctrl.isSalesPerson && $ctrl.summary.observations.length"> <h4 ng-show="$ctrl.isSalesPerson && $ctrl.summary.observations.length">