import { BadRequestException, Injectable, NotFoundException } from "@nestjs/common"; import { companiesRepo, auditRepo, type Company } from "@eden/database"; import { onlyDigits, isValidCNPJ } from "@eden/domain-shared"; import type { CreateCompanyDto } from "./dto/create-company.dto.js"; import type { UpdateCompanyDto } from "./dto/update-company.dto.js"; @Injectable() export class CompaniesService { list(includeInactive: boolean): Promise { return companiesRepo.listCompanies(includeInactive); } async get(id: string): Promise { const company = await companiesRepo.getCompanyById(id); if (!company) throw new NotFoundException("Empresa não encontrada"); return company; } async create(dto: CreateCompanyDto, actorId: string): Promise { this.assertValidCnpjIfPresent(dto.cnpj); const company = await companiesRepo.createCompany({ companyName: dto.companyName, tradeName: dto.tradeName, cnpj: dto.cnpj ? onlyDigits(dto.cnpj) : undefined, stateRegistration: dto.stateRegistration, municipalRegistration: dto.municipalRegistration, addressZip: dto.addressZip, addressStreet: dto.addressStreet, addressNumber: dto.addressNumber, addressComplement: dto.addressComplement, addressNeighborhood: dto.addressNeighborhood, addressCity: dto.addressCity, addressState: dto.addressState, addressCountry: dto.addressCountry, phone: dto.phone, email: dto.email, website: dto.website, legalRepName: dto.legalRepName, legalRepCpf: dto.legalRepCpf ? onlyDigits(dto.legalRepCpf) : undefined, legalRepRole: dto.legalRepRole, legalRepEmail: dto.legalRepEmail, createdBy: actorId, }); await auditRepo.appendAuditEvent({ actorType: "user", actorId, action: "company.created", resourceType: "company", resourceId: company.id, }); return company; } async update(id: string, dto: UpdateCompanyDto, actorId: string): Promise { await this.get(id); // 404 if missing this.assertValidCnpjIfPresent(dto.cnpj); const company = await companiesRepo.updateCompany(id, { companyName: dto.companyName, tradeName: dto.tradeName, cnpj: dto.cnpj ? onlyDigits(dto.cnpj) : undefined, stateRegistration: dto.stateRegistration, municipalRegistration: dto.municipalRegistration, addressZip: dto.addressZip, addressStreet: dto.addressStreet, addressNumber: dto.addressNumber, addressComplement: dto.addressComplement, addressNeighborhood: dto.addressNeighborhood, addressCity: dto.addressCity, addressState: dto.addressState, addressCountry: dto.addressCountry, phone: dto.phone, email: dto.email, website: dto.website, legalRepName: dto.legalRepName, legalRepCpf: dto.legalRepCpf ? onlyDigits(dto.legalRepCpf) : undefined, legalRepRole: dto.legalRepRole, legalRepEmail: dto.legalRepEmail, isActive: dto.isActive, }); if (!company) throw new NotFoundException("Empresa não encontrada"); await auditRepo.appendAuditEvent({ actorType: "user", actorId, action: "company.updated", resourceType: "company", resourceId: id, metadata: { fields: Object.keys(dto) }, }); return company; } private assertValidCnpjIfPresent(cnpj: string | undefined): void { if (cnpj && !isValidCNPJ(cnpj)) { throw new BadRequestException("CNPJ inválido"); } } }