/** * Company API Module * * Provides API methods for company management operations. * All methods accept and return domain objects (Company), with schema mapping handled internally. * * @layer Infrastructure - API Client * @module Company API */ import { COMPANIES_CREATE, COMPANIES_LIST, COMPANIES_GET, COMPANIES_UPDATE, COMPANIES_UPDATE_CURRENCY, COMPANIES_DELETE, } from "@archer/api-interface/endpoints/customer-api"; import { apiClient } from '../../ApiClient'; import { Company } from '@domain/entities/Company'; import type { PaginationMeta, ListParams } from '../shared/types'; import { CompanyRequestMapper } from './mappers/CompanyRequestMapper'; import { CompanyResponseMapper } from './mappers/CompanyResponseMapper'; /** * Company API * * Encapsulates all company-related API operations. * Public signatures use domain objects only, schema transformations are internal. */ export const companiesApi = { /** * Creates a new company * * @param company - Company domain object * @returns Promise resolving to created Company domain object * @throws ApiError if request fails * * @endpoint POST /companies * @auth Required (Platform Admin only) * * @example * ```typescript * const company = Company.create({ * id: crypto.randomUUID(), * name: 'Acme Corp', * type: CompanyType.CORPORATE * }); * * const created = await companiesApi.createCompany(company); * console.log(created.id); // Server-generated UUID * ``` */ async createCompany(company: Company): Promise { // Transform domain → request schema (internal) const requestDto = CompanyRequestMapper.toCreateRequest(company); // API call const response = await apiClient.post( COMPANIES_CREATE.path, requestDto ); // Transform response schema → domain (internal) return CompanyResponseMapper.toCompany(response); }, /** * Lists all companies with optional pagination and filtering * * @param params - Optional pagination and filter parameters * @returns Promise resolving to companies array and pagination metadata * @throws ApiError if request fails * * @endpoint GET /companies * @auth Required * * @example * ```typescript * // Get first page with default limit * const { companies, pagination } = await companiesApi.listCompanies(); * * // Get specific page with custom limit * const result = await companiesApi.listCompanies({ page: 2, limit: 20 }); * * // Filter by search query * const filtered = await companiesApi.listCompanies({ search: 'Acme' }); * ``` */ async listCompanies(params?: ListParams): Promise<{ companies: Company[]; pagination: PaginationMeta; }> { // API call with query params const response = await apiClient.get( COMPANIES_LIST.path, { params } ); // Transform response schema → domain (internal) return CompanyResponseMapper.toCompanyList(response); }, /** * Retrieves a single company by ID * * @param id - Company UUID * @returns Promise resolving to Company domain object * @throws ApiError if company not found or request fails * * @endpoint GET /companies/:id * @auth Required * * @example * ```typescript * const company = await companiesApi.getCompany('550e8400-e29b-41d4-a716-446655440000'); * console.log(company.name); // 'Acme Corp' * ``` */ async getCompany(id: string): Promise { // API call with path parameter const url = COMPANIES_GET.path.replace(':id', id); const response = await apiClient.get(url); // Transform response schema → domain (internal) return CompanyResponseMapper.toCompany(response); }, /** * Updates a company by ID * * @param id - Company UUID * @param updates - Partial Company domain object with fields to update * @returns Promise resolving to updated Company domain object * @throws ApiError if company not found or request fails * * @endpoint PUT /companies/:id * @auth Required (Company Admin or Platform Admin) * * @example * ```typescript * // Update company name only * const updated = await companiesApi.updateCompany('550e8400-e29b-41d4-a716-446655440000', { * name: 'New Company Name' * }); * * // Note: Company type is immutable and cannot be updated * ``` */ async updateCompany(id: string, updates: Partial>): Promise { // Transform domain → request schema (internal) const requestDto = CompanyRequestMapper.toUpdateRequest(updates); // API call with path parameter const url = COMPANIES_UPDATE.path.replace(':id', id); const response = await apiClient.put( url, requestDto ); // Transform response schema → domain (internal) return CompanyResponseMapper.toCompany(response); }, /** * Change the company's billing currency. * * Backed by PUT /companies/:id/currency — server rejects with 409 when * `currency_locked_at` is set. The caller should surface that error as * "locked by active subscription" in the UI. */ async updateCurrency(id: string, currency: 'EUR' | 'USD'): Promise { const url = COMPANIES_UPDATE_CURRENCY.path.replace(':id', id); const response = await apiClient.put(url, { currency }); return CompanyResponseMapper.toCompany(response); }, /** * Deletes a company by ID * * Permanently removes the company and all associated data. * This action is irreversible. * * @param id - Company UUID * @returns Promise resolving when deletion completes * @throws ApiError if company not found or request fails * * @endpoint DELETE /companies/:id * @auth Required (Platform Admin only) * * @example * ```typescript * await companiesApi.deleteCompany('550e8400-e29b-41d4-a716-446655440000'); * console.log('Company deleted successfully'); * ``` * * @warning * This operation is irreversible. All company data, members, and related records will be permanently deleted. */ async deleteCompany(id: string): Promise { // API call with path parameter const url = COMPANIES_DELETE.path.replace(':id', id); await apiClient.delete(url); }, };