58 lines
1.8 KiB
TypeScript
58 lines
1.8 KiB
TypeScript
import { Injectable } from '@nestjs/common';
|
|
import { AccessStore } from '../identity/access.store';
|
|
import { recordAudit } from '../identity/audit';
|
|
import type { Principal } from '../identity/identity.types';
|
|
import { AppError } from '../common/errors/app-error';
|
|
import { editableProduct } from './catalog.helpers';
|
|
import type { VariantInput } from './catalog.schemas';
|
|
|
|
@Injectable()
|
|
export class VariantStore {
|
|
constructor(private readonly access: AccessStore) {}
|
|
save(actor: Principal, productId: string, input: VariantInput, id?: string) {
|
|
return this.access.mutate(actor, 'catalog.manage', async (tx) => {
|
|
const product = await editableProduct(
|
|
tx,
|
|
actor.organizationId,
|
|
productId,
|
|
);
|
|
if (
|
|
id &&
|
|
!(await tx.productVariant.findFirst({
|
|
where: { id, productId, organizationId: actor.organizationId },
|
|
}))
|
|
) {
|
|
throw new AppError('VARIANT_NOT_FOUND');
|
|
}
|
|
if (
|
|
!id &&
|
|
(await tx.productVariant.count({ where: { productId } })) >= 100
|
|
)
|
|
throw new AppError('VARIANT_LIMIT');
|
|
if (
|
|
id &&
|
|
!input.active &&
|
|
product.status === 'PUBLISHED' &&
|
|
!(await tx.productVariant.count({
|
|
where: { productId, active: true, id: { not: id } },
|
|
}))
|
|
) {
|
|
throw new AppError('VARIANT_REQUIRED');
|
|
}
|
|
const variant = id
|
|
? await tx.productVariant.update({ where: { id }, data: input })
|
|
: await tx.productVariant.create({
|
|
data: { ...input, productId, organizationId: actor.organizationId },
|
|
});
|
|
await recordAudit(
|
|
tx,
|
|
actor.organizationId,
|
|
actor.userId,
|
|
id ? 'variant.updated' : 'variant.created',
|
|
variant.id,
|
|
);
|
|
return variant;
|
|
});
|
|
}
|
|
}
|