salix/services/loopback/common/models/client.js

184 lines
6.2 KiB
JavaScript

var UserError = require('../helpers').UserError;
var getFinalState = require('../helpers').getFinalState;
var isMultiple = require('../helpers').isMultiple;
module.exports = Self => {
// Methods
require('../methods/client/activate')(Self);
require('../methods/client/listAddresses')(Self);
require('../methods/client/card')(Self);
require('../methods/client/createWithUser')(Self);
require('../methods/client/listWorkers')(Self);
require('../methods/client/filter')(Self);
require('../methods/client/hasCustomerRole')(Self);
require('../methods/client/isValidClient')(Self);
require('../methods/client/activeSalesPerson')(Self);
require('../methods/client/addressesPropagateRe')(Self);
require('../methods/client/getDebt')(Self);
require('../methods/client/getMana')(Self);
require('../methods/client/getAverageInvoiced')(Self);
require('../methods/client/summary')(Self);
// Validations
Self.validatesUniquenessOf('fi', {
message: 'TIN must be unique'
});
Self.validatesUniquenessOf('socialName', {
message: 'The company name must be unique'
});
Self.validatesFormatOf('email', {
message: 'Invalid email',
allowNull: true,
allowBlank: true,
with: /^[\w|.|-]+@[\w|-]+(\.[\w|-]+)*(,[\w|.|-]+@[\w|-]+(\.[\w|-]+)*)*$/
});
Self.validatesLengthOf('postcode', {
allowNull: true,
allowBlank: true,
min: 3, max: 10
});
var validateIban = require('../validations/validateIban');
Self.validateBinded('iban', validateIban, {
message: 'The IBAN does not have the correct format',
allowNull: true, // FIXME: Ignored by loopback when it's false
allowBlank: true
});
Self.validateAsync('fi', tinIsValid, {
message: 'Invalid TIN'
});
let validateTin = require('../validations/validateTin');
async function tinIsValid(err, done) {
let filter = {
fields: ['code'],
where: {id: this.countryFk}
};
let country = await Self.app.models.Country.findOne(filter);
let code = country ? country.code.toLowerCase() : null;
if (!validateTin(this.fi, code))
err();
done();
}
Self.validate('payMethod', hasSalesMan, {
message: 'Cannot change the payment method if no salesperson'
});
function hasSalesMan(err) {
if (this.payMethod && !this.salesPerson)
err();
}
Self.validateAsync('payMethodFk', hasIban, {
message: 'That payment method requires an IBAN'
});
function hasIban(err, done) {
Self.app.models.PayMethod.findById(this.payMethodFk, (_, instance) => {
if (instance && instance.ibanRequired && !this.iban)
err();
done();
});
}
// Hooks
Self.observe('before save', async function(ctx) {
let changes = ctx.data || ctx.instance;
let finalState = getFinalState(ctx);
if (changes.salesPerson === null) {
changes.credit = 0;
changes.discount = 0;
changes.payMethodFk = 5; // Credit card
}
if (changes.payMethodFk !== undefined && changes.dueDay === undefined)
changes.dueDay = 5;
if (isMultiple(ctx)) return;
if (changes.isEqualizated || changes.fi !== undefined) {
let fiLetter = finalState.fi && finalState.fi.toUpperCase().charAt(0);
let canMarkEqualizationTax = fiLetter != 'A' && fiLetter != 'B';
if (finalState.isEqualizated && !canMarkEqualizationTax)
throw new UserError('Unable to mark the equivalence surcharge');
}
if (changes.credit !== undefined) {
try {
await validateCreditChange(ctx, finalState);
} catch (e) {
throw new UserError('You are not allowed to change the credit');
}
let filter = {fields: ['id'], where: {userFk: ctx.options.accessToken.userId}};
let worker = await Self.app.models.Worker.findOne(filter);
let newCredit = {
amount: changes.credit,
clientFk: finalState.id,
workerFk: worker ? worker.id : null
};
await Self.app.models.ClientCredit.create(newCredit);
}
});
async function validateCreditChange(ctx, finalState) {
let models = Self.app.models;
let userId = ctx.options.accessToken.userId;
let filter = {
fields: ['roleFk'],
where: {
maxAmount: {gt: ctx.data.credit}
}
};
let limits = await models.ClientCreditLimit.find(filter);
if (limits.length == 0)
throw new Error('Credit limits not found');
// Si el usuario no tiene alguno de los roles no continua
let requiredRoles = [];
for (limit of limits)
requiredRoles.push(limit.roleFk);
let where = {
roleId: {inq: requiredRoles},
principalType: 'USER',
principalId: userId
};
let count = await models.RoleMapping.count(where);
if (count <= 0)
throw new Error('The role cannot set this credit amount');
// Si se puso a 0 por gerencia, solo gerencia puede aumentarlo
let query = 'SELECT * FROM clientCredit WHERE clientFk = ? ORDER BY created DESC LIMIT 1';
let instances = await Self.rawSql(query, [finalState.id]);
if (instances.length !== 1 || instances[0].workerFk == userId || instances[0].amount > 0)
return;
query = `SELECT COUNT(distinct r.id) > 0 as hasManagerRole
FROM clientCredit cc
JOIN worker em ON em.id = cc.workerFk
JOIN account.user ac ON ac.id = em.userFk
JOIN salix.RoleMapping rm ON rm.principalId = ac.id
JOIN account.role r on r.id = rm.roleId
WHERE rm.principalType = 'USER'
AND cc.workerFk = ?
AND r.name = 'manager'`;
let instance = await Self.rawSql(query, [instances[0].workerFk]);
if (instance[0].hasManagerRole > 0)
throw new Error('Only manager can change the credit');
}
};