216 lines
6.9 KiB
JavaScript
216 lines
6.9 KiB
JavaScript
'use strict'
|
|
|
|
const Cliente = require('../models/Cliente')
|
|
|
|
function validarCpf(cpf) {
|
|
cpf = cpf.replace(/\D/g, '')
|
|
if (cpf.length !== 11 || /^(\d)\1+$/.test(cpf)) return false
|
|
let s = 0
|
|
for (let i = 0; i < 9; i++) s += +cpf[i] * (10 - i)
|
|
let r = (s * 10) % 11; if (r === 10 || r === 11) r = 0
|
|
if (r !== +cpf[9]) return false
|
|
s = 0
|
|
for (let i = 0; i < 10; i++) s += +cpf[i] * (11 - i)
|
|
r = (s * 10) % 11; if (r === 10 || r === 11) r = 0
|
|
return r === +cpf[10]
|
|
}
|
|
|
|
function validarCnpj(cnpj) {
|
|
cnpj = cnpj.replace(/\D/g, '')
|
|
if (cnpj.length !== 14 || /^(\d)\1+$/.test(cnpj)) return false
|
|
const calc = (n) => {
|
|
let s = 0, p = n - 7
|
|
for (let i = 0; i < n; i++) { p = p < 2 ? p + 9 : p; s += +cnpj[i] * p--; }
|
|
return s % 11 < 2 ? 0 : 11 - (s % 11)
|
|
}
|
|
return calc(12) === +cnpj[12] && calc(13) === +cnpj[13]
|
|
}
|
|
|
|
const clienteController = {
|
|
async list(req, res) {
|
|
try {
|
|
const tenantId = req.tenant.id
|
|
const { search, tipo, status, limit, offset } = req.query
|
|
const rows = await Cliente.list(tenantId, { search, tipo, status, limit, offset })
|
|
res.json(rows)
|
|
} catch (err) {
|
|
console.error('[cliente.list]', err.message)
|
|
res.status(500).json({ error: 'Erro ao listar clientes' })
|
|
}
|
|
},
|
|
|
|
async get(req, res) {
|
|
try {
|
|
const cliente = await Cliente.findComplete(req.params.id)
|
|
if (!cliente) return res.status(404).json({ error: 'Cliente não encontrado' })
|
|
res.json(cliente)
|
|
} catch (err) {
|
|
console.error('[cliente.get]', err.message)
|
|
res.status(500).json({ error: 'Erro ao buscar cliente' })
|
|
}
|
|
},
|
|
|
|
async create(req, res) {
|
|
try {
|
|
const tenantId = req.tenant.id
|
|
const { tipo, nome, cpf_cnpj, email, status } = req.body
|
|
if (!tipo || !['PF', 'PJ'].includes(tipo)) return res.status(400).json({ error: 'tipo deve ser PF ou PJ' })
|
|
if (!nome?.trim()) return res.status(400).json({ error: 'nome é obrigatório' })
|
|
if (!cpf_cnpj?.trim()) return res.status(400).json({ error: 'cpf_cnpj é obrigatório' })
|
|
|
|
const doc = cpf_cnpj.replace(/\D/g, '')
|
|
if (tipo === 'PF' && !validarCpf(doc)) return res.status(400).json({ error: 'CPF inválido' })
|
|
if (tipo === 'PJ' && !validarCnpj(doc)) return res.status(400).json({ error: 'CNPJ inválido' })
|
|
|
|
const existe = await Cliente.findByCpfCnpj(doc, tenantId)
|
|
if (existe) return res.status(409).json({ error: 'CPF/CNPJ já cadastrado' })
|
|
|
|
const user_id = req.user?.id || null
|
|
const cliente = await Cliente.create({ tenant_id: tenantId, tipo, nome: nome.trim(), cpf_cnpj: doc, email, status, user_id })
|
|
res.status(201).json(cliente)
|
|
} catch (err) {
|
|
console.error('[cliente.create]', err.message)
|
|
res.status(500).json({ error: 'Erro ao criar cliente' })
|
|
}
|
|
},
|
|
|
|
async update(req, res) {
|
|
try {
|
|
const { nome, email, status } = req.body
|
|
if (!nome?.trim()) return res.status(400).json({ error: 'nome é obrigatório' })
|
|
await Cliente.update(req.params.id, { nome: nome.trim(), email, status })
|
|
res.json({ ok: true })
|
|
} catch (err) {
|
|
console.error('[cliente.update]', err.message)
|
|
res.status(500).json({ error: 'Erro ao atualizar cliente' })
|
|
}
|
|
},
|
|
|
|
async remove(req, res) {
|
|
try {
|
|
await Cliente.delete(req.params.id)
|
|
res.json({ ok: true })
|
|
} catch (err) {
|
|
console.error('[cliente.remove]', err.message)
|
|
res.status(500).json({ error: 'Erro ao remover cliente' })
|
|
}
|
|
},
|
|
|
|
// ── Endereços ─────────────────────────────────────────────
|
|
|
|
async listEnderecos(req, res) {
|
|
try {
|
|
res.json(await Cliente.listEnderecos(req.params.id))
|
|
} catch (err) {
|
|
res.status(500).json({ error: 'Erro ao listar endereços' })
|
|
}
|
|
},
|
|
|
|
async addEndereco(req, res) {
|
|
try {
|
|
const dados = { ...req.body, cliente_id: req.params.id }
|
|
const end = await Cliente.createEndereco(dados)
|
|
if (dados.principal) await Cliente.setEndereçoPrincipal(req.params.id, end.id)
|
|
res.status(201).json(end)
|
|
} catch (err) {
|
|
console.error('[cliente.addEndereco]', err.message)
|
|
res.status(500).json({ error: 'Erro ao adicionar endereço' })
|
|
}
|
|
},
|
|
|
|
async updateEndereco(req, res) {
|
|
try {
|
|
await Cliente.updateEndereco(req.params.endId, req.body)
|
|
if (req.body.principal) await Cliente.setEndereçoPrincipal(req.params.id, req.params.endId)
|
|
res.json({ ok: true })
|
|
} catch (err) {
|
|
res.status(500).json({ error: 'Erro ao atualizar endereço' })
|
|
}
|
|
},
|
|
|
|
async removeEndereco(req, res) {
|
|
try {
|
|
await Cliente.deleteEndereco(req.params.endId)
|
|
res.json({ ok: true })
|
|
} catch (err) {
|
|
res.status(500).json({ error: 'Erro ao remover endereço' })
|
|
}
|
|
},
|
|
|
|
// ── Telefones ─────────────────────────────────────────────
|
|
|
|
async listTelefones(req, res) {
|
|
try {
|
|
res.json(await Cliente.listTelefones(req.params.id))
|
|
} catch (err) {
|
|
res.status(500).json({ error: 'Erro ao listar telefones' })
|
|
}
|
|
},
|
|
|
|
async addTelefone(req, res) {
|
|
try {
|
|
const tel = await Cliente.createTelefone({ ...req.body, cliente_id: req.params.id })
|
|
res.status(201).json(tel)
|
|
} catch (err) {
|
|
res.status(500).json({ error: 'Erro ao adicionar telefone' })
|
|
}
|
|
},
|
|
|
|
async updateTelefone(req, res) {
|
|
try {
|
|
await Cliente.updateTelefone(req.params.telId, req.body)
|
|
res.json({ ok: true })
|
|
} catch (err) {
|
|
res.status(500).json({ error: 'Erro ao atualizar telefone' })
|
|
}
|
|
},
|
|
|
|
async removeTelefone(req, res) {
|
|
try {
|
|
await Cliente.deleteTelefone(req.params.telId)
|
|
res.json({ ok: true })
|
|
} catch (err) {
|
|
res.status(500).json({ error: 'Erro ao remover telefone' })
|
|
}
|
|
},
|
|
|
|
// ── Responsáveis ─────────────────────────────────────────
|
|
|
|
async listResponsaveis(req, res) {
|
|
try {
|
|
res.json(await Cliente.listResponsaveis(req.params.id))
|
|
} catch (err) {
|
|
res.status(500).json({ error: 'Erro ao listar responsáveis' })
|
|
}
|
|
},
|
|
|
|
async addResponsavel(req, res) {
|
|
try {
|
|
const r = await Cliente.createResponsavel({ ...req.body, cliente_id: req.params.id })
|
|
res.status(201).json(r)
|
|
} catch (err) {
|
|
res.status(500).json({ error: 'Erro ao adicionar responsável' })
|
|
}
|
|
},
|
|
|
|
async updateResponsavel(req, res) {
|
|
try {
|
|
await Cliente.updateResponsavel(req.params.respId, req.body)
|
|
res.json({ ok: true })
|
|
} catch (err) {
|
|
res.status(500).json({ error: 'Erro ao atualizar responsável' })
|
|
}
|
|
},
|
|
|
|
async removeResponsavel(req, res) {
|
|
try {
|
|
await Cliente.deleteResponsavel(req.params.respId)
|
|
res.json({ ok: true })
|
|
} catch (err) {
|
|
res.status(500).json({ error: 'Erro ao remover responsável' })
|
|
}
|
|
},
|
|
}
|
|
|
|
module.exports = clienteController
|