feat: initial project structure (Model Project) - Backend + Multi-Frontend + Docker
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
'use strict'
|
||||
|
||||
const { execute, queryOne, query } = require('../database/postgres')
|
||||
|
||||
class User {
|
||||
static findAll(tenantId) {
|
||||
if (tenantId) return query('SELECT * FROM users WHERE tenant_id=$1 ORDER BY timestamp DESC', [tenantId])
|
||||
return query('SELECT * FROM users ORDER BY timestamp DESC')
|
||||
}
|
||||
|
||||
static findById(id) {
|
||||
return queryOne('SELECT * FROM users WHERE id = $1', [id])
|
||||
}
|
||||
|
||||
static findByEmail(email, tenantId) {
|
||||
if (tenantId) return queryOne('SELECT * FROM users WHERE email=$1 AND tenant_id=$2', [email, tenantId])
|
||||
return queryOne('SELECT * FROM users WHERE email = $1', [email])
|
||||
}
|
||||
|
||||
static findByCpf(cpf, tenantId) {
|
||||
const clean = cpf.replace(/[^\d]+/g, '')
|
||||
if (tenantId) return queryOne('SELECT * FROM users WHERE cpf=$1 AND tenant_id=$2', [clean, tenantId])
|
||||
return queryOne('SELECT * FROM users WHERE cpf = $1', [clean])
|
||||
}
|
||||
|
||||
static findByPhone(telefone, tenantId) {
|
||||
const clean = telefone.replace(/[^\d]+/g, '')
|
||||
return queryOne(
|
||||
`SELECT * FROM users WHERE REGEXP_REPLACE(telefone,'[^0-9]','','g')=$1 AND tenant_id=$2`,
|
||||
[clean, tenantId]
|
||||
)
|
||||
}
|
||||
|
||||
// Login por email+senha (novo) ou CPF+telefone (legado)
|
||||
static findByEmailAndTenant(email, tenantId) {
|
||||
return queryOne(
|
||||
'SELECT * FROM users WHERE LOWER(email)=LOWER($1) AND tenant_id=$2',
|
||||
[email, tenantId]
|
||||
)
|
||||
}
|
||||
|
||||
static findByCpfPhone(cpf, telefone, tenantId) {
|
||||
const cleanCpf = cpf.replace(/[^\d]+/g, '')
|
||||
const cleanTel = telefone.replace(/[^\d]+/g, '')
|
||||
return queryOne(
|
||||
`SELECT * FROM users
|
||||
WHERE cpf=$1
|
||||
AND REGEXP_REPLACE(telefone,'[^0-9]','','g')=$2
|
||||
AND tenant_id=$3`,
|
||||
[cleanCpf, cleanTel, tenantId]
|
||||
)
|
||||
}
|
||||
|
||||
static create({ nome, email, cpf, telefone, ip, source, password_hash, tenant_id, portal_session_id }) {
|
||||
return execute(
|
||||
`INSERT INTO users (nome, email, cpf, telefone, ip, source, password_hash, tenant_id, portal_session_id)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING id`,
|
||||
[nome, email || null, cpf || null, telefone || null, ip || null,
|
||||
source || 'hotspot', password_hash || null, tenant_id || 1,
|
||||
portal_session_id || null]
|
||||
)
|
||||
}
|
||||
|
||||
static async getStats(tenantId) {
|
||||
const p = tenantId ? [tenantId] : []
|
||||
const w = tenantId ? 'WHERE tenant_id=$1' : ''
|
||||
const w2 = tenantId ? 'AND tenant_id=$1' : ''
|
||||
const total = await queryOne(`SELECT COUNT(*) AS count FROM users ${w}`, p)
|
||||
const today = await queryOne(`SELECT COUNT(*) AS count FROM users WHERE timestamp::date=CURRENT_DATE ${w2}`, p)
|
||||
const withEmail = await queryOne(`SELECT COUNT(*) AS count FROM users WHERE email IS NOT NULL ${w2}`, p)
|
||||
return {
|
||||
total: parseInt(total?.count || 0),
|
||||
today: parseInt(today?.count || 0),
|
||||
withEmail: parseInt(withEmail?.count || 0),
|
||||
}
|
||||
}
|
||||
|
||||
static deleteById(id) {
|
||||
return execute('DELETE FROM users WHERE id = $1', [id])
|
||||
}
|
||||
|
||||
static update(id, { nome, email, cpf, telefone, source }) {
|
||||
return execute(
|
||||
`UPDATE users SET nome=$1, email=$2, cpf=$3, telefone=$4, source=$5 WHERE id=$6`,
|
||||
[nome, email || null, cpf || null, telefone || null, source, id]
|
||||
)
|
||||
}
|
||||
|
||||
static updatePassword(id, password_hash) {
|
||||
return execute('UPDATE users SET password_hash=$1 WHERE id=$2', [password_hash, id])
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = User
|
||||
Reference in New Issue
Block a user