Refactor types service into modular services and repositories
This commit is contained in:
58
src/common/repositories/composant-models.repository.ts
Normal file
58
src/common/repositories/composant-models.repository.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Prisma, PrismaClient } from '@prisma/client';
|
||||
import { PrismaService } from '../../prisma/prisma.service';
|
||||
|
||||
@Injectable()
|
||||
export class ComposantModelsRepository {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
private get client(): PrismaClient {
|
||||
return this.prisma;
|
||||
}
|
||||
|
||||
async create(
|
||||
data: Prisma.ComposantModelCreateInput,
|
||||
include?: Prisma.ComposantModelInclude,
|
||||
) {
|
||||
return this.client.composantModel.create({
|
||||
data,
|
||||
include,
|
||||
});
|
||||
}
|
||||
|
||||
async findAll(
|
||||
typeComposantId?: string,
|
||||
include?: Prisma.ComposantModelInclude,
|
||||
) {
|
||||
return this.client.composantModel.findMany({
|
||||
where: typeComposantId ? { typeComposantId } : undefined,
|
||||
include,
|
||||
orderBy: { name: 'asc' },
|
||||
});
|
||||
}
|
||||
|
||||
async findOne(id: string, include?: Prisma.ComposantModelInclude) {
|
||||
return this.client.composantModel.findUnique({
|
||||
where: { id },
|
||||
include,
|
||||
});
|
||||
}
|
||||
|
||||
async update(
|
||||
id: string,
|
||||
data: Prisma.ComposantModelUpdateInput,
|
||||
include?: Prisma.ComposantModelInclude,
|
||||
) {
|
||||
return this.client.composantModel.update({
|
||||
where: { id },
|
||||
data,
|
||||
include,
|
||||
});
|
||||
}
|
||||
|
||||
async delete(id: string) {
|
||||
return this.client.composantModel.delete({
|
||||
where: { id },
|
||||
});
|
||||
}
|
||||
}
|
||||
71
src/common/repositories/model-types.repository.spec.ts
Normal file
71
src/common/repositories/model-types.repository.spec.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { ModelTypesRepository } from './model-types.repository';
|
||||
|
||||
describe('ModelTypesRepository', () => {
|
||||
const prismaMock = {
|
||||
modelType: {
|
||||
findUnique: jest.fn(),
|
||||
create: jest.fn(),
|
||||
findMany: jest.fn(),
|
||||
findFirst: jest.fn(),
|
||||
update: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
},
|
||||
customField: {
|
||||
deleteMany: jest.fn(),
|
||||
createMany: jest.fn(),
|
||||
},
|
||||
} as any;
|
||||
|
||||
const repository = new ModelTypesRepository(prismaMock);
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should generate unique code when conflicts exist', async () => {
|
||||
prismaMock.modelType.findUnique
|
||||
.mockResolvedValueOnce({ id: 'existing' })
|
||||
.mockResolvedValueOnce(null);
|
||||
|
||||
const code = await repository.generateUniqueCode('My Type');
|
||||
|
||||
expect(code).toBe('my-type-1');
|
||||
expect(prismaMock.modelType.findUnique).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it('should create component type custom fields with relation id', async () => {
|
||||
await repository.createComponentTypeCustomFields('comp-id', [
|
||||
{ name: 'Field', type: 'string', required: true, options: [] },
|
||||
]);
|
||||
|
||||
expect(prismaMock.customField.createMany).toHaveBeenCalledWith({
|
||||
data: [
|
||||
{
|
||||
name: 'Field',
|
||||
type: 'string',
|
||||
required: true,
|
||||
options: [],
|
||||
typeComposantId: 'comp-id',
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('should create piece type custom fields with relation id', async () => {
|
||||
await repository.createPieceTypeCustomFields('piece-id', [
|
||||
{ name: 'Field', type: 'string', required: false, options: [] },
|
||||
]);
|
||||
|
||||
expect(prismaMock.customField.createMany).toHaveBeenCalledWith({
|
||||
data: [
|
||||
{
|
||||
name: 'Field',
|
||||
type: 'string',
|
||||
required: false,
|
||||
options: [],
|
||||
typePieceId: 'piece-id',
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
172
src/common/repositories/model-types.repository.ts
Normal file
172
src/common/repositories/model-types.repository.ts
Normal file
@@ -0,0 +1,172 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ModelCategory, Prisma, PrismaClient } from '@prisma/client';
|
||||
import { PrismaService } from '../../prisma/prisma.service';
|
||||
import { slugifyName } from '../utils/slug.util';
|
||||
|
||||
type CustomFieldInput = Omit<
|
||||
Prisma.CustomFieldCreateManyInput,
|
||||
'id' | 'typeMachineId' | 'typePieceId' | 'typeComposantId'
|
||||
>;
|
||||
|
||||
type PieceCustomFieldInput = Omit<
|
||||
Prisma.CustomFieldCreateManyInput,
|
||||
'id' | 'typeMachineId' | 'typePieceId' | 'typeComposantId'
|
||||
>;
|
||||
|
||||
type ModelTypeCreateData = Omit<Prisma.ModelTypeCreateInput, 'category'>;
|
||||
|
||||
@Injectable()
|
||||
export class ModelTypesRepository {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
private get client(): PrismaClient {
|
||||
return this.prisma;
|
||||
}
|
||||
|
||||
async generateUniqueCode(name: string): Promise<string> {
|
||||
const base = slugifyName(name) || 'type';
|
||||
let candidate = base;
|
||||
let suffix = 1;
|
||||
|
||||
while (await this.client.modelType.findUnique({ where: { code: candidate } })) {
|
||||
candidate = `${base}-${suffix++}`;
|
||||
}
|
||||
|
||||
return candidate;
|
||||
}
|
||||
|
||||
async createComponentType(
|
||||
data: ModelTypeCreateData,
|
||||
include?: Prisma.ModelTypeInclude,
|
||||
) {
|
||||
return this.client.modelType.create({
|
||||
data: {
|
||||
...data,
|
||||
category: ModelCategory.COMPONENT,
|
||||
},
|
||||
include,
|
||||
});
|
||||
}
|
||||
|
||||
async findComponentTypes(include?: Prisma.ModelTypeInclude) {
|
||||
return this.client.modelType.findMany({
|
||||
where: { category: ModelCategory.COMPONENT },
|
||||
include,
|
||||
});
|
||||
}
|
||||
|
||||
async findComponentType(id: string, include?: Prisma.ModelTypeInclude) {
|
||||
return this.client.modelType.findFirst({
|
||||
where: { id, category: ModelCategory.COMPONENT },
|
||||
include,
|
||||
});
|
||||
}
|
||||
|
||||
async updateComponentType(
|
||||
id: string,
|
||||
data: Prisma.ModelTypeUpdateInput,
|
||||
include?: Prisma.ModelTypeInclude,
|
||||
) {
|
||||
return this.client.modelType.update({
|
||||
where: { id },
|
||||
data,
|
||||
include,
|
||||
});
|
||||
}
|
||||
|
||||
async deleteComponentType(id: string) {
|
||||
return this.client.modelType.delete({
|
||||
where: { id },
|
||||
});
|
||||
}
|
||||
|
||||
async deleteComponentTypeCustomFields(typeComposantId: string) {
|
||||
await this.client.customField.deleteMany({
|
||||
where: { typeComposantId },
|
||||
});
|
||||
}
|
||||
|
||||
async createComponentTypeCustomFields(
|
||||
typeComposantId: string,
|
||||
customFields: CustomFieldInput[],
|
||||
) {
|
||||
if (!customFields.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.client.customField.createMany({
|
||||
data: customFields.map((field) => ({
|
||||
...field,
|
||||
typeComposantId,
|
||||
})),
|
||||
});
|
||||
}
|
||||
|
||||
async createPieceType(
|
||||
data: ModelTypeCreateData,
|
||||
include?: Prisma.ModelTypeInclude,
|
||||
) {
|
||||
return this.client.modelType.create({
|
||||
data: {
|
||||
...data,
|
||||
category: ModelCategory.PIECE,
|
||||
},
|
||||
include,
|
||||
});
|
||||
}
|
||||
|
||||
async findPieceTypes(include?: Prisma.ModelTypeInclude) {
|
||||
return this.client.modelType.findMany({
|
||||
where: { category: ModelCategory.PIECE },
|
||||
include,
|
||||
orderBy: { name: 'asc' },
|
||||
});
|
||||
}
|
||||
|
||||
async findPieceType(id: string, include?: Prisma.ModelTypeInclude) {
|
||||
return this.client.modelType.findFirst({
|
||||
where: { id, category: ModelCategory.PIECE },
|
||||
include,
|
||||
});
|
||||
}
|
||||
|
||||
async updatePieceType(
|
||||
id: string,
|
||||
data: Prisma.ModelTypeUpdateInput,
|
||||
include?: Prisma.ModelTypeInclude,
|
||||
) {
|
||||
return this.client.modelType.update({
|
||||
where: { id },
|
||||
data,
|
||||
include,
|
||||
});
|
||||
}
|
||||
|
||||
async deletePieceType(id: string) {
|
||||
return this.client.modelType.delete({
|
||||
where: { id },
|
||||
});
|
||||
}
|
||||
|
||||
async deletePieceTypeCustomFields(typePieceId: string) {
|
||||
await this.client.customField.deleteMany({
|
||||
where: { typePieceId },
|
||||
});
|
||||
}
|
||||
|
||||
async createPieceTypeCustomFields(
|
||||
typePieceId: string,
|
||||
customFields: PieceCustomFieldInput[],
|
||||
) {
|
||||
if (!customFields.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.client.customField.createMany({
|
||||
data: customFields.map((field) => ({
|
||||
...field,
|
||||
typePieceId,
|
||||
})),
|
||||
});
|
||||
}
|
||||
}
|
||||
55
src/common/repositories/piece-models.repository.ts
Normal file
55
src/common/repositories/piece-models.repository.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Prisma, PrismaClient } from '@prisma/client';
|
||||
import { PrismaService } from '../../prisma/prisma.service';
|
||||
|
||||
@Injectable()
|
||||
export class PieceModelsRepository {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
private get client(): PrismaClient {
|
||||
return this.prisma;
|
||||
}
|
||||
|
||||
async create(
|
||||
data: Prisma.PieceModelCreateInput,
|
||||
include?: Prisma.PieceModelInclude,
|
||||
) {
|
||||
return this.client.pieceModel.create({
|
||||
data,
|
||||
include,
|
||||
});
|
||||
}
|
||||
|
||||
async findAll(typePieceId?: string, include?: Prisma.PieceModelInclude) {
|
||||
return this.client.pieceModel.findMany({
|
||||
where: typePieceId ? { typePieceId } : undefined,
|
||||
include,
|
||||
orderBy: { name: 'asc' },
|
||||
});
|
||||
}
|
||||
|
||||
async findOne(id: string, include?: Prisma.PieceModelInclude) {
|
||||
return this.client.pieceModel.findUnique({
|
||||
where: { id },
|
||||
include,
|
||||
});
|
||||
}
|
||||
|
||||
async update(
|
||||
id: string,
|
||||
data: Prisma.PieceModelUpdateInput,
|
||||
include?: Prisma.PieceModelInclude,
|
||||
) {
|
||||
return this.client.pieceModel.update({
|
||||
where: { id },
|
||||
data,
|
||||
include,
|
||||
});
|
||||
}
|
||||
|
||||
async delete(id: string) {
|
||||
return this.client.pieceModel.delete({
|
||||
where: { id },
|
||||
});
|
||||
}
|
||||
}
|
||||
117
src/common/repositories/type-machines.repository.spec.ts
Normal file
117
src/common/repositories/type-machines.repository.spec.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
import { TypeMachinesRepository } from './type-machines.repository';
|
||||
|
||||
describe('TypeMachinesRepository', () => {
|
||||
const prismaMock = {
|
||||
customField: {
|
||||
deleteMany: jest.fn(),
|
||||
createMany: jest.fn(),
|
||||
},
|
||||
typeMachineComponentRequirement: {
|
||||
deleteMany: jest.fn(),
|
||||
createMany: jest.fn(),
|
||||
},
|
||||
typeMachinePieceRequirement: {
|
||||
deleteMany: jest.fn(),
|
||||
createMany: jest.fn(),
|
||||
},
|
||||
machine: {
|
||||
findMany: jest.fn().mockResolvedValue([{ id: '1', name: 'Machine' }]),
|
||||
},
|
||||
typeMachine: {
|
||||
create: jest.fn(),
|
||||
findMany: jest.fn(),
|
||||
findUnique: jest.fn(),
|
||||
update: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
},
|
||||
} as any;
|
||||
|
||||
const repository = new TypeMachinesRepository(prismaMock);
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should append typeMachineId when creating custom fields', async () => {
|
||||
await repository.createCustomFields('machine-id', [
|
||||
{ name: 'Field', type: 'string', required: true, options: [] },
|
||||
]);
|
||||
|
||||
expect(prismaMock.customField.createMany).toHaveBeenCalledWith({
|
||||
data: [
|
||||
{
|
||||
name: 'Field',
|
||||
type: 'string',
|
||||
required: true,
|
||||
options: [],
|
||||
typeMachineId: 'machine-id',
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('should append typeMachineId when creating component requirements', async () => {
|
||||
await repository.createComponentRequirements('machine-id', [
|
||||
{
|
||||
label: 'Comp',
|
||||
minCount: 1,
|
||||
maxCount: 2,
|
||||
required: true,
|
||||
allowNewModels: true,
|
||||
typeComposantId: 'comp',
|
||||
},
|
||||
]);
|
||||
|
||||
expect(
|
||||
prismaMock.typeMachineComponentRequirement.createMany,
|
||||
).toHaveBeenCalledWith({
|
||||
data: [
|
||||
{
|
||||
label: 'Comp',
|
||||
minCount: 1,
|
||||
maxCount: 2,
|
||||
required: true,
|
||||
allowNewModels: true,
|
||||
typeComposantId: 'comp',
|
||||
typeMachineId: 'machine-id',
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('should append typeMachineId when creating piece requirements', async () => {
|
||||
await repository.createPieceRequirements('machine-id', [
|
||||
{
|
||||
label: 'Piece',
|
||||
minCount: 0,
|
||||
maxCount: 1,
|
||||
required: false,
|
||||
allowNewModels: true,
|
||||
typePieceId: 'piece',
|
||||
},
|
||||
]);
|
||||
|
||||
expect(prismaMock.typeMachinePieceRequirement.createMany).toHaveBeenCalledWith({
|
||||
data: [
|
||||
{
|
||||
label: 'Piece',
|
||||
minCount: 0,
|
||||
maxCount: 1,
|
||||
required: false,
|
||||
allowNewModels: true,
|
||||
typePieceId: 'piece',
|
||||
typeMachineId: 'machine-id',
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('should find machines using type', async () => {
|
||||
const result = await repository.findMachinesUsingType('machine-id');
|
||||
expect(result).toEqual([{ id: '1', name: 'Machine' }]);
|
||||
expect(prismaMock.machine.findMany).toHaveBeenCalledWith({
|
||||
where: { typeMachineId: 'machine-id' },
|
||||
select: { id: true, name: true },
|
||||
});
|
||||
});
|
||||
});
|
||||
141
src/common/repositories/type-machines.repository.ts
Normal file
141
src/common/repositories/type-machines.repository.ts
Normal file
@@ -0,0 +1,141 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Prisma, PrismaClient } from '@prisma/client';
|
||||
import { PrismaService } from '../../prisma/prisma.service';
|
||||
|
||||
type CustomFieldInput = Omit<
|
||||
Prisma.CustomFieldCreateManyInput,
|
||||
'id' | 'typeMachineId' | 'typePieceId' | 'typeComposantId'
|
||||
>;
|
||||
|
||||
type ComponentRequirementInput = Omit<
|
||||
Prisma.TypeMachineComponentRequirementCreateManyInput,
|
||||
'id' | 'typeMachineId'
|
||||
>;
|
||||
|
||||
type PieceRequirementInput = Omit<
|
||||
Prisma.TypeMachinePieceRequirementCreateManyInput,
|
||||
'id' | 'typeMachineId'
|
||||
>;
|
||||
|
||||
@Injectable()
|
||||
export class TypeMachinesRepository {
|
||||
constructor(private readonly prisma: PrismaService) {}
|
||||
|
||||
private get client(): PrismaClient {
|
||||
return this.prisma;
|
||||
}
|
||||
|
||||
async create(
|
||||
data: Prisma.TypeMachineCreateInput,
|
||||
include?: Prisma.TypeMachineInclude,
|
||||
) {
|
||||
return this.client.typeMachine.create({
|
||||
data,
|
||||
include,
|
||||
});
|
||||
}
|
||||
|
||||
async findAll(include?: Prisma.TypeMachineInclude) {
|
||||
return this.client.typeMachine.findMany({
|
||||
include,
|
||||
});
|
||||
}
|
||||
|
||||
async findOne(id: string, include?: Prisma.TypeMachineInclude) {
|
||||
return this.client.typeMachine.findUnique({
|
||||
where: { id },
|
||||
include,
|
||||
});
|
||||
}
|
||||
|
||||
async update(
|
||||
id: string,
|
||||
data: Prisma.TypeMachineUpdateInput,
|
||||
include?: Prisma.TypeMachineInclude,
|
||||
) {
|
||||
return this.client.typeMachine.update({
|
||||
where: { id },
|
||||
data,
|
||||
include,
|
||||
});
|
||||
}
|
||||
|
||||
async delete(id: string) {
|
||||
return this.client.typeMachine.delete({
|
||||
where: { id },
|
||||
});
|
||||
}
|
||||
|
||||
async deleteCustomFields(typeMachineId: string) {
|
||||
await this.client.customField.deleteMany({
|
||||
where: { typeMachineId },
|
||||
});
|
||||
}
|
||||
|
||||
async createCustomFields(
|
||||
typeMachineId: string,
|
||||
customFields: CustomFieldInput[],
|
||||
) {
|
||||
if (!customFields.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.client.customField.createMany({
|
||||
data: customFields.map((field) => ({
|
||||
...field,
|
||||
typeMachineId,
|
||||
})),
|
||||
});
|
||||
}
|
||||
|
||||
async deleteComponentRequirements(typeMachineId: string) {
|
||||
await this.client.typeMachineComponentRequirement.deleteMany({
|
||||
where: { typeMachineId },
|
||||
});
|
||||
}
|
||||
|
||||
async createComponentRequirements(
|
||||
typeMachineId: string,
|
||||
requirements: ComponentRequirementInput[],
|
||||
) {
|
||||
if (!requirements.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.client.typeMachineComponentRequirement.createMany({
|
||||
data: requirements.map((requirement) => ({
|
||||
...requirement,
|
||||
typeMachineId,
|
||||
})),
|
||||
});
|
||||
}
|
||||
|
||||
async deletePieceRequirements(typeMachineId: string) {
|
||||
await this.client.typeMachinePieceRequirement.deleteMany({
|
||||
where: { typeMachineId },
|
||||
});
|
||||
}
|
||||
|
||||
async createPieceRequirements(
|
||||
typeMachineId: string,
|
||||
requirements: PieceRequirementInput[],
|
||||
) {
|
||||
if (!requirements.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.client.typeMachinePieceRequirement.createMany({
|
||||
data: requirements.map((requirement) => ({
|
||||
...requirement,
|
||||
typeMachineId,
|
||||
})),
|
||||
});
|
||||
}
|
||||
|
||||
async findMachinesUsingType(typeMachineId: string) {
|
||||
return this.client.machine.findMany({
|
||||
where: { typeMachineId },
|
||||
select: { id: true, name: true },
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user