parts and areas tested
This commit is contained in:
11
backend/src/company/company.module.ts
Normal file
11
backend/src/company/company.module.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { CompanyService } from './company.service';
|
||||
import { CompanyResolver } from './company.resolver';
|
||||
import { MongooseModule } from '@nestjs/mongoose';
|
||||
import { Company, CompanySchema } from '@/models/company.model';
|
||||
|
||||
@Module({
|
||||
imports: [MongooseModule.forFeature([{ name: Company.name, schema: CompanySchema }])],
|
||||
providers: [CompanyService, CompanyResolver]
|
||||
})
|
||||
export class CompanyModule { }
|
||||
18
backend/src/company/company.resolver.spec.ts
Normal file
18
backend/src/company/company.resolver.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { CompanyResolver } from './company.resolver';
|
||||
|
||||
describe('CompanyResolver', () => {
|
||||
let resolver: CompanyResolver;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [CompanyResolver],
|
||||
}).compile();
|
||||
|
||||
resolver = module.get<CompanyResolver>(CompanyResolver);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(resolver).toBeDefined();
|
||||
});
|
||||
});
|
||||
29
backend/src/company/company.resolver.ts
Normal file
29
backend/src/company/company.resolver.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Resolver, Args, ID, Info, Mutation, Query } from '@nestjs/graphql';
|
||||
import { CompanyService } from './company.service';
|
||||
import { Company } from '@/models/company.model';
|
||||
import { CreateCompanyInput } from './dto/create-company.input';
|
||||
import { Types } from 'mongoose';
|
||||
import graphqlFields from 'graphql-fields';
|
||||
import type { GraphQLResolveInfo } from 'graphql';
|
||||
import { ListCompanyResponse } from './dto/list-company.response';
|
||||
import { ListArguments } from '@/dto/list.input';
|
||||
|
||||
@Resolver()
|
||||
export class CompanyResolver {
|
||||
|
||||
constructor(private readonly companyService: CompanyService) { }
|
||||
|
||||
@Query(() => ListCompanyResponse, { name: 'companies' })
|
||||
async getCompanies(@Info() info: GraphQLResolveInfo, @Args('input') input: ListArguments): Promise<ListCompanyResponse> {
|
||||
const fields = graphqlFields(info); const projection = this.companyService.buildProjection(fields); return this.companyService.findAll(input.skip, input.limit, input.sort, input.filters);
|
||||
}
|
||||
|
||||
@Query(() => Company, { name: 'company', nullable: true })
|
||||
async getCompany(@Args('id', { type: () => ID }) id: string, @Info() info: GraphQLResolveInfo): Promise<Company | null> {
|
||||
const fields = graphqlFields(info); const projection = this.companyService.buildProjection(fields); return this.companyService.findById(new Types.ObjectId(id), projection);
|
||||
}
|
||||
|
||||
@Mutation(() => Company, { name: 'createCompany' })
|
||||
async createCompany(@Args('input') input: CreateCompanyInput): Promise<Company> { return this.companyService.create(input) }
|
||||
|
||||
}
|
||||
18
backend/src/company/company.service.spec.ts
Normal file
18
backend/src/company/company.service.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { CompanyService } from './company.service';
|
||||
|
||||
describe('CompanyService', () => {
|
||||
let service: CompanyService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [CompanyService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<CompanyService>(CompanyService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
39
backend/src/company/company.service.ts
Normal file
39
backend/src/company/company.service.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectModel } from '@nestjs/mongoose';
|
||||
import { Types, Model } from 'mongoose';
|
||||
import { Company, CompanyDocument } from '@/models/company.model';
|
||||
import { CreateCompanyInput } from './dto/create-company.input';
|
||||
import { ListCompanyResponse } from './dto/list-company.response';
|
||||
import { UpdateCompanyInput } from './dto/update-company.input';
|
||||
|
||||
@Injectable()
|
||||
export class CompanyService {
|
||||
|
||||
constructor(@InjectModel(Company.name) private readonly companyModel: Model<CompanyDocument>) { }
|
||||
|
||||
async findAll(projection: any, skip: number, limit: number, sort?: Record<string, 1 | -1>, filters?: Record<string, any>): Promise<ListCompanyResponse> {
|
||||
const query: any = {}; if (filters && Object.keys(filters).length > 0) { Object.assign(query, filters) };
|
||||
const totalCount = await this.companyModel.countDocuments(query).exec();
|
||||
const data = await this.companyModel.find(query, projection, { lean: true }).skip(skip).limit(limit).sort(sort).exec();
|
||||
return { data, totalCount };
|
||||
}
|
||||
|
||||
async findById(id: Types.ObjectId, projection?: any): Promise<CompanyDocument | null> {
|
||||
return this.companyModel.findById(id, projection, { lean: false }).populate({ path: 'company', select: projection?.company }).exec();
|
||||
}
|
||||
|
||||
async create(input: CreateCompanyInput): Promise<CompanyDocument> { const company = new this.companyModel(input); return company.save() }
|
||||
|
||||
async update(uuid: string, input: UpdateCompanyInput): Promise<CompanyDocument> { const company = await this.companyModel.findOne({ uuid }); if (!company) { throw new Error('Company not found') }; company.set(input); return company.save() }
|
||||
|
||||
async delete(uuid: string): Promise<boolean> { const company = await this.companyModel.deleteMany({ uuid }); return company.deletedCount > 0 }
|
||||
|
||||
buildProjection(fields: Record<string, any>): any {
|
||||
const projection: any = {};
|
||||
for (const key in fields) {
|
||||
if (key === 'buildSites' && typeof fields[key] === 'object') { for (const subField of Object.keys(fields[key])) { projection[`buildSites.${subField}`] = 1 } }
|
||||
else { projection[key] = 1 }
|
||||
}; return projection;
|
||||
}
|
||||
|
||||
}
|
||||
11
backend/src/company/dto/create-company.input.ts
Normal file
11
backend/src/company/dto/create-company.input.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
import { InputType, Field, ID } from '@nestjs/graphql';
|
||||
|
||||
|
||||
@InputType()
|
||||
export class CreateCompanyInput {
|
||||
|
||||
@Field()
|
||||
name: string;
|
||||
|
||||
}
|
||||
14
backend/src/company/dto/list-company.response.ts
Normal file
14
backend/src/company/dto/list-company.response.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { Field, ObjectType } from "@nestjs/graphql";
|
||||
import { Int } from "@nestjs/graphql";
|
||||
import { Company } from "@/models/company.model";
|
||||
|
||||
@ObjectType()
|
||||
export class ListCompanyResponse {
|
||||
|
||||
@Field(() => [Company], { nullable: true })
|
||||
data?: Company[];
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
totalCount?: number;
|
||||
|
||||
}
|
||||
9
backend/src/company/dto/update-company.input.ts
Normal file
9
backend/src/company/dto/update-company.input.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { InputType, Field, ID } from '@nestjs/graphql';
|
||||
|
||||
@InputType()
|
||||
export class UpdateCompanyInput {
|
||||
|
||||
@Field({ nullable: true })
|
||||
name?: string;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user