build-address added tested

This commit is contained in:
2025-11-18 16:25:03 +03:00
parent 6a5acd28db
commit 688576a1de
129 changed files with 8116 additions and 385 deletions

View File

@@ -11,6 +11,7 @@ import { BuildPartsModule } from './build-parts/build-parts.module';
import { BuildAreaModule } from './build-area/build-area.module';
import { UserTypesModule } from './user-types/user-types.module';
import { BuildTypesModule } from './build-types/build-types.module';
import { BuildAddressModule } from './build-address/build-address.module';
@Module({
imports: [
@@ -27,6 +28,7 @@ import { BuildTypesModule } from './build-types/build-types.module';
BuildAreaModule,
UserTypesModule,
BuildTypesModule,
BuildAddressModule,
],
controllers: [AppController],
providers: [AppService],

View File

@@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';
import { BuildAddressService } from './build-address.service';
import { BuildAddressResolver } from './build-address.resolver';
import { MongooseModule } from '@nestjs/mongoose';
import { BuildAddress, BuildAddressSchema } from '@/models/build-address.model';
@Module({
imports: [MongooseModule.forFeature([{ name: BuildAddress.name, schema: BuildAddressSchema }])],
providers: [BuildAddressService, BuildAddressResolver]
})
export class BuildAddressModule { }

View File

@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { BuildAddressResolver } from './build-address.resolver';
describe('BuildAddressResolver', () => {
let resolver: BuildAddressResolver;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [BuildAddressResolver],
}).compile();
resolver = module.get<BuildAddressResolver>(BuildAddressResolver);
});
it('should be defined', () => {
expect(resolver).toBeDefined();
});
});

View File

@@ -0,0 +1,37 @@
import { Resolver, Query, Args, ID, Info, Mutation } from '@nestjs/graphql';
import { Types } from 'mongoose';
import { BuildAddress } from '@/models/build-address.model';
import { ListArguments } from '@/dto/list.input';
import { UpdateBuildAddressInput } from './dto/update-build-address.input';
import { ListBuildAddressInput } from './dto/list-build-address.response';
import { CreateBuildAddressInput } from './dto/create-build-address.input';
import graphqlFields from 'graphql-fields';
import { BuildAddressService } from './build-address.service';
import type { GraphQLResolveInfo } from 'graphql';
@Resolver()
export class BuildAddressResolver {
constructor(private readonly buildAddressService: BuildAddressService) { }
@Query(() => ListBuildAddressInput, { name: "buildAddresses" })
async getBuildAddresses(@Info() info: GraphQLResolveInfo, @Args('input') input: ListArguments): Promise<ListBuildAddressInput> {
const fields = graphqlFields(info); const projection = this.buildAddressService.buildProjection(fields?.data); const { skip, limit, sort, filters } = input;
return await this.buildAddressService.findAll(projection, skip, limit, sort, filters);
}
@Query(() => BuildAddress, { name: 'buildAddress', nullable: true })
async getBuildAddress(@Args('id', { type: () => ID }) id: string, @Info() info: GraphQLResolveInfo): Promise<BuildAddress | null> {
const fields = graphqlFields(info); const projection = this.buildAddressService.buildProjection(fields); return this.buildAddressService.findById(new Types.ObjectId(id), projection);
}
@Mutation(() => BuildAddress, { name: 'createBuildAddress' })
async createBuildAddress(@Args('input') input: CreateBuildAddressInput): Promise<BuildAddress> { return this.buildAddressService.create(input) }
@Mutation(() => BuildAddress, { name: 'updateBuildAddress' })
async updateBuildAddress(@Args('uuid') uuid: string, @Args('input') input: UpdateBuildAddressInput): Promise<BuildAddress> { return this.buildAddressService.update(uuid, input) }
@Mutation(() => Boolean, { name: 'deleteBuildAddress' })
async deleteBuildAddress(@Args('uuid') uuid: string): Promise<boolean> { return this.buildAddressService.delete(uuid) }
}

View File

