metis-desk/modules/companies/src/api/infrastructure/persistence/company-persistence.mapper.ts

74 lines
2.6 KiB
TypeScript
Raw Normal View History

import type { Result as DomainResult } from "@repo/rdx-utils";
import type { InferAttributes } from "sequelize";
import { CompanyInputMapper } from "../../application/company-input.mapper";
import { Company } from "../../domain/company.aggregate";
import { Contact } from "../../domain/contact.entity";
import { Site } from "../../domain/site.entity";
import type { CompanyModel, ContactModel, SiteModel } from "./company.model";
export type CompanyRecord = {
company: InferAttributes<CompanyModel>;
contacts: InferAttributes<ContactModel>[];
sites: InferAttributes<SiteModel>[];
};
function persisted<T>(result: DomainResult<T, Error>): T {
if (!result.isSuccess) {
throw new Error("Persistencia de compañía inconsistente.");
}
return result.data;
}
export class CompanyPersistenceMapper {
private readonly input = new CompanyInputMapper();
toDomain(record: CompanyRecord): Company {
const id = persisted(this.input.id(record.company.id));
const props = persisted(this.input.company(record.company));
const contacts = record.contacts.map((row) => {
const companyId = persisted(this.input.id(row.companyId));
if (!companyId.equals(id)) {
throw new Error("Persistencia de contacto inconsistente.");
}
return Contact.rehydrate(
{ ...persisted(this.input.contact(row)), companyId },
persisted(this.input.id(row.id))
);
});
const sites = record.sites.map((row) => {
const companyId = persisted(this.input.id(row.companyId));
if (!companyId.equals(id)) {
throw new Error("Persistencia de sede inconsistente.");
}
return Site.rehydrate(
{ ...persisted(this.input.site(row)), companyId },
persisted(this.input.id(row.id))
);
});
return Company.rehydrate({ ...props, contacts, sites }, id);
}
toPersistence(company: Company): CompanyRecord {
return {
company: {
id: company.id.toPrimitive(),
name: company.name.toPrimitive(),
active: company.active,
},
contacts: company.contacts.map((contact) => ({
id: contact.id.toPrimitive(),
companyId: contact.companyId.toPrimitive(),
name: contact.name.toPrimitive(),
position: contact.position.toPrimitive(),
email: contact.email.toPrimitive(),
phone: contact.phone.toPrimitive(),
active: contact.active,
})),
sites: company.sites.map((site) => ({
id: site.id.toPrimitive(),
companyId: site.companyId.toPrimitive(),
name: site.name.toPrimitive(),
address: site.address.getOrUndefined()?.toPrimitive() ?? null,
})),
};
}
}