feat(resellers): UI de CNPJ/sócios/endereço/contatos, na ordem certa
Mesma UI construída pro Cadastro de Cliente, aplicada a Revenda, já direto na ordem pedida (Dados -> Sócios -> Endereço -> Contatos), sem precisar de uma segunda leva de reordenação. Criar uma revenda agora redireciona pra edição dela (não pra lista) já que CNPJ-lookup/Sócios só fazem sentido com um id existente. PartnersSection generalizada para reuso entre Cliente e Revenda. Corrige um bug real encontrado na verificação ao vivo: o rótulo do botão de busca estava amarrado ao que estava sendo digitado, não ao que já foi salvo — digitar um CNPJ válido trocava pra "Buscar novamente" antes de qualquer busca real acontecer. Suíte: 106/106 (inalterada). pnpm turbo run typecheck build: 28/28. Testado ao vivo com CNPJ real (Petrobras). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Client for `apps/api` `/v1/resellers` (see apps/api/src/resellers/resellers.controller.ts,
|
||||
* resellers.service.ts and packages/database/src/repositories/resellers.ts for the source of
|
||||
* truth — shapes below are mirrored, not invented).
|
||||
* resellers.service.ts and packages/database/src/repositories/resellers.ts +
|
||||
* reseller-partners.ts for the source of truth — shapes below are mirrored, not invented).
|
||||
*/
|
||||
import { apiRequest } from "./http.js";
|
||||
|
||||
@@ -15,6 +15,30 @@ export interface Reseller {
|
||||
document: string | null;
|
||||
contact_email: string | null;
|
||||
active: boolean;
|
||||
trade_name: string | null;
|
||||
state_registration: string | null;
|
||||
municipal_registration: string | null;
|
||||
opening_date: string | null;
|
||||
legal_nature: string | null;
|
||||
cnpj_situation: string | null;
|
||||
main_activity: string | null;
|
||||
address_zip: string | null;
|
||||
address_street: string | null;
|
||||
address_number: string | null;
|
||||
address_complement: string | null;
|
||||
address_neighborhood: string | null;
|
||||
address_city: string | null;
|
||||
address_state: string | null;
|
||||
address_country: string;
|
||||
contact_principal_name: string | null;
|
||||
contact_principal_email: string | null;
|
||||
contact_principal_phone: string | null;
|
||||
contact_financial_name: string | null;
|
||||
contact_financial_email: string | null;
|
||||
contact_financial_phone: string | null;
|
||||
contact_technical_name: string | null;
|
||||
contact_technical_email: string | null;
|
||||
contact_technical_phone: string | null;
|
||||
}
|
||||
|
||||
/** Request body — camelCase, matches `CreateResellerDto` exactly. */
|
||||
@@ -23,6 +47,33 @@ export interface CreateResellerInput {
|
||||
document?: string;
|
||||
contactEmail?: string;
|
||||
active?: boolean;
|
||||
|
||||
tradeName?: string;
|
||||
stateRegistration?: string;
|
||||
municipalRegistration?: string;
|
||||
openingDate?: string;
|
||||
legalNature?: string;
|
||||
cnpjSituation?: string;
|
||||
mainActivity?: string;
|
||||
|
||||
addressZip?: string;
|
||||
addressStreet?: string;
|
||||
addressNumber?: string;
|
||||
addressComplement?: string;
|
||||
addressNeighborhood?: string;
|
||||
addressCity?: string;
|
||||
addressState?: string;
|
||||
addressCountry?: string;
|
||||
|
||||
contactPrincipalName?: string;
|
||||
contactPrincipalEmail?: string;
|
||||
contactPrincipalPhone?: string;
|
||||
contactFinancialName?: string;
|
||||
contactFinancialEmail?: string;
|
||||
contactFinancialPhone?: string;
|
||||
contactTechnicalName?: string;
|
||||
contactTechnicalEmail?: string;
|
||||
contactTechnicalPhone?: string;
|
||||
}
|
||||
|
||||
/** Matches `UpdateResellerDto`: everything optional. */
|
||||
@@ -76,3 +127,88 @@ export function unassignUserFromReseller(
|
||||
{ accessToken },
|
||||
);
|
||||
}
|
||||
|
||||
/** `reseller_partners` row — see packages/database/src/repositories/reseller-partners.ts. */
|
||||
export interface ResellerPartner {
|
||||
id: string;
|
||||
reseller_id: string;
|
||||
name: string;
|
||||
document: string | null;
|
||||
qualification: string | null;
|
||||
source: string;
|
||||
cpf: string | null;
|
||||
will_sign: boolean;
|
||||
signature_email: string | null;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
/** Body of `POST /v1/resellers/:id/partners` — matches `CreateResellerPartnerDto`. */
|
||||
export interface CreateResellerPartnerInput {
|
||||
name: string;
|
||||
document?: string;
|
||||
qualification?: string;
|
||||
cpf?: string;
|
||||
willSign?: boolean;
|
||||
signatureEmail?: string;
|
||||
}
|
||||
|
||||
/** Body of `PATCH /v1/resellers/:id/partners/:partnerId` — matches `UpdateResellerPartnerDto`. */
|
||||
export interface UpdateResellerPartnerInput {
|
||||
cpf?: string;
|
||||
willSign?: boolean;
|
||||
signatureEmail?: string;
|
||||
}
|
||||
|
||||
export function listResellerPartners(id: string, accessToken: string): Promise<ResellerPartner[]> {
|
||||
return apiRequest<ResellerPartner[]>(`/resellers/${id}/partners`, { method: "GET" }, { accessToken });
|
||||
}
|
||||
|
||||
export function createResellerPartner(
|
||||
id: string,
|
||||
input: CreateResellerPartnerInput,
|
||||
accessToken: string,
|
||||
): Promise<ResellerPartner> {
|
||||
return apiRequest<ResellerPartner>(
|
||||
`/resellers/${id}/partners`,
|
||||
{ method: "POST", body: JSON.stringify(input) },
|
||||
{ accessToken },
|
||||
);
|
||||
}
|
||||
|
||||
export function updateResellerPartner(
|
||||
id: string,
|
||||
partnerId: string,
|
||||
input: UpdateResellerPartnerInput,
|
||||
accessToken: string,
|
||||
): Promise<ResellerPartner> {
|
||||
return apiRequest<ResellerPartner>(
|
||||
`/resellers/${id}/partners/${partnerId}`,
|
||||
{ method: "PATCH", body: JSON.stringify(input) },
|
||||
{ accessToken },
|
||||
);
|
||||
}
|
||||
|
||||
/** Result of `POST /v1/resellers/:id/cnpj-lookup` on a match (201). */
|
||||
export interface ResellerCnpjLookupResult {
|
||||
reseller: Reseller;
|
||||
partners: ResellerPartner[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up a CNPJ against the external source and applies the result to the
|
||||
* reseller (company data, address, partners) server-side. 404 means the CNPJ
|
||||
* wasn't found — caller should surface the API's message and leave the
|
||||
* reseller untouched (caller catches `ApiError` and inspects
|
||||
* `.status`/`.message`, same pattern as client-registrations).
|
||||
*/
|
||||
export function applyResellerCnpjLookup(
|
||||
id: string,
|
||||
cnpj: string,
|
||||
accessToken: string,
|
||||
): Promise<ResellerCnpjLookupResult> {
|
||||
return apiRequest<ResellerCnpjLookupResult>(
|
||||
`/resellers/${id}/cnpj-lookup`,
|
||||
{ method: "POST", body: JSON.stringify({ cnpj }) },
|
||||
{ accessToken },
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user