2026-10-05 11:13:51 +00:00
|
|
|
import { UniqueID } from "@repo/rdx-ddd";
|
|
|
|
|
import { Result } from "@repo/rdx-utils";
|
|
|
|
|
|
|
|
|
|
import { Resource } from "../domain/resource.aggregate";
|
|
|
|
|
import { ResourceCatalogError } from "../domain/resource-definition";
|
|
|
|
|
import type { ResourceInput } from "../domain/resource-values";
|
|
|
|
|
|
|
|
|
|
import type { IResourceRepository } from "./resource.repository";
|
|
|
|
|
import { mapResourceInput } from "./resource-input.mapper";
|
2026-10-10 10:01:58 +00:00
|
|
|
|
2026-10-05 11:13:51 +00:00
|
|
|
export class ResourceUseCases {
|
|
|
|
|
constructor(private readonly repository: IResourceRepository) {}
|
2026-10-10 10:01:58 +00:00
|
|
|
|
2026-10-05 11:13:51 +00:00
|
|
|
get(companyId: string) {
|
|
|
|
|
const company = UniqueID.create(companyId);
|
2026-10-10 10:01:58 +00:00
|
|
|
|
2026-10-05 11:13:51 +00:00
|
|
|
if (!company.isSuccess) {
|
|
|
|
|
return Promise.resolve(Result.fail(new ResourceCatalogError("INVALID_REQUEST")));
|
|
|
|
|
}
|
2026-10-10 10:01:58 +00:00
|
|
|
|
2026-10-05 11:13:51 +00:00
|
|
|
return this.repository.get(company.data);
|
|
|
|
|
}
|
2026-10-10 10:01:58 +00:00
|
|
|
|
2026-10-05 11:13:51 +00:00
|
|
|
save(companyId: string, id: string | undefined, input: ResourceInput, actorId: string) {
|
|
|
|
|
const company = UniqueID.create(companyId);
|
|
|
|
|
const actor = UniqueID.create(actorId);
|
|
|
|
|
const identity = id ? UniqueID.create(id) : undefined;
|
2026-10-10 10:01:58 +00:00
|
|
|
|
2026-10-05 11:13:51 +00:00
|
|
|
if (!(company.isSuccess && actor.isSuccess) || (identity && !identity.isSuccess)) {
|
|
|
|
|
return Promise.resolve(Result.fail(new ResourceCatalogError("INVALID_REQUEST")));
|
|
|
|
|
}
|
2026-10-10 10:01:58 +00:00
|
|
|
|
2026-10-05 11:13:51 +00:00
|
|
|
return this.repository.save(company.data, (context) => {
|
|
|
|
|
const previous = identity?.isSuccess
|
|
|
|
|
? context.resources.find((resource) => resource.id.equals(identity.data))
|
|
|
|
|
: undefined;
|
2026-10-10 10:01:58 +00:00
|
|
|
|
2026-10-05 11:13:51 +00:00
|
|
|
if (id && !previous) {
|
|
|
|
|
return Result.fail(new ResourceCatalogError("RESOURCE_NOT_FOUND"));
|
|
|
|
|
}
|
|
|
|
|
const mapped = mapResourceInput(input, company.data, context, previous);
|
2026-10-10 10:01:58 +00:00
|
|
|
|
2026-10-05 11:13:51 +00:00
|
|
|
if (!mapped.isSuccess) {
|
|
|
|
|
return Result.fail(mapped.error);
|
|
|
|
|
}
|
2026-10-05 15:01:32 +00:00
|
|
|
const current = mapped.data.values.toPrimitive();
|
2026-10-10 10:01:58 +00:00
|
|
|
|
2026-10-05 15:01:32 +00:00
|
|
|
if (
|
|
|
|
|
current.integration?.kind === "mailbox" &&
|
|
|
|
|
context.resources.some((item) => {
|
|
|
|
|
const old = item.values.toPrimitive();
|
2026-10-10 10:01:58 +00:00
|
|
|
|
2026-10-05 15:01:32 +00:00
|
|
|
return (
|
|
|
|
|
!item.id.equals(previous?.id) &&
|
|
|
|
|
old.integration?.kind === "mailbox" &&
|
|
|
|
|
old.characteristics[old.integration.addressFieldId] ===
|
|
|
|
|
current.characteristics[
|
|
|
|
|
current.integration?.kind === "mailbox" ? current.integration.addressFieldId : ""
|
|
|
|
|
]
|
|
|
|
|
);
|
|
|
|
|
})
|
|
|
|
|
) {
|
|
|
|
|
return Result.fail(new ResourceCatalogError("NAME_EXISTS"));
|
|
|
|
|
}
|
2026-10-05 11:13:51 +00:00
|
|
|
if (
|
|
|
|
|
context.resources.some(
|
|
|
|
|
(item) =>
|
|
|
|
|
!item.id.equals(previous?.id) &&
|
|
|
|
|
item.values.toPrimitive().templateId === mapped.data.values.toPrimitive().templateId &&
|
2026-10-05 15:01:32 +00:00
|
|
|
sameAccessContext(item.values.toPrimitive().integration, current.integration) &&
|
2026-10-05 11:13:51 +00:00
|
|
|
item.values.name.toPrimitive().toLocaleLowerCase("es") ===
|
|
|
|
|
mapped.data.values.name.toPrimitive().toLocaleLowerCase("es")
|
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
return Result.fail(new ResourceCatalogError("NAME_EXISTS"));
|
|
|
|
|
}
|
|
|
|
|
const now = new Date().toISOString();
|
2026-10-10 10:01:58 +00:00
|
|
|
|
2026-10-05 11:13:51 +00:00
|
|
|
return previous
|
|
|
|
|
? previous.update(mapped.data.values, actor.data, now)
|
|
|
|
|
: Resource.create(
|
|
|
|
|
company.data,
|
|
|
|
|
mapped.data.specification,
|
|
|
|
|
mapped.data.values,
|
|
|
|
|
actor.data,
|
|
|
|
|
now
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-10-05 15:01:32 +00:00
|
|
|
|
|
|
|
|
function sameAccessContext(
|
|
|
|
|
first: ResourceInput["integration"],
|
|
|
|
|
second: ResourceInput["integration"]
|
|
|
|
|
) {
|
|
|
|
|
if (first?.kind !== "access" || second?.kind !== "access") {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2026-10-10 10:01:58 +00:00
|
|
|
|
2026-10-05 15:01:32 +00:00
|
|
|
return (
|
|
|
|
|
first.resourceTypeId === second.resourceTypeId &&
|
|
|
|
|
first.systemId === second.systemId &&
|
|
|
|
|
first.environmentId === second.environmentId
|
|
|
|
|
);
|
|
|
|
|
}
|