var UserError = require('../helpers').UserError; var getFinalState = require('../helpers').getFinalState; var isMultiple = require('../helpers').isMultiple; module.exports = function(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: 'El NIF/CIF debe ser único' }); Self.validatesUniquenessOf('socialName', { message: 'La razón social debe ser única' }); Self.validatesFormatOf('email', { message: 'Correo electrónico inválido', 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: 'El iban no tiene el formato correcto', allowNull: true, // FIXME: Ignored by loopback when it's false allowBlank: true }); Self.validateAsync('fi', tinIsValid, { message: 'DNI Incorrecto' }); 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: 'No se puede cambiar la forma de pago si no hay comercial asignado' }); function hasSalesMan(err) { if (this.payMethod && !this.salesPerson) err(); } Self.validateAsync('payMethodFk', hasIban, { message: 'El método de pago seleccionado requiere que se especifique el 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'); } };