@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { BuildAddressService } from './build-address.service';
describe('BuildAddressService', () => {
let service: BuildAddressService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [BuildAddressService],
}).compile();
service = module.get<BuildAddressService>(BuildAddressService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

View File

@@ -0,0 +1,31 @@
import { Injectable } from '@nestjs/common';
import { UpdateBuildAddressInput } from './dto/update-build-address.input';
import { ListBuildAddressInput } from './dto/list-build-address.response';
import { CreateBuildAddressInput } from './dto/create-build-address.input';
import { InjectModel } from '@nestjs/mongoose';
import { Types, Model } from 'mongoose';
import { BuildAddress, BuildAddressDocument } from '@/models/build-address.model';
@Injectable()
export class BuildAddressService {
constructor(@InjectModel(BuildAddress.name) private readonly buildAddressModel: Model<BuildAddressDocument>) { }
async findAll(projection: any, skip: number, limit: number, sort?: Record<string, 1 | -1>, filters?: Record<string, any>): Promise<ListBuildAddressInput> {
const query: any = {}; if (filters && Object.keys(filters).length > 0) { Object.assign(query, filters) };
const totalCount = await this.buildAddressModel.countDocuments(query).exec();
const data = await this.buildAddressModel.find(query, projection, { lean: true }).skip(skip).limit(limit).sort(sort).exec();
return { data, totalCount };
}
async findById(id: Types.ObjectId, projection?: any): Promise<BuildAddressDocument | null> { return this.buildAddressModel.findById(id, projection, { lean: false }).populate({ path: 'person', select: projection?.person }).exec() }
async create(input: CreateBuildAddressInput): Promise<BuildAddressDocument> { const user = new this.buildAddressModel(input); return user.save() }
async update(uuid: string, input: UpdateBuildAddressInput): Promise<BuildAddressDocument> { const user = await this.buildAddressModel.findOne({ uuid }); if (!user) { throw new Error('User not found') }; user.set(input); console.dir({ uuid, input }, { depth: null }); return user.save() }
async delete(uuid: string): Promise<boolean> { const user = await this.buildAddressModel.deleteMany({ uuid }); return user.deletedCount > 0 }
buildProjection(fields: Record<string, any>): Record<string, 1> { const projection: Record<string, 1> = {}; for (const key in fields) { projection[key] = 1 }; return projection }
}

View File

@@ -0,0 +1,32 @@
import { InputType, Field, Float, ID } from "@nestjs/graphql";
import { Types } from "mongoose";
@InputType()
export class CreateBuildAddressInput {
@Field()
buildNumber: string;
@Field()
doorNumber: string;
@Field()
floorNumber: string;
@Field()
commentAddress: string;
@Field()
letterAddress: string;
@Field()
shortLetterAddress: string;
@Field(() => Float)
latitude: number;
@Field(() => Float)
longitude: number;
@Field(() => ID, { nullable: true })
street?: Types.ObjectId;
}

View File

@@ -0,0 +1,14 @@
import { ObjectType, Field, Int } from "@nestjs/graphql";
import { BuildAddress } from "@/models/build-address.model";
@ObjectType()
export class ListBuildAddressInput {
@Field(() => [BuildAddress], { nullable: true })
data?: BuildAddress[];
@Field(() => Int, { nullable: true })
totalCount?: number;
}

View File

@@ -0,0 +1,34 @@
import { InputType, Field, Float, ID } from "@nestjs/graphql";
import { Types } from "mongoose";
@InputType()
export class UpdateBuildAddressInput {
@Field({ nullable: true })
buildNumber?: string;
@Field({ nullable: true })
doorNumber?: string;
@Field({ nullable: true })
floorNumber?: string;
@Field({ nullable: true })
commentAddress?: string;
@Field({ nullable: true })
letterAddress?: string;
@Field({ nullable: true })
shortLetterAddress?: string;
@Field(() => Float, { nullable: true })
latitude?: number;
@Field(() => Float, { nullable: true })
longitude?: number;
@Field(() => ID, { nullable: true })
street?: Types.ObjectId;
}

View File

@@ -3,6 +3,7 @@ import { Field, Int, InputType, ObjectType } from '@nestjs/graphql';
@InputType()
export class ListArguments {
@Field(() => GraphQLJSONObject, { nullable: true })
filters?: any;

View File

@@ -6,6 +6,10 @@ import { Base } from '@/models/base.model';
@ObjectType()
@Schema({ timestamps: true })
export class BuildAddress extends Base {
@Field(() => ID)
readonly _id: string;
@Field()
@Prop({ required: true })
buildNumber: string;
@@ -38,9 +42,10 @@ export class BuildAddress extends Base {
@Prop({ required: true })
longitude: number;
@Field(() => ID)
@Prop({ type: Types.ObjectId, ref: 'Street', required: true })
street: Types.ObjectId;
@Field(() => ID, { nullable: true })
@Prop({ type: Types.ObjectId, ref: 'Street', required: false })
street?: Types.ObjectId;
}
export type BuildAddressDocument = BuildAddress & Document;

View File

@@ -3,9 +3,11 @@ import { Person } from "@/models/person.model";
@ObjectType()
export class ListPeopleResponse {
@Field(() => [Person], { nullable: true })
data?: Person[];
@Field(() => Int, { nullable: true })
totalCount?: number;
}

View File

@@ -5,9 +5,7 @@ import { UsersService } from './users.service';
import { UserSchema, User } from '@/models/user.model';
@Module({
imports: [
MongooseModule.forFeature([{ name: User.name, schema: UserSchema }])
],
imports: [MongooseModule.forFeature([{ name: User.name, schema: UserSchema }])],
providers: [UsersService, UsersResolver],
})
export class UsersModule { }