Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5000-invoiceOut.global-invoicing
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
This commit is contained in:
commit
0bda8c0ed6
|
@ -14,7 +14,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
-
|
-
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
-
|
- (Clientes -> Listado extendido) Resuelto error al filtrar por clientes inactivos desde la columna "Activo"
|
||||||
|
- (General) Al pasar el ratón por encima del icono de "Borrar" en un campo, se hacía más grande afectando a la interfaz
|
||||||
|
|
||||||
## [2308.01] - 2023-03-09
|
## [2308.01] - 2023-03-09
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
|
||||||
|
VALUES('ClaimBeginning', 'isEditable', 'READ', 'ALLOW', 'ROLE', 'employee');
|
||||||
|
|
||||||
|
DELETE FROM `salix`.`ACL`
|
||||||
|
WHERE model='Claim' AND property='isEditable';
|
||||||
|
|
|
@ -1759,12 +1759,12 @@ INSERT INTO `vn`.`clientSample`(`id`, `clientFk`, `typeFk`, `created`, `workerFk
|
||||||
INSERT INTO `vn`.`claimState`(`id`, `code`, `description`, `roleFk`, `priority`, `hasToNotify`)
|
INSERT INTO `vn`.`claimState`(`id`, `code`, `description`, `roleFk`, `priority`, `hasToNotify`)
|
||||||
VALUES
|
VALUES
|
||||||
( 1, 'pending', 'Pendiente', 1, 1, 0),
|
( 1, 'pending', 'Pendiente', 1, 1, 0),
|
||||||
( 2, 'managed', 'Gestionado', 1, 5, 0),
|
( 2, 'managed', 'Gestionado', 72, 5, 0),
|
||||||
( 3, 'resolved', 'Resuelto', 72, 7, 0),
|
( 3, 'resolved', 'Resuelto', 72, 7, 0),
|
||||||
( 4, 'canceled', 'Anulado', 72, 6, 1),
|
( 4, 'canceled', 'Anulado', 72, 6, 1),
|
||||||
( 5, 'incomplete', 'Incompleta', 72, 3, 1),
|
( 5, 'incomplete', 'Incompleta', 1, 3, 1),
|
||||||
( 6, 'mana', 'Mana', 1, 4, 0),
|
( 6, 'mana', 'Mana', 72, 4, 0),
|
||||||
( 7, 'lack', 'Faltas', 1, 2, 0);
|
( 7, 'lack', 'Faltas', 72, 2, 0);
|
||||||
|
|
||||||
INSERT INTO `vn`.`claim`(`id`, `ticketCreated`, `claimStateFk`, `clientFk`, `workerFk`, `responsibility`, `isChargedToMana`, `created`, `packages`, `rma`)
|
INSERT INTO `vn`.`claim`(`id`, `ticketCreated`, `claimStateFk`, `clientFk`, `workerFk`, `responsibility`, `isChargedToMana`, `created`, `packages`, `rma`)
|
||||||
VALUES
|
VALUES
|
||||||
|
|
|
@ -40,7 +40,7 @@ export default class Check extends Toggle {
|
||||||
|
|
||||||
set tripleState(value) {
|
set tripleState(value) {
|
||||||
this._tripleState = value;
|
this._tripleState = value;
|
||||||
this.field = this.field;
|
this.field = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
get tripleState() {
|
get tripleState() {
|
||||||
|
|
|
@ -45,8 +45,8 @@ describe('Component vnCheck', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should set value to null and change to true when clicked`, () => {
|
it(`should set value to null and change to true when clicked`, () => {
|
||||||
controller.field = null;
|
|
||||||
controller.tripleState = true;
|
controller.tripleState = true;
|
||||||
|
controller.field = null;
|
||||||
element.click();
|
element.click();
|
||||||
|
|
||||||
expect(controller.field).toEqual(true);
|
expect(controller.field).toEqual(true);
|
||||||
|
|
|
@ -436,6 +436,7 @@ export default class SmartTable extends Component {
|
||||||
|
|
||||||
if (filters && filters.userFilter)
|
if (filters && filters.userFilter)
|
||||||
this.model.userFilter = filters.userFilter;
|
this.model.userFilter = filters.userFilter;
|
||||||
|
|
||||||
this.addFilter(field, this.$inputsScope.searchProps[field]);
|
this.addFilter(field, this.$inputsScope.searchProps[field]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,7 +452,7 @@ export default class SmartTable extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
addFilter(field, value) {
|
addFilter(field, value) {
|
||||||
if (value == '') value = null;
|
if (value === '') value = null;
|
||||||
|
|
||||||
let stateFilter = {tableQ: {}};
|
let stateFilter = {tableQ: {}};
|
||||||
if (this.$params.q) {
|
if (this.$params.q) {
|
||||||
|
@ -462,7 +463,7 @@ export default class SmartTable extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
const whereParams = {[field]: value};
|
const whereParams = {[field]: value};
|
||||||
if (value) {
|
if (value !== '' && value !== null && value !== undefined) {
|
||||||
let where = {[field]: value};
|
let where = {[field]: value};
|
||||||
if (this.exprBuilder) {
|
if (this.exprBuilder) {
|
||||||
where = buildFilter(whereParams, (param, value) =>
|
where = buildFilter(whereParams, (param, value) =>
|
||||||
|
|
|
@ -147,10 +147,11 @@
|
||||||
"Receipt's bank was not found": "Receipt's bank was not found",
|
"Receipt's bank was not found": "Receipt's bank was not found",
|
||||||
"This receipt was not compensated": "This receipt was not compensated",
|
"This receipt was not compensated": "This receipt was not compensated",
|
||||||
"Client's email was not found": "Client's email was not found",
|
"Client's email was not found": "Client's email was not found",
|
||||||
"Tickets with associated refunds": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº {{id}}",
|
"Tickets with associated refunds": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº {{id}}",
|
||||||
"It is not possible to modify tracked sales": "It is not possible to modify tracked sales",
|
"It is not possible to modify tracked sales": "It is not possible to modify tracked sales",
|
||||||
"It is not possible to modify sales that their articles are from Floramondo": "It is not possible to modify sales that their articles are from Floramondo",
|
"It is not possible to modify sales that their articles are from Floramondo": "It is not possible to modify sales that their articles are from Floramondo",
|
||||||
"It is not possible to modify cloned sales": "It is not possible to modify cloned sales",
|
"It is not possible to modify cloned sales": "It is not possible to modify cloned sales",
|
||||||
"Valid priorities: 1,2,3": "Valid priorities: 1,2,3",
|
"Valid priorities: 1,2,3": "Valid priorities: 1,2,3",
|
||||||
"Warehouse inventory not seted": "Warehouse inventory not seted"
|
"Warehouse inventory not seted": "Warehouse inventory not seted",
|
||||||
|
"Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº 2": "Tickets with associated refunds can't be deleted. This ticket is associated with refund Nº 2"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('isEditable', {
|
Self.remoteMethodCtx('isEditable', {
|
||||||
description: 'Check if a claim is editable',
|
description: 'Check if an state is editable',
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: [{
|
accepts: [{
|
||||||
arg: 'id',
|
arg: 'id',
|
||||||
type: 'number',
|
type: 'number',
|
||||||
required: true,
|
required: true,
|
||||||
description: 'the claim id',
|
description: 'the state id',
|
||||||
http: {source: 'path'}
|
http: {source: 'path'}
|
||||||
}],
|
}],
|
||||||
returns: {
|
returns: {
|
||||||
|
@ -21,25 +21,18 @@ module.exports = Self => {
|
||||||
|
|
||||||
Self.isEditable = async(ctx, id, options) => {
|
Self.isEditable = async(ctx, id, options) => {
|
||||||
const userId = ctx.req.accessToken.userId;
|
const userId = ctx.req.accessToken.userId;
|
||||||
|
const models = Self.app.models;
|
||||||
const myOptions = {};
|
const myOptions = {};
|
||||||
|
|
||||||
if (typeof options == 'object')
|
if (typeof options == 'object')
|
||||||
Object.assign(myOptions, options);
|
Object.assign(myOptions, options);
|
||||||
|
|
||||||
const isClaimManager = await Self.app.models.Account.hasRole(userId, 'claimManager', myOptions);
|
const state = await models.ClaimState.findById(id, {
|
||||||
|
include: {
|
||||||
const claim = await Self.app.models.Claim.findById(id, {
|
relation: 'writeRole'
|
||||||
fields: ['claimStateFk'],
|
}
|
||||||
include: [{
|
}, myOptions);
|
||||||
relation: 'claimState'
|
const roleWithGrants = state && state.writeRole().name;
|
||||||
}]
|
return await models.Account.hasRole(userId, roleWithGrants, myOptions);
|
||||||
}, myOptions);
|
|
||||||
|
|
||||||
const isClaimResolved = claim && claim.claimState().code == 'resolved';
|
|
||||||
|
|
||||||
if (!claim || (isClaimResolved && !isClaimManager))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
|
@ -1,16 +1,16 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
describe('claim isEditable()', () => {
|
describe('claimstate isEditable()', () => {
|
||||||
const salesPerdonId = 18;
|
const salesPersonId = 18;
|
||||||
const claimManagerId = 72;
|
const claimManagerId = 72;
|
||||||
it('should return false if the given claim does not exist', async() => {
|
it('should return false if the given state does not exist', async() => {
|
||||||
const tx = await app.models.Claim.beginTransaction({});
|
const tx = await app.models.Claim.beginTransaction({});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
const ctx = {req: {accessToken: {userId: claimManagerId}}};
|
const ctx = {req: {accessToken: {userId: claimManagerId}}};
|
||||||
const result = await app.models.Claim.isEditable(ctx, 99999, options);
|
const result = await app.models.ClaimState.isEditable(ctx, 9999, options);
|
||||||
|
|
||||||
expect(result).toEqual(false);
|
expect(result).toEqual(false);
|
||||||
|
|
||||||
|
@ -27,8 +27,8 @@ describe('claim isEditable()', () => {
|
||||||
try {
|
try {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
const ctx = {req: {accessToken: {userId: salesPerdonId}}};
|
const ctx = {req: {accessToken: {userId: salesPersonId}}};
|
||||||
const result = await app.models.Claim.isEditable(ctx, 4, options);
|
const result = await app.models.ClaimState.isEditable(ctx, 3, options);
|
||||||
|
|
||||||
expect(result).toEqual(false);
|
expect(result).toEqual(false);
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ describe('claim isEditable()', () => {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
const ctx = {req: {accessToken: {userId: claimManagerId}}};
|
const ctx = {req: {accessToken: {userId: claimManagerId}}};
|
||||||
const result = await app.models.Claim.isEditable(ctx, 4, options);
|
const result = await app.models.ClaimState.isEditable(ctx, 3, options);
|
||||||
|
|
||||||
expect(result).toEqual(true);
|
expect(result).toEqual(true);
|
||||||
|
|
||||||
|
@ -63,8 +63,8 @@ describe('claim isEditable()', () => {
|
||||||
try {
|
try {
|
||||||
const options = {transaction: tx};
|
const options = {transaction: tx};
|
||||||
|
|
||||||
const ctx = {req: {accessToken: {userId: salesPerdonId}}};
|
const ctx = {req: {accessToken: {userId: claimManagerId}}};
|
||||||
const result = await app.models.Claim.isEditable(ctx, 1, options);
|
const result = await app.models.ClaimState.isEditable(ctx, 7, options);
|
||||||
|
|
||||||
expect(result).toEqual(true);
|
expect(result).toEqual(true);
|
||||||
|
|
|
@ -65,7 +65,8 @@ module.exports = Self => {
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
promises.push(Self.app.models.Claim.find(filter, myOptions));
|
const models = Self.app.models;
|
||||||
|
promises.push(models.Claim.find(filter, myOptions));
|
||||||
|
|
||||||
// Claim detail
|
// Claim detail
|
||||||
filter = {
|
filter = {
|
||||||
|
@ -82,7 +83,7 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
promises.push(Self.app.models.ClaimBeginning.find(filter, myOptions));
|
promises.push(models.ClaimBeginning.find(filter, myOptions));
|
||||||
|
|
||||||
// Claim observations
|
// Claim observations
|
||||||
filter = {
|
filter = {
|
||||||
|
@ -96,7 +97,7 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
promises.push(Self.app.models.ClaimObservation.find(filter, myOptions));
|
promises.push(models.ClaimObservation.find(filter, myOptions));
|
||||||
|
|
||||||
// Claim developments
|
// Claim developments
|
||||||
filter = {
|
filter = {
|
||||||
|
@ -128,7 +129,7 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
promises.push(Self.app.models.ClaimDevelopment.find(filter, myOptions));
|
promises.push(models.ClaimDevelopment.find(filter, myOptions));
|
||||||
|
|
||||||
// Claim action
|
// Claim action
|
||||||
filter = {
|
filter = {
|
||||||
|
@ -145,11 +146,11 @@ module.exports = Self => {
|
||||||
{relation: 'claimBeggining'}
|
{relation: 'claimBeggining'}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
promises.push(Self.app.models.ClaimEnd.find(filter, myOptions));
|
promises.push(models.ClaimEnd.find(filter, myOptions));
|
||||||
|
|
||||||
const res = await Promise.all(promises);
|
const res = await Promise.all(promises);
|
||||||
|
|
||||||
summary.isEditable = await Self.isEditable(ctx, id, myOptions);
|
summary.isEditable = await models.ClaimState.isEditable(ctx, res[0][0].claimStateFk, myOptions);
|
||||||
[summary.claim] = res[0];
|
[summary.claim] = res[0];
|
||||||
summary.salesClaimed = res[1];
|
summary.salesClaimed = res[1];
|
||||||
summary.observations = res[2];
|
summary.observations = res[2];
|
||||||
|
|
|
@ -2,6 +2,7 @@ const UserError = require('vn-loopback/util/user-error');
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethod('updateClaim', {
|
Self.remoteMethod('updateClaim', {
|
||||||
description: 'Update a claim with privileges',
|
description: 'Update a claim with privileges',
|
||||||
|
accessType: 'WRITE',
|
||||||
accepts: [{
|
accepts: [{
|
||||||
arg: 'ctx',
|
arg: 'ctx',
|
||||||
type: 'object',
|
type: 'object',
|
||||||
|
@ -78,11 +79,11 @@ module.exports = Self => {
|
||||||
|
|
||||||
// Validate when claimState has been changed
|
// Validate when claimState has been changed
|
||||||
if (args.claimStateFk) {
|
if (args.claimStateFk) {
|
||||||
const canUpdate = await canChangeState(ctx, claim.claimStateFk, myOptions);
|
const canEditOldState = await models.ClaimState.isEditable(ctx, claim.claimStateFk, myOptions);
|
||||||
const hasRights = await canChangeState(ctx, args.claimStateFk, myOptions);
|
const canEditNewState = await models.ClaimState.isEditable(ctx, args.claimStateFk, myOptions);
|
||||||
const isClaimManager = await models.Account.hasRole(userId, 'claimManager', myOptions);
|
const isClaimManager = await models.Account.hasRole(userId, 'claimManager', myOptions);
|
||||||
|
|
||||||
if (!canUpdate || !hasRights || changedHasToPickUp && !isClaimManager)
|
if (!canEditOldState || !canEditNewState || changedHasToPickUp && !isClaimManager)
|
||||||
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`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,21 +114,6 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
async function canChangeState(ctx, id, options) {
|
|
||||||
let models = Self.app.models;
|
|
||||||
let userId = ctx.req.accessToken.userId;
|
|
||||||
|
|
||||||
let state = await models.ClaimState.findById(id, {
|
|
||||||
include: {
|
|
||||||
relation: 'writeRole'
|
|
||||||
}
|
|
||||||
}, options);
|
|
||||||
let stateRole = state.writeRole().name;
|
|
||||||
let canUpdate = await models.Account.hasRole(userId, stateRole, options);
|
|
||||||
|
|
||||||
return canUpdate;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function notifyStateChange(ctx, workerId, claim, state) {
|
async function notifyStateChange(ctx, workerId, claim, state) {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const origin = ctx.req.headers.origin;
|
const origin = ctx.req.headers.origin;
|
||||||
|
|
|
@ -22,8 +22,28 @@ module.exports = Self => {
|
||||||
async function claimIsEditable(ctx) {
|
async function claimIsEditable(ctx) {
|
||||||
const loopBackContext = LoopBackContext.getCurrentContext();
|
const loopBackContext = LoopBackContext.getCurrentContext();
|
||||||
const httpCtx = {req: loopBackContext.active};
|
const httpCtx = {req: loopBackContext.active};
|
||||||
|
const models = Self.app.models;
|
||||||
|
const myOptions = {};
|
||||||
|
|
||||||
|
if (ctx.options && ctx.options.transaction)
|
||||||
|
myOptions.transaction = ctx.options.transaction;
|
||||||
|
|
||||||
const claimBeginning = await Self.findById(ctx.where.id);
|
const claimBeginning = await Self.findById(ctx.where.id);
|
||||||
const isEditable = await Self.app.models.Claim.isEditable(httpCtx, claimBeginning.claimFk);
|
|
||||||
|
const filter = {
|
||||||
|
where: {id: claimBeginning.claimFk},
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
relation: 'claimState',
|
||||||
|
scope: {
|
||||||
|
fields: ['id', 'code', 'description']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
const [claim] = await models.Claim.find(filter, myOptions);
|
||||||
|
const isEditable = await models.ClaimState.isEditable(httpCtx, claim.ClaimState());
|
||||||
|
|
||||||
if (!isEditable)
|
if (!isEditable)
|
||||||
throw new UserError(`The current claim can't be modified`);
|
throw new UserError(`The current claim can't be modified`);
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
require('../methods/claim-state/isEditable')(Self);
|
||||||
|
};
|
|
@ -6,7 +6,6 @@ module.exports = Self => {
|
||||||
require('../methods/claim/regularizeClaim')(Self);
|
require('../methods/claim/regularizeClaim')(Self);
|
||||||
require('../methods/claim/uploadFile')(Self);
|
require('../methods/claim/uploadFile')(Self);
|
||||||
require('../methods/claim/updateClaimAction')(Self);
|
require('../methods/claim/updateClaimAction')(Self);
|
||||||
require('../methods/claim/isEditable')(Self);
|
|
||||||
require('../methods/claim/updateClaimDestination')(Self);
|
require('../methods/claim/updateClaimDestination')(Self);
|
||||||
require('../methods/claim/downloadFile')(Self);
|
require('../methods/claim/downloadFile')(Self);
|
||||||
require('../methods/claim/claimPickupPdf')(Self);
|
require('../methods/claim/claimPickupPdf')(Self);
|
||||||
|
|
|
@ -151,7 +151,7 @@ class Controller extends Section {
|
||||||
isClaimEditable() {
|
isClaimEditable() {
|
||||||
if (!this.claim) return;
|
if (!this.claim) return;
|
||||||
|
|
||||||
this.$http.get(`Claims/${this.claim.id}/isEditable`).then(res => {
|
this.$http.get(`ClaimStates/${this.claim.id}/isEditable`).then(res => {
|
||||||
this.isRewritable = res.data;
|
this.isRewritable = res.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ describe('claim', () => {
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
$httpBackend.whenGET('Claims/ClaimBeginnings').respond({});
|
$httpBackend.whenGET('Claims/ClaimBeginnings').respond({});
|
||||||
$httpBackend.whenGET(`Tickets/1/isEditable`).respond(true);
|
$httpBackend.whenGET(`Tickets/1/isEditable`).respond(true);
|
||||||
$httpBackend.whenGET(`Claims/2/isEditable`).respond(true);
|
$httpBackend.whenGET(`ClaimStates/2/isEditable`).respond(true);
|
||||||
const $element = angular.element('<vn-claim-detail></vn-claim-detail>');
|
const $element = angular.element('<vn-claim-detail></vn-claim-detail>');
|
||||||
controller = $componentController('vnClaimDetail', {$element, $scope});
|
controller = $componentController('vnClaimDetail', {$element, $scope});
|
||||||
controller.claim = {
|
controller.claim = {
|
||||||
|
|
Loading…
Reference in New Issue