feat(resellers): campos de representante legal (preparação p/ contrato)
Usuário: o cadastro de revenda precisa ficar completo porque essa mesma base vai alimentar a criação de contrato com a revenda dentro do ERP. resellers ganha rep_full_name/rep_cpf/rep_role/rep_email/ rep_mobile_phone/rep_authorization_ack, mesmo shape de client_registrations.pj_rep_* — um contrato precisa de um signatário nomeado e autorizado, não só a lista geral de sócios. Divergência deliberada: ao contrário de pj_rep_cpf (bloqueado do PATCH genérico em client_registrations, esperando um fluxo de submissão pública que o EDEN ainda não construiu — hoje uma lacuna conhecida, nunca preenchido de fato), rep_cpf aqui fica livremente editável — revenda não tem esse fluxo de submissão pública pra travar atrás. Nova tela: card "Representante legal" entre "Dados da revenda" e "Sócios". Suíte: 107/107 (106→107). pnpm turbo run typecheck build: 28/28. Testado ao vivo em navegador real. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Representante legal da revenda — mirrors `client_registrations.pj_rep_*`
|
||||
* (packages/database/migrations/1788447739229_client-registrations.cjs).
|
||||
* Motivation (user, 2026-09-18): reseller registration data will later
|
||||
* feed reseller contract creation inside the ERP, same as
|
||||
* client_registrations already does for client contracts — a contract
|
||||
* needs a named, authorized signer for the legal entity, not just the
|
||||
* general Sócios list (`reseller_partners`, added in
|
||||
* 1789700000000_resellers-expansion.cjs).
|
||||
*
|
||||
* Deliberate deviation from `client_registrations.pj_rep_cpf`: there it's
|
||||
* structurally excluded from the generic admin PATCH (`UpdateClientRegistrationDto`)
|
||||
* because in the legacy it's only ever set during the public self-service
|
||||
* submission flow, which EDEN hasn't built yet — so it stays permanently
|
||||
* unset there today, a known pre-existing gap, not something to replicate.
|
||||
* Resellers have no such public submission flow (always backoffice-created)
|
||||
* and no "original submission" moment to lock behind, so `rep_cpf` here is
|
||||
* a plain, freely-PATCH-able column like every other reseller field — see
|
||||
* `resellers.service.ts`, no new DTO exclusion added for it.
|
||||
*/
|
||||
|
||||
exports.shorthands = undefined;
|
||||
|
||||
exports.up = (pgm) => {
|
||||
pgm.sql(`
|
||||
ALTER TABLE resellers
|
||||
ADD COLUMN rep_full_name TEXT,
|
||||
ADD COLUMN rep_cpf TEXT,
|
||||
ADD COLUMN rep_role TEXT,
|
||||
ADD COLUMN rep_email TEXT,
|
||||
ADD COLUMN rep_mobile_phone TEXT,
|
||||
ADD COLUMN rep_authorization_ack BOOLEAN NOT NULL DEFAULT false;
|
||||
|
||||
COMMENT ON COLUMN resellers.rep_authorization_ack IS
|
||||
'Confirmação de que o representante está autorizado a agir pela revenda — mesmo campo de intenção que client_registrations.pj_rep_authorization_ack, sem o mesmo bloqueio estrutural de edição (ver cabeçalho da migration).';
|
||||
`);
|
||||
};
|
||||
|
||||
exports.down = (pgm) => {
|
||||
pgm.sql(`
|
||||
ALTER TABLE resellers
|
||||
DROP COLUMN IF EXISTS rep_full_name,
|
||||
DROP COLUMN IF EXISTS rep_cpf,
|
||||
DROP COLUMN IF EXISTS rep_role,
|
||||
DROP COLUMN IF EXISTS rep_email,
|
||||
DROP COLUMN IF EXISTS rep_mobile_phone,
|
||||
DROP COLUMN IF EXISTS rep_authorization_ack;
|
||||
`);
|
||||
};
|
||||
@@ -33,6 +33,12 @@ export interface Reseller {
|
||||
contact_technical_name: string | null;
|
||||
contact_technical_email: string | null;
|
||||
contact_technical_phone: string | null;
|
||||
rep_full_name: string | null;
|
||||
rep_cpf: string | null;
|
||||
rep_role: string | null;
|
||||
rep_email: string | null;
|
||||
rep_mobile_phone: string | null;
|
||||
rep_authorization_ack: boolean;
|
||||
}
|
||||
|
||||
export async function listResellers(includeInactive = false): Promise<Reseller[]> {
|
||||
@@ -79,6 +85,12 @@ export interface CreateResellerInput {
|
||||
contactTechnicalName?: string | null;
|
||||
contactTechnicalEmail?: string | null;
|
||||
contactTechnicalPhone?: string | null;
|
||||
repFullName?: string | null;
|
||||
repCpf?: string | null;
|
||||
repRole?: string | null;
|
||||
repEmail?: string | null;
|
||||
repMobilePhone?: string | null;
|
||||
repAuthorizationAck?: boolean;
|
||||
}
|
||||
|
||||
export async function createReseller(input: CreateResellerInput): Promise<Reseller> {
|
||||
@@ -91,7 +103,8 @@ export async function createReseller(input: CreateResellerInput): Promise<Resell
|
||||
address_neighborhood, address_city, address_state, address_country,
|
||||
contact_principal_name, contact_principal_email, contact_principal_phone,
|
||||
contact_financial_name, contact_financial_email, contact_financial_phone,
|
||||
contact_technical_name, contact_technical_email, contact_technical_phone
|
||||
contact_technical_name, contact_technical_email, contact_technical_phone,
|
||||
rep_full_name, rep_cpf, rep_role, rep_email, rep_mobile_phone, rep_authorization_ack
|
||||
)
|
||||
VALUES (
|
||||
$1, $2, $3, COALESCE($4, true), $5,
|
||||
@@ -101,7 +114,8 @@ export async function createReseller(input: CreateResellerInput): Promise<Resell
|
||||
$17, $18, $19, COALESCE($20, 'Brasil'),
|
||||
$21, $22, $23,
|
||||
$24, $25, $26,
|
||||
$27, $28, $29
|
||||
$27, $28, $29,
|
||||
$30, $31, $32, $33, $34, COALESCE($35, false)
|
||||
)
|
||||
RETURNING *`,
|
||||
[
|
||||
@@ -134,6 +148,12 @@ export async function createReseller(input: CreateResellerInput): Promise<Resell
|
||||
input.contactTechnicalName ?? null,
|
||||
input.contactTechnicalEmail ?? null,
|
||||
input.contactTechnicalPhone ?? null,
|
||||
input.repFullName ?? null,
|
||||
input.repCpf ?? null,
|
||||
input.repRole ?? null,
|
||||
input.repEmail ?? null,
|
||||
input.repMobilePhone ?? null,
|
||||
input.repAuthorizationAck ?? null,
|
||||
],
|
||||
);
|
||||
const reseller = rows[0];
|
||||
@@ -176,7 +196,13 @@ export async function updateReseller(
|
||||
contact_financial_phone = COALESCE($26, contact_financial_phone),
|
||||
contact_technical_name = COALESCE($27, contact_technical_name),
|
||||
contact_technical_email = COALESCE($28, contact_technical_email),
|
||||
contact_technical_phone = COALESCE($29, contact_technical_phone)
|
||||
contact_technical_phone = COALESCE($29, contact_technical_phone),
|
||||
rep_full_name = COALESCE($30, rep_full_name),
|
||||
rep_cpf = COALESCE($31, rep_cpf),
|
||||
rep_role = COALESCE($32, rep_role),
|
||||
rep_email = COALESCE($33, rep_email),
|
||||
rep_mobile_phone = COALESCE($34, rep_mobile_phone),
|
||||
rep_authorization_ack = COALESCE($35, rep_authorization_ack)
|
||||
WHERE id = $1
|
||||
RETURNING *`,
|
||||
[
|
||||
@@ -209,6 +235,12 @@ export async function updateReseller(
|
||||
input.contactTechnicalName ?? null,
|
||||
input.contactTechnicalEmail ?? null,
|
||||
input.contactTechnicalPhone ?? null,
|
||||
input.repFullName ?? null,
|
||||
input.repCpf ?? null,
|
||||
input.repRole ?? null,
|
||||
input.repEmail ?? null,
|
||||
input.repMobilePhone ?? null,
|
||||
input.repAuthorizationAck ?? null,
|
||||
],
|
||||
);
|
||||
return rows[0] ?? null;
|
||||
|
||||
Reference in New Issue
Block a user