Compare commits
20 Commits
main
...
developmen
| Author | SHA1 | Date |
|---|---|---|
|
|
53e1f1e4fc | |
|
|
56b42bb906 | |
|
|
5bb6021102 | |
|
|
0394d42d02 | |
|
|
d22fc017df | |
|
|
eaca36573e | |
|
|
3aebb79d36 | |
|
|
2062aa7a1d | |
|
|
eedfed1a65 | |
|
|
a5a7a7e7b5 | |
|
|
44f209ae1f | |
|
|
688576a1de | |
|
|
6a5acd28db | |
|
|
f870c2e62e | |
|
|
cf4f632afe | |
|
|
a67170daa8 | |
|
|
2e329d8dfe | |
|
|
42983eab65 | |
|
|
45f6b7a1ef | |
|
|
053586c5cc |
|
|
@ -0,0 +1,56 @@
|
|||
# compiled output
|
||||
/dist
|
||||
/node_modules
|
||||
/build
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
pnpm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
|
||||
# Tests
|
||||
/coverage
|
||||
/.nyc_output
|
||||
|
||||
# IDEs and editors
|
||||
/.idea
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
*.launch
|
||||
.settings/
|
||||
*.sublime-workspace
|
||||
|
||||
# IDE - VSCode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# temp directory
|
||||
.temp
|
||||
.tmp
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all"
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
FROM node:20-alpine
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# Copy package files
|
||||
COPY package*.json ./
|
||||
|
||||
RUN npm install
|
||||
|
||||
# Copy everything from root
|
||||
COPY . .
|
||||
|
||||
RUN npm run build
|
||||
|
||||
EXPOSE 4000
|
||||
|
||||
CMD ["node", "dist/server.js"]
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
<p align="center">
|
||||
<a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo-small.svg" width="120" alt="Nest Logo" /></a>
|
||||
</p>
|
||||
|
||||
[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
|
||||
[circleci-url]: https://circleci.com/gh/nestjs/nest
|
||||
|
||||
<p align="center">A progressive <a href="http://nodejs.org" target="_blank">Node.js</a> framework for building efficient and scalable server-side applications.</p>
|
||||
<p align="center">
|
||||
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
|
||||
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
|
||||
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/dm/@nestjs/common.svg" alt="NPM Downloads" /></a>
|
||||
<a href="https://circleci.com/gh/nestjs/nest" target="_blank"><img src="https://img.shields.io/circleci/build/github/nestjs/nest/master" alt="CircleCI" /></a>
|
||||
<a href="https://discord.gg/G7Qnnhy" target="_blank"><img src="https://img.shields.io/badge/discord-online-brightgreen.svg" alt="Discord"/></a>
|
||||
<a href="https://opencollective.com/nest#backer" target="_blank"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
|
||||
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
|
||||
<a href="https://paypal.me/kamilmysliwiec" target="_blank"><img src="https://img.shields.io/badge/Donate-PayPal-ff3f59.svg" alt="Donate us"/></a>
|
||||
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://img.shields.io/badge/Support%20us-Open%20Collective-41B883.svg" alt="Support us"></a>
|
||||
<a href="https://twitter.com/nestframework" target="_blank"><img src="https://img.shields.io/twitter/follow/nestframework.svg?style=social&label=Follow" alt="Follow us on Twitter"></a>
|
||||
</p>
|
||||
<!--[](https://opencollective.com/nest#backer)
|
||||
[](https://opencollective.com/nest#sponsor)-->
|
||||
|
||||
## Description
|
||||
|
||||
[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
|
||||
|
||||
## Project setup
|
||||
|
||||
```bash
|
||||
$ npm install
|
||||
```
|
||||
|
||||
## Compile and run the project
|
||||
|
||||
```bash
|
||||
# development
|
||||
$ npm run start
|
||||
|
||||
# watch mode
|
||||
$ npm run start:dev
|
||||
|
||||
# production mode
|
||||
$ npm run start:prod
|
||||
```
|
||||
|
||||
## Run tests
|
||||
|
||||
```bash
|
||||
# unit tests
|
||||
$ npm run test
|
||||
|
||||
# e2e tests
|
||||
$ npm run test:e2e
|
||||
|
||||
# test coverage
|
||||
$ npm run test:cov
|
||||
```
|
||||
|
||||
## Deployment
|
||||
|
||||
When you're ready to deploy your NestJS application to production, there are some key steps you can take to ensure it runs as efficiently as possible. Check out the [deployment documentation](https://docs.nestjs.com/deployment) for more information.
|
||||
|
||||
If you are looking for a cloud-based platform to deploy your NestJS application, check out [Mau](https://mau.nestjs.com), our official platform for deploying NestJS applications on AWS. Mau makes deployment straightforward and fast, requiring just a few simple steps:
|
||||
|
||||
```bash
|
||||
$ npm install -g @nestjs/mau
|
||||
$ mau deploy
|
||||
```
|
||||
|
||||
With Mau, you can deploy your application in just a few clicks, allowing you to focus on building features rather than managing infrastructure.
|
||||
|
||||
## Resources
|
||||
|
||||
Check out a few resources that may come in handy when working with NestJS:
|
||||
|
||||
- Visit the [NestJS Documentation](https://docs.nestjs.com) to learn more about the framework.
|
||||
- For questions and support, please visit our [Discord channel](https://discord.gg/G7Qnnhy).
|
||||
- To dive deeper and get more hands-on experience, check out our official video [courses](https://courses.nestjs.com/).
|
||||
- Deploy your application to AWS with the help of [NestJS Mau](https://mau.nestjs.com) in just a few clicks.
|
||||
- Visualize your application graph and interact with the NestJS application in real-time using [NestJS Devtools](https://devtools.nestjs.com).
|
||||
- Need help with your project (part-time to full-time)? Check out our official [enterprise support](https://enterprise.nestjs.com).
|
||||
- To stay in the loop and get updates, follow us on [X](https://x.com/nestframework) and [LinkedIn](https://linkedin.com/company/nestjs).
|
||||
- Looking for a job, or have a job to offer? Check out our official [Jobs board](https://jobs.nestjs.com).
|
||||
|
||||
## Support
|
||||
|
||||
Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
|
||||
|
||||
## Stay in touch
|
||||
|
||||
- Author - [Kamil Myśliwiec](https://twitter.com/kammysliwiec)
|
||||
- Website - [https://nestjs.com](https://nestjs.com/)
|
||||
- Twitter - [@nestframework](https://twitter.com/nestframework)
|
||||
|
||||
## License
|
||||
|
||||
Nest is [MIT licensed](https://github.com/nestjs/nest/blob/master/LICENSE).
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
// @ts-check
|
||||
import eslint from '@eslint/js';
|
||||
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
|
||||
import globals from 'globals';
|
||||
import tseslint from 'typescript-eslint';
|
||||
|
||||
export default tseslint.config(
|
||||
{
|
||||
ignores: ['eslint.config.mjs'],
|
||||
},
|
||||
eslint.configs.recommended,
|
||||
...tseslint.configs.recommendedTypeChecked,
|
||||
eslintPluginPrettierRecommended,
|
||||
{
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node,
|
||||
...globals.jest,
|
||||
},
|
||||
sourceType: 'commonjs',
|
||||
parserOptions: {
|
||||
projectService: true,
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
rules: {
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-floating-promises': 'warn',
|
||||
'@typescript-eslint/no-unsafe-argument': 'warn',
|
||||
"prettier/prettier": ["error", { endOfLine: "auto" }],
|
||||
},
|
||||
},
|
||||
);
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/nest-cli",
|
||||
"collection": "@nestjs/schematics",
|
||||
"sourceRoot": "src",
|
||||
"compilerOptions": {
|
||||
"deleteOutDir": true
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,82 @@
|
|||
{
|
||||
"name": "backend",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"author": "",
|
||||
"private": true,
|
||||
"license": "UNLICENSED",
|
||||
"scripts": {
|
||||
"build": "nest build",
|
||||
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
||||
"start": "nest start",
|
||||
"start:dev": "nest start --watch",
|
||||
"start:debug": "nest start --debug --watch",
|
||||
"start:prod": "node dist/main",
|
||||
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
|
||||
"test": "jest",
|
||||
"test:watch": "jest --watch",
|
||||
"test:cov": "jest --coverage",
|
||||
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
||||
"test:e2e": "jest --config ./test/jest-e2e.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@apollo/server": "^5.1.0",
|
||||
"@as-integrations/express5": "^1.1.2",
|
||||
"@nestjs/apollo": "^13.2.1",
|
||||
"@nestjs/common": "^11.0.1",
|
||||
"@nestjs/core": "^11.0.1",
|
||||
"@nestjs/graphql": "^13.2.0",
|
||||
"@nestjs/mongoose": "^11.0.3",
|
||||
"@nestjs/platform-express": "^11.0.1",
|
||||
"graphql": "^16.12.0",
|
||||
"graphql-fields": "^2.0.3",
|
||||
"graphql-type-json": "^0.3.2",
|
||||
"mongoose": "^8.19.3",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"rxjs": "^7.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.2.0",
|
||||
"@eslint/js": "^9.18.0",
|
||||
"@nestjs/cli": "^11.0.0",
|
||||
"@nestjs/schematics": "^11.0.0",
|
||||
"@nestjs/testing": "^11.0.1",
|
||||
"@types/express": "^5.0.0",
|
||||
"@types/graphql": "^14.2.3",
|
||||
"@types/graphql-fields": "^1.3.9",
|
||||
"@types/jest": "^30.0.0",
|
||||
"@types/node": "^22.10.7",
|
||||
"@types/supertest": "^6.0.2",
|
||||
"eslint": "^9.18.0",
|
||||
"eslint-config-prettier": "^10.0.1",
|
||||
"eslint-plugin-prettier": "^5.2.2",
|
||||
"globals": "^16.0.0",
|
||||
"jest": "^30.0.0",
|
||||
"prettier": "^3.4.2",
|
||||
"source-map-support": "^0.5.21",
|
||||
"supertest": "^7.0.0",
|
||||
"ts-jest": "^29.2.5",
|
||||
"ts-loader": "^9.5.2",
|
||||
"ts-node": "^10.9.2",
|
||||
"tsconfig-paths": "^4.2.0",
|
||||
"typescript": "^5.7.3",
|
||||
"typescript-eslint": "^8.20.0"
|
||||
},
|
||||
"jest": {
|
||||
"moduleFileExtensions": [
|
||||
"js",
|
||||
"json",
|
||||
"ts"
|
||||
],
|
||||
"rootDir": "src",
|
||||
"testRegex": ".*\\.spec\\.ts$",
|
||||
"transform": {
|
||||
"^.+\\.(t|j)s$": "ts-jest"
|
||||
},
|
||||
"collectCoverageFrom": [
|
||||
"**/*.(t|j)s"
|
||||
],
|
||||
"coverageDirectory": "../coverage",
|
||||
"testEnvironment": "node"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
|
||||
describe('AppController', () => {
|
||||
let appController: AppController;
|
||||
|
||||
beforeEach(async () => {
|
||||
const app: TestingModule = await Test.createTestingModule({
|
||||
controllers: [AppController],
|
||||
providers: [AppService],
|
||||
}).compile();
|
||||
|
||||
appController = app.get<AppController>(AppController);
|
||||
});
|
||||
|
||||
describe('root', () => {
|
||||
it('should return "Hello World!"', () => {
|
||||
expect(appController.getHello()).toBe('Hello World!');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import { Controller, Get } from '@nestjs/common';
|
||||
import { AppService } from './app.service';
|
||||
|
||||
@Controller()
|
||||
export class AppController {
|
||||
constructor(private readonly appService: AppService) { }
|
||||
|
||||
@Get()
|
||||
getHello(): string {
|
||||
return this.appService.getHello();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { AppController } from './app.controller';
|
||||
import { AppService } from './app.service';
|
||||
import { GraphQLModule } from '@nestjs/graphql';
|
||||
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
|
||||
import { MongooseModule } from '@nestjs/mongoose';
|
||||
import { UsersModule } from './users/users.module';
|
||||
import { PeopleModule } from './people/people.module';
|
||||
import { BuildModule } from './builds/build.module';
|
||||
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';
|
||||
import { BuildIbanModule } from './build-iban/build-iban.module';
|
||||
import { BuildSitesModule } from './build-sites/build-sites.module';
|
||||
import { CompanyModule } from './company/company.module';
|
||||
import { LivingSpaceModule } from './living-space/living-space.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
GraphQLModule.forRoot<ApolloDriverConfig>({
|
||||
driver: ApolloDriver,
|
||||
autoSchemaFile: true,
|
||||
playground: true,
|
||||
}),
|
||||
MongooseModule.forRoot(process.env.MONGODB_URI || "mongodb://evyosdbuser:evyosdbpassword@10.10.2.13:27017/evyosdb"),
|
||||
BuildModule,
|
||||
UsersModule,
|
||||
PeopleModule,
|
||||
BuildPartsModule,
|
||||
BuildAreaModule,
|
||||
UserTypesModule,
|
||||
BuildTypesModule,
|
||||
BuildAddressModule,
|
||||
BuildIbanModule,
|
||||
BuildSitesModule,
|
||||
CompanyModule,
|
||||
LivingSpaceModule,
|
||||
],
|
||||
controllers: [AppController],
|
||||
providers: [AppService],
|
||||
})
|
||||
export class AppModule { }
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
@Injectable()
|
||||
export class AppService {
|
||||
getHello(): string {
|
||||
return 'Hello World!';
|
||||
}
|
||||
}
|
||||
|
|
@ -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 { }
|
||||
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
|
@ -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) }
|
||||
|
||||
}
|
||||
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
|
@ -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 }
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { BuildAreaResolver } from './build-area.resolver';
|
||||
import { BuildAreaService } from './build-area.service';
|
||||
import { MongooseModule } from '@nestjs/mongoose';
|
||||
import { BuildArea, BuildAreaSchema } from '@/models/build-area.model';
|
||||
import { Build, BuildSchema } from '@/models/build.model';
|
||||
|
||||
@Module({
|
||||
imports: [MongooseModule.forFeature([
|
||||
{ name: BuildArea.name, schema: BuildAreaSchema },
|
||||
{ name: Build.name, schema: BuildSchema }
|
||||
])],
|
||||
providers: [BuildAreaResolver, BuildAreaService]
|
||||
})
|
||||
export class BuildAreaModule { }
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { BuildAreaResolver } from './build-area.resolver';
|
||||
|
||||
describe('BuildAreaResolver', () => {
|
||||
let resolver: BuildAreaResolver;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [BuildAreaResolver],
|
||||
}).compile();
|
||||
|
||||
resolver = module.get<BuildAreaResolver>(BuildAreaResolver);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(resolver).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
import { Resolver, Query, Args, ID, Info, Mutation } from '@nestjs/graphql';
|
||||
import { Types } from 'mongoose';
|
||||
import { BuildArea } from '@/models/build-area.model';
|
||||
import { BuildAreaService } from './build-area.service';
|
||||
import { ListArguments } from '@/dto/list.input';
|
||||
import { UpdateBuildAreaInput } from './dto/update-build-area.input';
|
||||
import { ListBuildAreaResponse } from './dto/list-build-area.response';
|
||||
import { CreateBuildAreaInput } from './dto/create-build-area.input';
|
||||
import graphqlFields from 'graphql-fields';
|
||||
import type { GraphQLResolveInfo } from 'graphql';
|
||||
|
||||
@Resolver()
|
||||
export class BuildAreaResolver {
|
||||
|
||||
constructor(private readonly buildAreaService: BuildAreaService) { }
|
||||
|
||||
@Query(() => ListBuildAreaResponse, { name: 'buildAreas' })
|
||||
async getBuildAreas(@Info() info: GraphQLResolveInfo, @Args('input') input: ListArguments): Promise<ListBuildAreaResponse> {
|
||||
const fields = graphqlFields(info); const projection = this.buildAreaService.buildProjection(fields?.data); return await this.buildAreaService.findAll(projection, input);
|
||||
}
|
||||
|
||||
@Query(() => BuildArea, { name: 'getBuildArea', nullable: true })
|
||||
async getBuildArea(@Args('id', { type: () => ID }) id: string, @Info() info: GraphQLResolveInfo): Promise<BuildArea | null> {
|
||||
const fields = graphqlFields(info); const projection = this.buildAreaService.buildProjection(fields); return this.buildAreaService.findById(new Types.ObjectId(id), projection);
|
||||
}
|
||||
|
||||
@Mutation(() => BuildArea, { name: 'createBuildArea' })
|
||||
async createBuildArea(@Args('input') input: CreateBuildAreaInput): Promise<BuildArea> { return this.buildAreaService.create(input) }
|
||||
|
||||
@Mutation(() => BuildArea, { name: 'updateBuildArea' })
|
||||
async updateBuildArea(@Args('uuid') uuid: string, @Args('input') input: UpdateBuildAreaInput): Promise<BuildArea> { return this.buildAreaService.update(uuid, input) }
|
||||
|
||||
@Mutation(() => Boolean, { name: 'deleteBuildArea' })
|
||||
async deleteBuildArea(@Args('uuid') uuid: string): Promise<boolean> { return this.buildAreaService.delete(uuid) }
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { BuildAreaService } from './build-area.service';
|
||||
|
||||
describe('BuildAreaService', () => {
|
||||
let service: BuildAreaService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [BuildAreaService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<BuildAreaService>(BuildAreaService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectModel } from '@nestjs/mongoose';
|
||||
import { Types, Model } from 'mongoose';
|
||||
import { BuildArea, BuildAreaDocument } from '@/models/build-area.model';
|
||||
import { CreateBuildAreaInput } from './dto/create-build-area.input';
|
||||
import { ListBuildAreaResponse } from './dto/list-build-area.response';
|
||||
import { UpdateBuildAreaInput } from './dto/update-build-area.input';
|
||||
import { ListArguments } from '@/dto/list.input';
|
||||
import { Build, BuildDocument } from '@/models/build.model';
|
||||
|
||||
@Injectable()
|
||||
export class BuildAreaService {
|
||||
|
||||
constructor(
|
||||
@InjectModel(BuildArea.name) private readonly buildAreaModel: Model<BuildAreaDocument>,
|
||||
@InjectModel(Build.name) private readonly buildModel: Model<BuildDocument>
|
||||
) { }
|
||||
|
||||
async findAll(projection: any, listArguments: ListArguments): Promise<ListBuildAreaResponse> {
|
||||
const { skip, limit, sort, filters } = listArguments;
|
||||
const query: any = {}; if (filters && Object.keys(filters).length > 0) { Object.assign(query, filters) };
|
||||
if (filters?.buildId) { query.buildId = new Types.ObjectId(filters?.buildId) };
|
||||
const totalCount = await this.buildAreaModel.countDocuments(query).exec();
|
||||
const data = await this.buildAreaModel.find(query, projection, { lean: true }).skip(skip).limit(limit).sort(sort).exec();
|
||||
return { data, totalCount };
|
||||
}
|
||||
|
||||
async findById(id: Types.ObjectId, projection?: any): Promise<BuildAreaDocument | null> { return this.buildAreaModel.findById(id, projection, { lean: false }).populate({ path: 'buildArea', select: projection?.buildArea }).exec() }
|
||||
|
||||
async create(input: CreateBuildAreaInput): Promise<BuildAreaDocument> {
|
||||
const getBuildID = await this.buildModel.findById(input?.buildId, { _id: 1 }, { lean: true }).exec();
|
||||
if (getBuildID) { input.buildId = new Types.ObjectId(getBuildID._id) };
|
||||
const buildArea = new this.buildAreaModel(input); return buildArea.save()
|
||||
}
|
||||
|
||||
async update(uuid: string, input: UpdateBuildAreaInput): Promise<BuildAreaDocument> { const buildArea = await this.buildAreaModel.findOne({ uuid }); if (!buildArea) { throw new Error('BuildArea not found') }; buildArea.set(input); return buildArea.save() }
|
||||
|
||||
async delete(uuid: string): Promise<boolean> { const buildArea = await this.buildAreaModel.deleteMany({ uuid }); return buildArea.deletedCount > 0 }
|
||||
|
||||
buildProjection(fields: Record<string, any>): any {
|
||||
const projection: any = {};
|
||||
for (const key in fields) {
|
||||
if (key === 'buildArea' && typeof fields[key] === 'object') { for (const subField of Object.keys(fields[key])) { projection[`buildArea.${subField}`] = 1 } }
|
||||
else { projection[key] = 1 }
|
||||
}; return projection;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
import { ExpiryBaseInput } from "@/models/base.model";
|
||||
import { InputType, Field, ID, Float } from "@nestjs/graphql";
|
||||
import { Types } from "mongoose";
|
||||
|
||||
@InputType()
|
||||
export class CreateBuildAreaInput extends ExpiryBaseInput {
|
||||
|
||||
@Field(() => ID, { nullable: false })
|
||||
buildId: Types.ObjectId;
|
||||
|
||||
@Field(() => ID, { nullable: true })
|
||||
partTypeId?: Types.ObjectId;
|
||||
|
||||
@Field()
|
||||
areaName: string;
|
||||
|
||||
@Field()
|
||||
areaCode: string;
|
||||
|
||||
@Field()
|
||||
areaType: string;
|
||||
|
||||
@Field()
|
||||
areaDirection: string;
|
||||
|
||||
@Field(() => Float)
|
||||
areaGrossSize: number;
|
||||
|
||||
@Field(() => Float)
|
||||
areaNetSize: number;
|
||||
|
||||
@Field(() => Float)
|
||||
width: number;
|
||||
|
||||
@Field(() => Float)
|
||||
size: number;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import { ObjectType, Field, Int } from "@nestjs/graphql";
|
||||
import { BuildArea } from "@/models/build-area.model";
|
||||
|
||||
@ObjectType()
|
||||
export class ListBuildAreaResponse {
|
||||
|
||||
@Field(() => [BuildArea], { nullable: true })
|
||||
data?: BuildArea[];
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
totalCount?: number;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
import { InputType, Field, Float, ID } from "@nestjs/graphql";
|
||||
import { Types } from "mongoose";
|
||||
|
||||
@InputType()
|
||||
export class UpdateBuildAreaInput {
|
||||
|
||||
@Field(() => ID, { nullable: true })
|
||||
build?: Types.ObjectId;
|
||||
|
||||
@Field(() => ID, { nullable: true })
|
||||
partType?: Types.ObjectId;
|
||||
|
||||
@Field({ nullable: true })
|
||||
areaName?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
areaCode?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
areaType?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
areaDirection?: string;
|
||||
|
||||
@Field(() => Float, { nullable: true })
|
||||
areaGrossSize?: number;
|
||||
|
||||
@Field(() => Float, { nullable: true })
|
||||
areaNetSize?: number;
|
||||
|
||||
@Field(() => Float, { nullable: true })
|
||||
width?: number;
|
||||
|
||||
@Field(() => Float, { nullable: true })
|
||||
size?: number;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { BuildIbanResolver } from './build-iban.resolver';
|
||||
import { BuildIbanService } from './build-iban.service';
|
||||
import { MongooseModule } from '@nestjs/mongoose';
|
||||
import { BuildIban, BuildIbanSchema, Build, BuildSchema } from '@/models/build.model';
|
||||
|
||||
@Module({
|
||||
imports: [MongooseModule.forFeature([
|
||||
{ name: BuildIban.name, schema: BuildIbanSchema }, { name: Build.name, schema: BuildSchema }
|
||||
])],
|
||||
providers: [BuildIbanResolver, BuildIbanService]
|
||||
})
|
||||
export class BuildIbanModule { }
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { BuildIbanResolver } from './build-iban.resolver';
|
||||
|
||||
describe('BuildIbanResolver', () => {
|
||||
let resolver: BuildIbanResolver;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [BuildIbanResolver],
|
||||
}).compile();
|
||||
|
||||
resolver = module.get<BuildIbanResolver>(BuildIbanResolver);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(resolver).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
import { Resolver, Query, Args, ID, Info, Mutation } from '@nestjs/graphql';
|
||||
import { BuildIban } from '@/models/build.model';
|
||||
import graphqlFields from 'graphql-fields';
|
||||
import { Types } from 'mongoose';
|
||||
import { CreateBuildIbanInput } from './dto/create-build-ibans.input';
|
||||
import { UpdateBuildIbanInput } from './dto/update-build-ibans.input';
|
||||
import { ListBuildIbanResponse } from './dto/list-build-ibans.response';
|
||||
import { ListArguments } from '@/dto/list.input';
|
||||
import { BuildIbanService } from './build-iban.service';
|
||||
import type { GraphQLResolveInfo } from 'graphql';
|
||||
|
||||
@Resolver()
|
||||
export class BuildIbanResolver {
|
||||
|
||||
constructor(private readonly buildIbanService: BuildIbanService) { }
|
||||
|
||||
@Query(() => ListBuildIbanResponse, { name: 'buildIbans' })
|
||||
async getBuildIbans(@Info() info: GraphQLResolveInfo, @Args('input') input: ListArguments): Promise<ListBuildIbanResponse> {
|
||||
const fields = graphqlFields(info); const projection = this.buildIbanService.buildProjection(fields?.data); const { skip, limit, sort, filters } = input;
|
||||
return await this.buildIbanService.findAll(projection, skip, limit, sort, filters);
|
||||
}
|
||||
|
||||
@Query(() => BuildIban, { name: 'getBuildIban', nullable: true })
|
||||
async getBuildIban(@Args('id', { type: () => ID }) id: string, @Info() info: GraphQLResolveInfo): Promise<BuildIban | null> {
|
||||
const fields = graphqlFields(info); const projection = this.buildIbanService.buildProjection(fields); return this.buildIbanService.findById(new Types.ObjectId(id), projection);
|
||||
}
|
||||
|
||||
@Mutation(() => BuildIban, { name: 'createBuildIban' })
|
||||
async createBuildIban(@Args('input') input: CreateBuildIbanInput): Promise<BuildIban> { return this.buildIbanService.create(input) }
|
||||
|
||||
@Mutation(() => BuildIban, { name: 'updateBuildIban' })
|
||||
async updateBuildIban(@Args('uuid') uuid: string, @Args('input') input: UpdateBuildIbanInput): Promise<BuildIban> { return this.buildIbanService.update(uuid, input) }
|
||||
|
||||
@Mutation(() => Boolean, { name: 'deleteBuildIban' })
|
||||
async deleteBuildIban(@Args('uuid') uuid: string): Promise<boolean> { return this.buildIbanService.delete(uuid) }
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { BuildIbanService } from './build-iban.service';
|
||||
|
||||
describe('BuildIbanService', () => {
|
||||
let service: BuildIbanService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [BuildIbanService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<BuildIbanService>(BuildIbanService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectModel } from '@nestjs/mongoose';
|
||||
import { Types, Model } from 'mongoose';
|
||||
import { Build, BuildDocument, BuildIban, BuildIbanDocument } from '@/models/build.model';
|
||||
import { ListBuildIbanResponse } from './dto/list-build-ibans.response';
|
||||
import { CreateBuildIbanInput } from './dto/create-build-ibans.input';
|
||||
import { UpdateBuildIbanInput } from './dto/update-build-ibans.input';
|
||||
|
||||
@Injectable()
|
||||
export class BuildIbanService {
|
||||
|
||||
constructor(
|
||||
@InjectModel(BuildIban.name) private readonly buildIbanModel: Model<BuildIbanDocument>,
|
||||
@InjectModel(Build.name) private readonly buildModel: Model<BuildDocument>
|
||||
) { }
|
||||
|
||||
async findAll(projection: any, skip: number, limit: number, sort?: Record<string, 1 | -1>, filters?: Record<string, any>): Promise<ListBuildIbanResponse> {
|
||||
const query: any = {}; if (filters && Object.keys(filters).length > 0) { Object.assign(query, filters) };
|
||||
if (!!query?.buildId) { query.buildId = new Types.ObjectId(query?.buildId) };
|
||||
const totalCount = await this.buildIbanModel.countDocuments(query).exec();
|
||||
const data = await this.buildIbanModel.find(query, projection, { lean: true }).skip(skip).limit(limit).sort(sort).exec();
|
||||
return { data, totalCount };
|
||||
}
|
||||
|
||||
async findById(id: Types.ObjectId, projection?: any): Promise<BuildIbanDocument | null> {
|
||||
return this.buildIbanModel.findById(id, projection, { lean: false }).populate({ path: 'buildIban', select: projection?.buildIban }).exec();
|
||||
}
|
||||
|
||||
async create(input: CreateBuildIbanInput): Promise<BuildIbanDocument> {
|
||||
const build = await this.buildModel.findOne({ _id: new Types.ObjectId(input.buildId) });
|
||||
if (!build) { throw new Error('Build not found') }
|
||||
const buildIban = new this.buildIbanModel({ ...input, buildId: build._id }); return buildIban.save()
|
||||
}
|
||||
|
||||
async update(uuid: string, input: UpdateBuildIbanInput): Promise<BuildIbanDocument> {
|
||||
const buildIban = await this.buildIbanModel.findOne({ uuid }); if (!buildIban) { throw new Error('BuildIban not found') }; buildIban.set(input); return buildIban.save()
|
||||
}
|
||||
|
||||
async delete(uuid: string): Promise<boolean> { const buildIban = await this.buildIbanModel.deleteMany({ uuid }); return buildIban.deletedCount > 0 }
|
||||
|
||||
buildProjection(fields: Record<string, any>): any {
|
||||
const projection: any = {};
|
||||
for (const key in fields) { if (key === 'buildIban' && typeof fields[key] === 'object') { for (const subField of Object.keys(fields[key])) { projection[`buildIban.${subField}`] = 1 } } else { projection[key] = 1 } }; return projection;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import { ExpiryBaseInput } from "@/models/base.model";
|
||||
import { InputType, Field } from "@nestjs/graphql";
|
||||
|
||||
@InputType()
|
||||
export class CreateBuildIbanInput extends ExpiryBaseInput {
|
||||
|
||||
@Field()
|
||||
buildId: string;
|
||||
|
||||
@Field()
|
||||
iban: string;
|
||||
|
||||
@Field()
|
||||
startDate: string;
|
||||
|
||||
@Field()
|
||||
stopDate: string;
|
||||
|
||||
@Field()
|
||||
bankCode: string;
|
||||
|
||||
@Field()
|
||||
xcomment: string;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import { BuildIban } from "@/models/build.model";
|
||||
import { Field, Int, ObjectType } from "@nestjs/graphql";
|
||||
|
||||
@ObjectType()
|
||||
export class ListBuildIbanResponse {
|
||||
|
||||
@Field(() => [BuildIban], { nullable: true })
|
||||
data?: BuildIban[];
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
totalCount?: number;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import { ExpiryBaseInput } from "@/models/base.model";
|
||||
import { InputType, Field } from "@nestjs/graphql";
|
||||
|
||||
@InputType()
|
||||
export class UpdateBuildIbanInput extends ExpiryBaseInput {
|
||||
|
||||
@Field({ nullable: true })
|
||||
iban?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
startDate?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
stopDate?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
bankCode?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
xcomment?: string;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { BuildPartsService } from './build-parts.service';
|
||||
import { BuildPartsResolver } from './build-parts.resolver';
|
||||
import { MongooseModule } from '@nestjs/mongoose';
|
||||
import { BuildParts, BuildPartsSchema } from '@/models/build-parts.model';
|
||||
import { Build, BuildSchema } from '@/models/build.model';
|
||||
|
||||
@Module({
|
||||
imports: [MongooseModule.forFeature([
|
||||
{ name: BuildParts.name, schema: BuildPartsSchema },
|
||||
{ name: Build.name, schema: BuildSchema }])],
|
||||
providers: [BuildPartsService, BuildPartsResolver]
|
||||
})
|
||||
export class BuildPartsModule { }
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { BuildPartsResolver } from './build-parts.resolver';
|
||||
|
||||
describe('BuildPartsResolver', () => {
|
||||
let resolver: BuildPartsResolver;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [BuildPartsResolver],
|
||||
}).compile();
|
||||
|
||||
resolver = module.get<BuildPartsResolver>(BuildPartsResolver);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(resolver).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
import { Resolver, Query, Args, ID, Info, Mutation } from '@nestjs/graphql';
|
||||
import { Types } from 'mongoose';
|
||||
import { BuildParts } from '@/models/build-parts.model';
|
||||
import { CreateBuildPartsInput } from './dto/create-build-part.input';
|
||||
import { BuildPartsService } from './build-parts.service';
|
||||
import { ListArguments } from '@/dto/list.input';
|
||||
import { ListBuildPartsResponse } from './dto/list-build-parts.response';
|
||||
import graphqlFields from 'graphql-fields';
|
||||
import type { GraphQLResolveInfo } from 'graphql';
|
||||
import { UpdateBuildPartsInput } from './dto/update-build-parts.input';
|
||||
|
||||
@Resolver()
|
||||
export class BuildPartsResolver {
|
||||
|
||||
constructor(private readonly buildPartsService: BuildPartsService) { }
|
||||
|
||||
@Query(() => ListBuildPartsResponse, { name: 'buildParts' })
|
||||
async getBuildParts(@Info() info: GraphQLResolveInfo, @Args('input') input: ListArguments): Promise<ListBuildPartsResponse> {
|
||||
const fields = graphqlFields(info); const projection = this.buildPartsService.buildProjection(fields?.data); const { skip, limit, sort, filters } = input;
|
||||
return await this.buildPartsService.findAll(projection, skip, limit, sort, filters);
|
||||
}
|
||||
|
||||
@Query(() => BuildParts, { name: 'buildPart', nullable: true })
|
||||
async getBuildPart(@Args('id', { type: () => ID }) id: string, @Info() info: GraphQLResolveInfo): Promise<BuildParts | null> {
|
||||
const fields = graphqlFields(info); const projection = this.buildPartsService.buildProjection(fields); return this.buildPartsService.findById(new Types.ObjectId(id), projection);
|
||||
}
|
||||
|
||||
@Mutation(() => BuildParts, { name: 'createBuildPart' })
|
||||
async createBuildPart(@Args('input') input: CreateBuildPartsInput): Promise<BuildParts> { return this.buildPartsService.create(input) }
|
||||
|
||||
@Mutation(() => Boolean, { name: 'deleteBuildPart' })
|
||||
async deleteBuildPart(@Args('uuid') uuid: string): Promise<boolean> { return this.buildPartsService.delete(uuid) }
|
||||
|
||||
@Mutation(() => BuildParts, { name: 'updateBuildPart' })
|
||||
async updateBuildPart(@Args('uuid') uuid: string, @Args('input') input: UpdateBuildPartsInput): Promise<BuildParts> { return this.buildPartsService.update(uuid, input) }
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { BuildPartsService } from './build-parts.service';
|
||||
|
||||
describe('BuildPartsService', () => {
|
||||
let service: BuildPartsService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [BuildPartsService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<BuildPartsService>(BuildPartsService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectModel } from '@nestjs/mongoose';
|
||||
import { Types, Model } from 'mongoose';
|
||||
import { BuildParts, BuildPartsDocument } from '@/models/build-parts.model';
|
||||
import { CreateBuildPartsInput } from './dto/create-build-part.input';
|
||||
import { ListBuildPartsResponse } from './dto/list-build-parts.response';
|
||||
import { UpdateBuildPartsInput } from './dto/update-build-parts.input';
|
||||
import { Build, BuildDocument } from '@/models/build.model';
|
||||
|
||||
@Injectable()
|
||||
export class BuildPartsService {
|
||||
|
||||
constructor(
|
||||
@InjectModel(BuildParts.name) private readonly buildPartsModel: Model<BuildPartsDocument>,
|
||||
@InjectModel(Build.name) private readonly buildModel: Model<BuildDocument>
|
||||
) { }
|
||||
|
||||
async findAll(projection: any, skip: number, limit: number, sort?: Record<string, 1 | -1>, filters?: Record<string, any>): Promise<ListBuildPartsResponse> {
|
||||
const query: any = {}; if (filters && Object.keys(filters).length > 0) { Object.assign(query, filters) };
|
||||
if (query?.buildId) { query.buildId = new Types.ObjectId(query?.buildId) };
|
||||
const totalCount = await this.buildPartsModel.countDocuments(query).exec();
|
||||
const data = await this.buildPartsModel.find(query, projection, { lean: true }).skip(skip).limit(limit).sort(sort).exec();
|
||||
return { data, totalCount };
|
||||
}
|
||||
|
||||
async findById(id: Types.ObjectId, projection?: any): Promise<BuildPartsDocument | null> {
|
||||
return this.buildPartsModel.findById(id, projection, { lean: false }).populate({ path: 'buildParts', select: projection?.buildParts }).exec();
|
||||
}
|
||||
|
||||
async create(input: CreateBuildPartsInput): Promise<BuildPartsDocument> {
|
||||
const getBuildID = await this.buildModel.findById(input?.buildId, { _id: 1 }, { lean: true }).exec();
|
||||
if (getBuildID) { input.buildId = new Types.ObjectId(getBuildID._id) };
|
||||
if (input?.directionId) { input.directionId = new Types.ObjectId(input?.directionId) };
|
||||
if (input?.typeId) { input.typeId = new Types.ObjectId(input?.typeId) };
|
||||
const buildParts = new this.buildPartsModel(input); return buildParts.save()
|
||||
}
|
||||
|
||||
async update(uuid: string, input: UpdateBuildPartsInput): Promise<BuildPartsDocument> {
|
||||
const buildParts = await this.buildPartsModel.findOne({ _id: new Types.ObjectId(uuid) }); if (!buildParts) { throw new Error('BuildParts not found') };
|
||||
if (input?.buildId) { const getBuildID = await this.buildModel.findById(input?.buildId, { _id: 1 }, { lean: true }).exec(); if (getBuildID) { input.buildId = new Types.ObjectId(getBuildID._id) } };
|
||||
if (input?.directionId) { input.directionId = new Types.ObjectId(input?.directionId) };
|
||||
if (input?.typeId) { input.typeId = new Types.ObjectId(input?.typeId) }; buildParts.set(input); return buildParts.save()
|
||||
}
|
||||
|
||||
async delete(uuid: string): Promise<boolean> { console.log(uuid); const buildParts = await this.buildPartsModel.deleteMany({ _id: new Types.ObjectId(uuid) }); return buildParts.deletedCount > 0 }
|
||||
|
||||
buildProjection(fields: Record<string, any>): any {
|
||||
const projection: any = {};
|
||||
for (const key in fields) {
|
||||
if (key === 'buildParts' && typeof fields[key] === 'object') { for (const subField of Object.keys(fields[key])) { projection[`buildParts.${subField}`] = 1 } }
|
||||
else { projection[key] = 1 }
|
||||
}
|
||||
return projection;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
import { InputType, Field, ID, Float } from '@nestjs/graphql';
|
||||
import { Types } from 'mongoose';
|
||||
|
||||
@InputType()
|
||||
export class CreateBuildPartsInput {
|
||||
|
||||
@Field(() => ID, { nullable: false })
|
||||
buildId: Types.ObjectId;
|
||||
|
||||
@Field({ nullable: false })
|
||||
addressGovCode: string;
|
||||
|
||||
@Field(() => Float, { nullable: false })
|
||||
no: number;
|
||||
|
||||
@Field(() => Float, { nullable: false })
|
||||
level: number;
|
||||
|
||||
@Field({ nullable: false })
|
||||
code: string;
|
||||
|
||||
@Field(() => Float, { nullable: false })
|
||||
grossSize: number;
|
||||
|
||||
@Field(() => Float, { nullable: false })
|
||||
netSize: number;
|
||||
|
||||
@Field({ nullable: false })
|
||||
defaultAccessory: string;
|
||||
|
||||
@Field({ nullable: false })
|
||||
humanLivability: boolean;
|
||||
|
||||
@Field({ nullable: false })
|
||||
key: string;
|
||||
|
||||
@Field(() => ID, { nullable: true })
|
||||
directionId: Types.ObjectId;
|
||||
|
||||
@Field(() => ID, { nullable: true })
|
||||
typeId: Types.ObjectId;
|
||||
|
||||
@Field(() => Boolean, { nullable: false })
|
||||
active: boolean;
|
||||
|
||||
@Field(() => Boolean, { nullable: false })
|
||||
isConfirmed: boolean;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
expiryStarts: string;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
expiryEnds: string;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import { BuildParts } from "@/models/build-parts.model";
|
||||
import { Field, Int, ObjectType } from "@nestjs/graphql";
|
||||
|
||||
@ObjectType()
|
||||
export class ListBuildPartsResponse {
|
||||
|
||||
@Field(() => [BuildParts], { nullable: true })
|
||||
data?: BuildParts[];
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
totalCount?: number;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
import { ExpiryBaseInput } from "@/models/base.model";
|
||||
import { InputType, Field, ID, Float } from "@nestjs/graphql";
|
||||
import { Types } from "mongoose";
|
||||
|
||||
@InputType()
|
||||
export class UpdateBuildPartsInput extends ExpiryBaseInput {
|
||||
|
||||
@Field(() => ID, { nullable: true })
|
||||
buildId?: Types.ObjectId;
|
||||
|
||||
@Field({ nullable: true })
|
||||
addressGovCode?: string;
|
||||
|
||||
@Field(() => Float, { nullable: true })
|
||||
no?: number;
|
||||
|
||||
@Field(() => Float, { nullable: true })
|
||||
level?: number;
|
||||
|
||||
@Field({ nullable: true })
|
||||
code?: string;
|
||||
|
||||
@Field(() => Float, { nullable: true })
|
||||
grossSize?: number;
|
||||
|
||||
@Field(() => Float, { nullable: true })
|
||||
netSize?: number;
|
||||
|
||||
@Field({ nullable: true })
|
||||
defaultAccessory?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
humanLivability?: boolean;
|
||||
|
||||
@Field({ nullable: true })
|
||||
key?: string;
|
||||
|
||||
@Field(() => ID, { nullable: true })
|
||||
directionId?: Types.ObjectId;
|
||||
|
||||
@Field(() => ID, { nullable: true })
|
||||
typeId?: Types.ObjectId;
|
||||
|
||||
@Field(() => Boolean, { nullable: true })
|
||||
active?: boolean;
|
||||
|
||||
@Field(() => Boolean, { nullable: true })
|
||||
isConfirmed?: boolean;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { BuildSitesService } from './build-sites.service';
|
||||
import { BuildSitesResolver } from './build-sites.resolver';
|
||||
import { MongooseModule } from '@nestjs/mongoose';
|
||||
import { BuildSites, BuildSiteSchema } from '@/models/build-site.model';
|
||||
|
||||
@Module({
|
||||
imports: [MongooseModule.forFeature([{ name: BuildSites.name, schema: BuildSiteSchema }])],
|
||||
providers: [BuildSitesService, BuildSitesResolver]
|
||||
})
|
||||
export class BuildSitesModule { }
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { BuildSitesResolver } from './build-sites.resolver';
|
||||
|
||||
describe('BuildSitesResolver', () => {
|
||||
let resolver: BuildSitesResolver;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [BuildSitesResolver],
|
||||
}).compile();
|
||||
|
||||
resolver = module.get<BuildSitesResolver>(BuildSitesResolver);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(resolver).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
import { Resolver, Query, Args, ID, Info, Mutation } from '@nestjs/graphql';
|
||||
import { Types } from 'mongoose';
|
||||
import { BuildSites } from '@/models/build-site.model';
|
||||
import { BuildSitesService } from './build-sites.service';
|
||||
import { ListArguments } from '@/dto/list.input';
|
||||
import { ListBuildSitesResponse } from './dto/list-build-sites.response';
|
||||
import { CreateBuildSitesInput } from './dto/create-build-sites.input';
|
||||
import { UpdateBuildSitesInput } from './dto/update-build-sites.input';
|
||||
import graphqlFields from 'graphql-fields';
|
||||
import type { GraphQLResolveInfo } from 'graphql';
|
||||
|
||||
@Resolver()
|
||||
export class BuildSitesResolver {
|
||||
|
||||
constructor(private readonly buildSitesService: BuildSitesService) { }
|
||||
|
||||
@Query(() => ListBuildSitesResponse, { name: 'buildSites' })
|
||||
async getBuildSites(@Info() info: GraphQLResolveInfo, @Args('input') input: ListArguments): Promise<ListBuildSitesResponse> {
|
||||
const fields = graphqlFields(info); const projection = this.buildSitesService.buildProjection(fields?.data); const { skip, limit, sort, filters } = input;
|
||||
return await this.buildSitesService.findAll(projection, skip, limit, sort, filters);
|
||||
}
|
||||
|
||||
@Query(() => BuildSites, { name: 'getBuildSite', nullable: true })
|
||||
async getBuildSite(@Args('id', { type: () => ID }) id: string, @Info() info: GraphQLResolveInfo): Promise<BuildSites | null> {
|
||||
const fields = graphqlFields(info); const projection = this.buildSitesService.buildProjection(fields); return this.buildSitesService.findById(new Types.ObjectId(id), projection);
|
||||
}
|
||||
|
||||
@Mutation(() => BuildSites, { name: 'createBuildSite' })
|
||||
async createBuildSite(@Args('input') input: CreateBuildSitesInput): Promise<BuildSites> { return this.buildSitesService.create(input) }
|
||||
|
||||
@Mutation(() => BuildSites, { name: 'updateBuildSite' })
|
||||
async updateBuildSite(@Args('uuid') uuid: string, @Args('input') input: UpdateBuildSitesInput): Promise<BuildSites> { return this.buildSitesService.update(uuid, input) }
|
||||
|
||||
@Mutation(() => Boolean, { name: 'deleteBuildSite' })
|
||||
async deleteBuildSite(@Args('uuid') uuid: string): Promise<boolean> { return this.buildSitesService.delete(uuid) }
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { BuildSitesService } from './build-sites.service';
|
||||
|
||||
describe('BuildSitesService', () => {
|
||||
let service: BuildSitesService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [BuildSitesService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<BuildSitesService>(BuildSitesService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { Types } from 'mongoose';
|
||||
import { ListBuildSitesResponse } from './dto/list-build-sites.response';
|
||||
import { CreateBuildSitesInput } from './dto/create-build-sites.input';
|
||||
import { UpdateBuildSitesInput } from './dto/update-build-sites.input';
|
||||
import { InjectModel } from '@nestjs/mongoose';
|
||||
import { BuildSites, BuildSiteDocument } from '@/models/build-site.model';
|
||||
import { Model } from 'mongoose';
|
||||
import { Build, BuildDocument } from '@/models/build.model';
|
||||
|
||||
@Injectable()
|
||||
export class BuildSitesService {
|
||||
|
||||
constructor(@InjectModel(BuildSites.name) private readonly buildSitesModel: Model<BuildSiteDocument>) { }
|
||||
|
||||
async findAll(projection: any, skip: number, limit: number, sort?: Record<string, 1 | -1>, filters?: Record<string, any>): Promise<ListBuildSitesResponse> {
|
||||
const query: any = {}; if (filters && Object.keys(filters).length > 0) { Object.assign(query, filters) };
|
||||
const totalCount = await this.buildSitesModel.countDocuments(query).exec();
|
||||
const data = await this.buildSitesModel.find(query, projection, { lean: true }).skip(skip).limit(limit).sort(sort).exec();
|
||||
return { data, totalCount };
|
||||
}
|
||||
|
||||
async findById(id: Types.ObjectId, projection?: any): Promise<BuildSiteDocument | null> {
|
||||
return this.buildSitesModel.findById(id, projection, { lean: false }).populate({ path: 'buildSites', select: projection?.buildSites }).exec();
|
||||
}
|
||||
|
||||
async create(input: CreateBuildSitesInput): Promise<BuildSiteDocument> {
|
||||
|
||||
const buildSite = new this.buildSitesModel(input); return buildSite.save()
|
||||
}
|
||||
|
||||
async update(uuid: string, input: UpdateBuildSitesInput): Promise<BuildSiteDocument> { const buildSite = await this.buildSitesModel.findOne({ uuid }); if (!buildSite) { throw new Error('BuildSite not found') }; buildSite.set(input); return buildSite.save() }
|
||||
|
||||
async delete(uuid: string): Promise<boolean> { const buildSite = await this.buildSitesModel.deleteMany({ uuid }); return buildSite.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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
import { InputType, Field } from "@nestjs/graphql";
|
||||
import { Types } from "mongoose";
|
||||
import { ID } from "@nestjs/graphql";
|
||||
import { ExpiryBaseInput } from "@/models/base.model";
|
||||
|
||||
@InputType()
|
||||
export class CreateBuildSitesInput extends ExpiryBaseInput {
|
||||
|
||||
@Field(() => String)
|
||||
siteName: string;
|
||||
|
||||
@Field(() => String)
|
||||
siteNo: string;
|
||||
|
||||
@Field(() => ID, { nullable: true })
|
||||
address?: Types.ObjectId;
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import { ObjectType, Field } from "@nestjs/graphql";
|
||||
import { BuildSites } from "@/models/build-site.model";
|
||||
|
||||
@ObjectType()
|
||||
export class ListBuildSitesResponse {
|
||||
|
||||
@Field(() => [BuildSites], { nullable: true })
|
||||
data: BuildSites[];
|
||||
|
||||
@Field(() => Number, { nullable: true })
|
||||
totalCount: number;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { InputType, Field } from "@nestjs/graphql";
|
||||
import { Types } from "mongoose";
|
||||
import { ID } from "@nestjs/graphql";
|
||||
import { ExpiryBaseInput } from "@/models/base.model";
|
||||
|
||||
@InputType()
|
||||
export class UpdateBuildSitesInput extends ExpiryBaseInput {
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
siteName?: string;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
siteNo?: string;
|
||||
|
||||
@Field(() => ID, { nullable: true })
|
||||
address?: Types.ObjectId;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { BuildTypesResolver } from './build-types.resolver';
|
||||
import { BuildTypesService } from './build-types.service';
|
||||
import { MongooseModule } from '@nestjs/mongoose';
|
||||
import { BuildTypes, BuildTypesSchema } from '@/models/build-types.model';
|
||||
|
||||
@Module({
|
||||
imports: [MongooseModule.forFeature([{ name: BuildTypes.name, schema: BuildTypesSchema }])],
|
||||
providers: [BuildTypesResolver, BuildTypesService]
|
||||
})
|
||||
export class BuildTypesModule { }
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { BuildTypesResolver } from './build-types.resolver';
|
||||
|
||||
describe('BuildTypesResolver', () => {
|
||||
let resolver: BuildTypesResolver;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [BuildTypesResolver],
|
||||
}).compile();
|
||||
|
||||
resolver = module.get<BuildTypesResolver>(BuildTypesResolver);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(resolver).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
import { Resolver, Query, Args, ID, Info, Mutation } from '@nestjs/graphql';
|
||||
import { BuildTypes } from '@/models/build-types.model';
|
||||
import graphqlFields from 'graphql-fields';
|
||||
import { Types } from 'mongoose';
|
||||
import { BuildTypesService } from './build-types.service';
|
||||
import { CreateBuildTypesInput } from './dto/create-build-types.input';
|
||||
import { UpdateBuildTypesInput } from './dto/update-build-types.input';
|
||||
import type { GraphQLResolveInfo } from 'graphql';
|
||||
import { ListBuildTypesResponse } from './dto/list-users.response';
|
||||
import { ListArguments } from '@/dto/list.input';
|
||||
|
||||
@Resolver()
|
||||
export class BuildTypesResolver {
|
||||
|
||||
constructor(private readonly buildTypesService: BuildTypesService) { }
|
||||
|
||||
@Query(() => ListBuildTypesResponse, { name: 'buildTypes' })
|
||||
async getBuildTypes(@Info() info: GraphQLResolveInfo, @Args('input') input: ListArguments): Promise<ListBuildTypesResponse> {
|
||||
const fields = graphqlFields(info); const projection = this.buildTypesService.buildProjection(fields?.data); const { skip, limit, sort, filters } = input;
|
||||
return await this.buildTypesService.findAll(projection, skip, limit, sort, filters);
|
||||
}
|
||||
|
||||
@Query(() => BuildTypes, { name: 'getBuildType', nullable: true })
|
||||
async getBuildType(@Args('id', { type: () => ID }) id: string, @Info() info: GraphQLResolveInfo): Promise<BuildTypes | null> {
|
||||
const fields = graphqlFields(info); const projection = this.buildTypesService.buildProjection(fields); return this.buildTypesService.findById(new Types.ObjectId(id), projection);
|
||||
}
|
||||
|
||||
@Mutation(() => BuildTypes, { name: 'createBuildType' })
|
||||
async createBuildType(@Args('input') input: CreateBuildTypesInput): Promise<BuildTypes> { return this.buildTypesService.create(input) }
|
||||
|
||||
@Mutation(() => BuildTypes, { name: 'updateBuildType' })
|
||||
async updateBuildType(@Args('uuid') uuid: string, @Args('input') input: UpdateBuildTypesInput): Promise<BuildTypes> { return this.buildTypesService.update(uuid, input) }
|
||||
|
||||
@Mutation(() => Boolean, { name: 'deleteBuildType' })
|
||||
async deleteBuildType(@Args('uuid') uuid: string): Promise<boolean> { return this.buildTypesService.delete(uuid) }
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { BuildTypesService } from './build-types.service';
|
||||
|
||||
describe('BuildTypesService', () => {
|
||||
let service: BuildTypesService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [BuildTypesService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<BuildTypesService>(BuildTypesService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectModel } from '@nestjs/mongoose';
|
||||
import { Types, Model } from 'mongoose';
|
||||
import { BuildTypes, BuildTypesDocument } from '@/models/build-types.model';
|
||||
import { CreateBuildTypesInput } from './dto/create-build-types.input';
|
||||
import { UpdateBuildTypesInput } from './dto/update-build-types.input';
|
||||
import { ListBuildTypesResponse } from './dto/list-users.response';
|
||||
|
||||
@Injectable()
|
||||
export class BuildTypesService {
|
||||
|
||||
constructor(@InjectModel(BuildTypes.name) private readonly buildTypesModel: Model<BuildTypesDocument>) { }
|
||||
|
||||
async findAll(projection: any, skip: number, limit: number, sort?: Record<string, 1 | -1>, filters?: Record<string, any>): Promise<ListBuildTypesResponse> {
|
||||
const query: any = {}; if (filters && Object.keys(filters).length > 0) { Object.assign(query, filters) };
|
||||
const totalCount = await this.buildTypesModel.countDocuments(query).exec();
|
||||
const data = await this.buildTypesModel.find(query, projection, { lean: true }).skip(skip).limit(limit).sort(sort).exec();
|
||||
return { data, totalCount };
|
||||
}
|
||||
|
||||
async findById(id: Types.ObjectId, projection?: any): Promise<BuildTypesDocument | null> {
|
||||
return this.buildTypesModel.findById(id, projection, { lean: false }).populate({ path: 'buildTypes', select: projection?.buildTypes }).exec();
|
||||
}
|
||||
|
||||
async create(input: CreateBuildTypesInput): Promise<BuildTypesDocument> { const buildTypes = new this.buildTypesModel(input); return buildTypes.save() }
|
||||
|
||||
async update(uuid: string, input: UpdateBuildTypesInput): Promise<BuildTypesDocument> { const buildTypes = await this.buildTypesModel.findOne({ uuid }); if (!buildTypes) { throw new Error('BuildTypes not found') }; buildTypes.set(input); return buildTypes.save() }
|
||||
|
||||
async delete(uuid: string): Promise<boolean> { const buildTypes = await this.buildTypesModel.deleteMany({ uuid }); return buildTypes.deletedCount > 0 }
|
||||
|
||||
buildProjection(fields: Record<string, any>): any {
|
||||
const projection: any = {};
|
||||
for (const key in fields) {
|
||||
if (key === 'buildTypes' && typeof fields[key] === 'object') { for (const subField of Object.keys(fields[key])) { projection[`buildTypes.${subField}`] = 1 } }
|
||||
else { projection[key] = 1 }
|
||||
}
|
||||
return projection;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
import { ExpiryBaseInput } from "@/models/base.model";
|
||||
import { InputType, Field } from "@nestjs/graphql";
|
||||
|
||||
@InputType()
|
||||
export class CreateBuildTypesInput extends ExpiryBaseInput {
|
||||
|
||||
@Field()
|
||||
type: string;
|
||||
|
||||
@Field()
|
||||
token: string;
|
||||
|
||||
@Field()
|
||||
typeToken: string;
|
||||
|
||||
@Field()
|
||||
description: string;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
import { Field, Int, ObjectType } from "@nestjs/graphql";
|
||||
import { BuildTypes } from "@/models/build-types.model";
|
||||
|
||||
@ObjectType()
|
||||
export class ListBuildTypesResponse {
|
||||
|
||||
@Field(() => [BuildTypes], { nullable: true })
|
||||
data?: BuildTypes[];
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
totalCount?: number;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
import { ExpiryBaseInput } from "@/models/base.model";
|
||||
import { InputType, Field } from "@nestjs/graphql";
|
||||
|
||||
@InputType()
|
||||
export class UpdateBuildTypesInput extends ExpiryBaseInput {
|
||||
|
||||
@Field({ nullable: true })
|
||||
type?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
token?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
typeToken?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
description?: string;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { BuildResolver } from './build.resolver';
|
||||
import { MongooseModule } from '@nestjs/mongoose';
|
||||
import { BuildSchema, BuildIbanSchema } from '@/models/build.model';
|
||||
import { BuildService } from './build.service';
|
||||
import { BuildAreaSchema } from '@/models/build-area.model';
|
||||
import { CompanySchema } from '@/models/company.model';
|
||||
import { PersonSchema } from '@/models/person.model';
|
||||
import { BuildTypesSchema } from '@/models/build-types.model';
|
||||
|
||||
@Module({
|
||||
imports: [MongooseModule.forFeature([
|
||||
{ name: 'Build', schema: BuildSchema }, { name: 'BuildArea', schema: BuildAreaSchema }, { name: 'BuildIban', schema: BuildIbanSchema },
|
||||
{ name: 'Company', schema: CompanySchema }, { name: 'Person', schema: PersonSchema }, { name: 'BuildTypes', schema: BuildTypesSchema },
|
||||
])],
|
||||
providers: [BuildResolver, BuildService]
|
||||
})
|
||||
export class BuildModule { }
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { BuildResolver } from './build.resolver';
|
||||
|
||||
describe('BuildResolver', () => {
|
||||
let resolver: BuildResolver;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [BuildResolver],
|
||||
}).compile();
|
||||
|
||||
resolver = module.get<BuildResolver>(BuildResolver);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(resolver).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
import graphqlFields from 'graphql-fields';
|
||||
import { Resolver, Query, Args, ID, Info, Mutation } from '@nestjs/graphql';
|
||||
import { Types } from 'mongoose';
|
||||
import { Build } from '@/models/build.model';
|
||||
import { CreateBuildInput } from './dto/create-build.input';
|
||||
import { UpdateBuildResponsibleInput, UpdateBuildAttributeInput, UpdateBuildInput } from './dto/update-build.input';
|
||||
import { BuildService } from './build.service';
|
||||
import { ListArguments } from '@/dto/list.input';
|
||||
import { ListBuildResponse, ListPartialAreaResponse, ListPartialCompanyResponse, ListPartialIbanResponse } from './dto/list-build.response';
|
||||
import type { GraphQLResolveInfo } from 'graphql';
|
||||
|
||||
@Resolver()
|
||||
export class BuildResolver {
|
||||
|
||||
constructor(private readonly buildService: BuildService) { }
|
||||
|
||||
@Query(() => ListBuildResponse, { name: 'builds' })
|
||||
async getBuilds(@Info() info: GraphQLResolveInfo, @Args('input') input: ListArguments): Promise<ListBuildResponse> {
|
||||
const fields = graphqlFields(info); const projection = this.buildService.buildProjection(fields); return this.buildService.findAll(input.skip, input.limit, input.sort, input.filters);
|
||||
}
|
||||
|
||||
@Query(() => ListPartialAreaResponse, { name: 'getBuildsAreas' })
|
||||
async getBuildsAreas(@Info() info: GraphQLResolveInfo, @Args('id') id: string, @Args('input') input: ListArguments): Promise<ListPartialAreaResponse> {
|
||||
const fields = graphqlFields(info); const projection = this.buildService.buildProjection(fields); return this.buildService.findAllAreas(id, input.skip, input.limit, input.sort, input.filters);
|
||||
}
|
||||
|
||||
@Query(() => ListPartialIbanResponse, { name: 'getBuildsIbans' })
|
||||
async getBuildsIbans(@Info() info: GraphQLResolveInfo, @Args('id') id: string, @Args('input') input: ListArguments): Promise<ListPartialIbanResponse> {
|
||||
const fields = graphqlFields(info); const projection = this.buildService.buildProjection(fields); return this.buildService.findAllIbans(id, input.skip, input.limit, input.sort, input.filters);
|
||||
}
|
||||
|
||||
@Query(() => ListPartialCompanyResponse, { name: 'getBuildsCompaniesAndResponsibles' })
|
||||
async getBuildsCompaniesAndResponsibles(@Info() info: GraphQLResolveInfo, @Args('id') id: string, @Args('input') input: ListArguments): Promise<ListPartialCompanyResponse> {
|
||||
const fields = graphqlFields(info); const projection = this.buildService.buildProjection(fields); return this.buildService.findAllCompaniesAndResponsibles(id, input.skip, input.limit, input.sort, input.filters);
|
||||
}
|
||||
|
||||
@Query(() => Build, { name: 'build', nullable: true })
|
||||
async getBuild(@Args('id', { type: () => ID }) id: string, @Info() info: GraphQLResolveInfo): Promise<Build | null> {
|
||||
const fields = graphqlFields(info); const projection = this.buildService.buildProjection(fields); return this.buildService.findById(new Types.ObjectId(id), projection);
|
||||
}
|
||||
|
||||
@Mutation(() => Boolean, { name: 'deleteBuild' })
|
||||
async deleteBuild(@Args('uuid') uuid: string): Promise<boolean> { return this.buildService.delete(uuid) }
|
||||
|
||||
@Mutation(() => Build, { name: 'createBuild' })
|
||||
async createBuild(@Args('input') input: CreateBuildInput): Promise<Build> { return this.buildService.create(input) }
|
||||
|
||||
@Mutation(() => Build, { name: 'updateBuild' })
|
||||
async updateBuild(@Args('uuid') uuid: string, @Args('input') input: UpdateBuildInput): Promise<Build> { return this.buildService.update(uuid, input) }
|
||||
|
||||
@Mutation(() => Build, { name: 'updateBuildResponsible' })
|
||||
async updateBuildResponsible(@Args('uuid') uuid: string, @Args('input') input: UpdateBuildResponsibleInput): Promise<Build> { return this.buildService.updateResponsible(uuid, input) }
|
||||
|
||||
@Mutation(() => Build, { name: 'updateBuildAttribute' })
|
||||
async updateBuildAttribute(@Args('uuid') uuid: string, @Args('input') input: UpdateBuildAttributeInput): Promise<Build> { return this.buildService.updateAttribute(uuid, input) }
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { BuildService } from './build.service';
|
||||
|
||||
describe('BuildService', () => {
|
||||
let service: BuildService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [BuildService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<BuildService>(BuildService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectModel } from '@nestjs/mongoose';
|
||||
import { Types, Model } from 'mongoose';
|
||||
import { Build, BuildDocument, BuildIban, BuildIbanDocument } from '@/models/build.model';
|
||||
import { CreateBuildInput } from './dto/create-build.input';
|
||||
import { UpdateBuildAttributeInput, UpdateBuildInput, UpdateBuildResponsibleInput } from './dto/update-build.input';
|
||||
import { ListBuildResponse, ListPartialAreaResponse, ListPartialCompanyResponse, ListPartialIbanResponse } from './dto/list-build.response';
|
||||
import { cleanRefArrayField } from '@/lib/getListOfModelByIDs';
|
||||
import { BuildArea, BuildAreaDocument } from '@/models/build-area.model';
|
||||
import { Company, CompanyDocument } from '@/models/company.model';
|
||||
import { Person, PersonDocument } from '@/models/person.model';
|
||||
import { BuildTypes, BuildTypesDocument } from '@/models/build-types.model';
|
||||
|
||||
@Injectable()
|
||||
export class BuildService {
|
||||
|
||||
constructor(
|
||||
@InjectModel(Build.name) private readonly buildModel: Model<BuildDocument>,
|
||||
@InjectModel(BuildArea.name) private readonly areaModel: Model<BuildAreaDocument>,
|
||||
@InjectModel(BuildIban.name) private readonly ibanModel: Model<BuildIbanDocument>,
|
||||
@InjectModel(Company.name) private readonly companyModel: Model<CompanyDocument>,
|
||||
@InjectModel(Person.name) private readonly personModel: Model<PersonDocument>,
|
||||
@InjectModel(BuildTypes.name) private readonly buildTypeModel: Model<BuildTypesDocument>,
|
||||
) { }
|
||||
|
||||
async findAll(skip: number, limit: number, sort?: Record<string, 1 | -1>, filters?: Record<string, any>): Promise<ListBuildResponse> {
|
||||
const query: any = {}; if (filters && Object.keys(filters).length > 0) { Object.assign(query, filters) };
|
||||
const totalCount = await this.buildModel.countDocuments(query).exec();
|
||||
const data = await this.buildModel.find(query).populate('buildType').skip(skip).limit(limit).sort(sort).exec();
|
||||
return { data, totalCount };
|
||||
}
|
||||
|
||||
async findById(id: Types.ObjectId, projection?: any): Promise<BuildDocument | null> {
|
||||
return this.buildModel.findById(id, projection, { lean: false }).populate({ path: 'buildArea', select: projection?.buildArea }).exec();
|
||||
}
|
||||
|
||||
async create(input: CreateBuildInput): Promise<BuildDocument> {
|
||||
const getObjectIDofToken = await this.buildTypeModel.findOne({ _id: new Types.ObjectId(input.buildType) });
|
||||
const build = new this.buildModel(input);
|
||||
if (!getObjectIDofToken?._id) { throw new Error('Build type not found') }
|
||||
const idOfBuildTypes = new Types.ObjectId(getObjectIDofToken._id)
|
||||
build.set({ buildType: idOfBuildTypes }); await build.populate('buildType');
|
||||
return build.save()
|
||||
}
|
||||
|
||||
async update(uuid: string, input: UpdateBuildInput): Promise<BuildDocument> {
|
||||
let idOfBuildTypes: Types.ObjectId | null = null;
|
||||
if (input.buildType) {
|
||||
const buildTypeDoc = await this.buildTypeModel.findOne({ _id: new Types.ObjectId(input.buildType) });
|
||||
if (!buildTypeDoc?._id) { throw new Error('Build type not found') }; idOfBuildTypes = new Types.ObjectId(buildTypeDoc._id);
|
||||
}
|
||||
const build = await this.buildModel.findById(new Types.ObjectId(uuid));
|
||||
if (!build) { throw new Error('Build not found') }
|
||||
const { info, buildType: _ignoredBuildType, ...rest } = input;
|
||||
if (Object.keys(rest).length > 0) { build.set(rest) }
|
||||
if (info) { build.set({ info: { ...(build.info as any)?.toObject?.() ?? build.info ?? {}, ...info } }) }
|
||||
if (idOfBuildTypes) { build.set({ buildType: idOfBuildTypes }) }
|
||||
const saved = await build.save(); await saved.populate('buildType'); return saved;
|
||||
}
|
||||
|
||||
async delete(uuid: string): Promise<boolean> {
|
||||
const build = await this.buildModel.deleteMany({ _id: new Types.ObjectId(uuid) }); return build.deletedCount > 0;
|
||||
}
|
||||
|
||||
async updateResponsible(uuid: string, input: UpdateBuildResponsibleInput): Promise<BuildDocument> {
|
||||
const build = await this.buildModel.findOne({ _id: new Types.ObjectId(uuid) }); if (!build) { throw new Error('Build not found') }; build.set({ responsible: input }); return build.save()
|
||||
}
|
||||
|
||||
async updateAttribute(uuid: string, input: UpdateBuildAttributeInput): Promise<BuildDocument> {
|
||||
const build = await this.buildModel.findOne({ _id: new Types.ObjectId(uuid) }); if (!build) { throw new Error('Build not found') }; build.set({ attribute: input }); return build.save()
|
||||
}
|
||||
|
||||
async findAllAreas(id: string, skip: number, limit: number, sort?: Record<string, 1 | -1>, filters?: Record<string, any>): Promise<ListPartialAreaResponse> {
|
||||
const buildId = new Types.ObjectId(id);
|
||||
const { keptIds } = await cleanRefArrayField({ parentModel: this.buildModel, refModel: this.areaModel, parentId: buildId, fieldName: "areas", });
|
||||
if (keptIds.length === 0) { return { data: [], totalCount: 0 } }
|
||||
const query: any = { _id: { $in: keptIds } };
|
||||
if (filters && Object.keys(filters).length > 0) { Object.assign(query, filters) }
|
||||
const totalCount = await this.areaModel.countDocuments(query).exec();
|
||||
const data = await this.areaModel.find(query).skip(skip).limit(limit).sort(sort).exec();
|
||||
return { data, totalCount };
|
||||
}
|
||||
|
||||
async findAllIbans(id: string, skip: number, limit: number, sort?: Record<string, 1 | -1>, filters?: Record<string, any>): Promise<ListPartialIbanResponse> {
|
||||
const buildId = new Types.ObjectId(id);
|
||||
const { keptIds } = await cleanRefArrayField({ parentModel: this.buildModel, refModel: this.ibanModel, parentId: buildId, fieldName: "ibans", });
|
||||
if (keptIds.length === 0) { return { data: [], totalCount: 0 } }
|
||||
const query: any = { _id: { $in: keptIds } };
|
||||
if (filters && Object.keys(filters).length > 0) { Object.assign(query, filters) }
|
||||
const totalCount = await this.ibanModel.countDocuments(query).exec();
|
||||
const data = await this.ibanModel.find(query).skip(skip).limit(limit).sort(sort).exec();
|
||||
return { data, totalCount };
|
||||
}
|
||||
|
||||
async findAllCompaniesAndResponsibles(id: string, skip: number, limit: number, sort?: Record<string, 1 | -1>, filters?: Record<string, any>): Promise<ListPartialCompanyResponse> {
|
||||
const buildId = new Types.ObjectId(id);
|
||||
const build = await this.buildModel.findById(buildId).lean();
|
||||
if (!build) throw new Error('Build not found');
|
||||
const responsibles = (build.responsibles || []) as { company?: string; person?: string }[];
|
||||
if (responsibles.length === 0) { return { data: [], totalCount: 0 } }
|
||||
console.dir({ responsibles }, { depth: Infinity });
|
||||
const companyIds = Array.from(new Set(responsibles.map(r => r.company).filter((id): id is string => !!id))).map(id => new Types.ObjectId(id));
|
||||
const personIds = Array.from(new Set(responsibles.map(r => r.person).filter((id): id is string => !!id))).map(id => new Types.ObjectId(id));
|
||||
console.dir({ companyIds, personIds }, { depth: Infinity });
|
||||
const t = await this.companyModel.find({ _id: { $in: companyIds } })
|
||||
const l = await this.companyModel.find({ _id: { $in: companyIds } }).lean()
|
||||
console.dir({ t, l }, { depth: Infinity })
|
||||
const [companies, persons] = await Promise.all([this.companyModel.find({ _id: { $in: companyIds } }).lean(), this.personModel.find({ _id: { $in: personIds } }).lean(),]);
|
||||
console.dir({ companies, persons }, { depth: Infinity })
|
||||
const companyMap = new Map(companies.map(c => [String(c._id), c]));
|
||||
const personMap = new Map(persons.map(p => [String(p._id), p]));
|
||||
const cleanedResponsibles: { company?: string; person?: string }[] = [];
|
||||
const resolvedList: { company?: any; person?: any }[] = [];
|
||||
for (const r of responsibles) {
|
||||
const companyId = r.company && String(r.company);
|
||||
const personId = r.person && String(r.person);
|
||||
const companyDoc = companyId ? companyMap.get(companyId) : undefined;
|
||||
const personDoc = personId ? personMap.get(personId) : undefined;
|
||||
if ((companyId && !companyDoc) || (personId && !personDoc)) { continue }
|
||||
cleanedResponsibles.push({ company: companyId, person: personId });
|
||||
resolvedList.push({ company: companyDoc, person: personDoc });
|
||||
}
|
||||
console.dir({ buildId, cleanedResponsibles, resolvedList }, { depth: Infinity });
|
||||
await this.buildModel.updateOne({ _id: buildId }, { $set: { responsibles: cleanedResponsibles } });
|
||||
const totalCount = resolvedList.length;
|
||||
const data = resolvedList.slice(skip, skip + limit);
|
||||
return { data, totalCount };
|
||||
}
|
||||
|
||||
buildProjection(fields: Record<string, any>): any {
|
||||
const projection: any = {};
|
||||
for (const key in fields) {
|
||||
if (key === 'build' && typeof fields[key] === 'object') { for (const subField of Object.keys(fields[key])) { projection[`build.${subField}`] = 1 } }
|
||||
else { projection[key] = 1 }
|
||||
}
|
||||
return projection;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
import { ExpiryBaseInput } from "@/models/base.model";
|
||||
import { InputType, Field } from "@nestjs/graphql";
|
||||
|
||||
@InputType()
|
||||
export class CreateBuildInfoInput {
|
||||
|
||||
@Field()
|
||||
govAddressCode: string;
|
||||
|
||||
@Field()
|
||||
buildName: string;
|
||||
|
||||
@Field()
|
||||
buildNo: string;
|
||||
|
||||
@Field()
|
||||
maxFloor: number;
|
||||
|
||||
@Field()
|
||||
undergroundFloor: number;
|
||||
|
||||
@Field()
|
||||
buildDate: Date;
|
||||
|
||||
@Field()
|
||||
decisionPeriodDate: Date;
|
||||
|
||||
@Field()
|
||||
taxNo: string;
|
||||
|
||||
@Field()
|
||||
liftCount: number;
|
||||
|
||||
@Field()
|
||||
heatingSystem: boolean;
|
||||
|
||||
@Field()
|
||||
coolingSystem: boolean;
|
||||
|
||||
@Field()
|
||||
hotWaterSystem: boolean;
|
||||
|
||||
@Field()
|
||||
blockServiceManCount: number;
|
||||
|
||||
@Field()
|
||||
securityServiceManCount: number;
|
||||
|
||||
@Field()
|
||||
garageCount: number;
|
||||
|
||||
@Field({ nullable: true })
|
||||
managementRoomId?: string;
|
||||
|
||||
}
|
||||
|
||||
@InputType()
|
||||
export class CreateBuildInput extends ExpiryBaseInput {
|
||||
|
||||
@Field()
|
||||
buildType: string;
|
||||
|
||||
@Field(() => CreateBuildInfoInput)
|
||||
info: CreateBuildInfoInput;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
import { Field, Int, ObjectType } from "@nestjs/graphql";
|
||||
import { Build, BuildIban } from "@/models/build.model";
|
||||
import { BuildArea } from "@/models/build-area.model";
|
||||
import { Company } from "@/models/company.model";
|
||||
import { Person } from "@/models/person.model";
|
||||
|
||||
@ObjectType()
|
||||
export class ListBuildResponse {
|
||||
|
||||
@Field(() => [Build], { nullable: true })
|
||||
data?: Build[];
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
totalCount?: number;
|
||||
|
||||
}
|
||||
|
||||
@ObjectType()
|
||||
export class ListPartialAreaResponse {
|
||||
|
||||
@Field(() => [BuildArea], { nullable: true })
|
||||
data?: BuildArea[];
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
totalCount?: number;
|
||||
|
||||
}
|
||||
|
||||
@ObjectType()
|
||||
export class ListPartialIbanResponse {
|
||||
|
||||
@Field(() => [BuildIban], { nullable: true })
|
||||
data?: BuildIban[];
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
totalCount?: number;
|
||||
|
||||
}
|
||||
|
||||
@ObjectType()
|
||||
class ResponsibleCompanyPerson {
|
||||
|
||||
@Field(() => Company, { nullable: true })
|
||||
company?: Company;
|
||||
|
||||
@Field(() => Person, { nullable: true })
|
||||
person?: Person;
|
||||
}
|
||||
|
||||
@ObjectType()
|
||||
export class ListPartialCompanyResponse {
|
||||
|
||||
@Field(() => [ResponsibleCompanyPerson])
|
||||
data: ResponsibleCompanyPerson[];
|
||||
|
||||
@Field(() => Int)
|
||||
totalCount: number;
|
||||
}
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
import { InputType, Field, ID } from "@nestjs/graphql";
|
||||
import { ExpiryBaseInput } from "@/models/base.model";
|
||||
|
||||
@InputType()
|
||||
export class UpdateResponsibleInput {
|
||||
|
||||
@Field(() => ID, { nullable: true })
|
||||
company?: string;
|
||||
|
||||
@Field(() => ID, { nullable: true })
|
||||
person?: string;
|
||||
|
||||
}
|
||||
|
||||
@InputType()
|
||||
export class UpdateBuildAttributeInput {
|
||||
|
||||
@Field(() => ID, { nullable: true })
|
||||
site?: string;
|
||||
|
||||
@Field(() => ID, { nullable: true })
|
||||
address?: string;
|
||||
|
||||
@Field(() => [ID], { nullable: true })
|
||||
areas?: string[];
|
||||
|
||||
@Field(() => [ID], { nullable: true })
|
||||
ibans?: string[];
|
||||
|
||||
@Field(() => [UpdateResponsibleInput], { nullable: true })
|
||||
responsibles?: UpdateResponsibleInput[];
|
||||
|
||||
}
|
||||
|
||||
@InputType()
|
||||
export class UpdateBuildResponsibleInput {
|
||||
|
||||
@Field(() => ID, { nullable: true })
|
||||
company?: string;
|
||||
|
||||
@Field(() => ID, { nullable: true })
|
||||
person?: string;
|
||||
|
||||
}
|
||||
|
||||
@InputType()
|
||||
export class UpdateBuildInfoInput {
|
||||
|
||||
@Field({ nullable: true })
|
||||
govAddressCode?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
buildName?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
buildNo?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
maxFloor?: number;
|
||||
|
||||
@Field({ nullable: true })
|
||||
undergroundFloor?: number;
|
||||
|
||||
@Field({ nullable: true })
|
||||
buildDate?: Date;
|
||||
|
||||
@Field({ nullable: true })
|
||||
decisionPeriodDate?: Date;
|
||||
|
||||
@Field({ nullable: true })
|
||||
taxNo?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
liftCount?: number;
|
||||
|
||||
@Field({ nullable: true })
|
||||
heatingSystem?: boolean;
|
||||
|
||||
@Field({ nullable: true })
|
||||
coolingSystem?: boolean;
|
||||
|
||||
@Field({ nullable: true })
|
||||
hotWaterSystem?: boolean;
|
||||
|
||||
@Field({ nullable: true })
|
||||
blockServiceManCount?: number;
|
||||
|
||||
@Field({ nullable: true })
|
||||
securityServiceManCount?: number;
|
||||
|
||||
@Field({ nullable: true })
|
||||
garageCount?: number;
|
||||
|
||||
@Field({ nullable: true })
|
||||
managementRoomId?: string;
|
||||
|
||||
}
|
||||
|
||||
@InputType()
|
||||
export class UpdateBuildInput extends ExpiryBaseInput {
|
||||
|
||||
@Field({ nullable: true })
|
||||
buildType?: string;
|
||||
|
||||
@Field(() => UpdateBuildInfoInput, { nullable: true })
|
||||
info?: UpdateBuildInfoInput;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
mutation CreateBuild($input: CreateBuildInput!) {
|
||||
createBuild(input: $input) {
|
||||
_id
|
||||
uuid
|
||||
createdAt
|
||||
expiryStarts
|
||||
expiryEnds
|
||||
buildType
|
||||
collectionToken
|
||||
ibans
|
||||
responsibles {
|
||||
company
|
||||
person
|
||||
}
|
||||
areas
|
||||
info {
|
||||
govAddressCode
|
||||
buildName
|
||||
buildNo
|
||||
maxFloor
|
||||
undergroundFloor
|
||||
buildDate
|
||||
decisionPeriodDate
|
||||
taxNo
|
||||
liftCount
|
||||
heatingSystem
|
||||
coolingSystem
|
||||
hotWaterSystem
|
||||
blockServiceManCount
|
||||
securityServiceManCount
|
||||
garageCount
|
||||
managementRoomId
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"input": {
|
||||
"expiryStarts": "2025-01-10T08:00:00.000Z",
|
||||
"expiryEnds": "2099-12-31T00:00:00.000Z",
|
||||
"buildType": "675abc12ef90123456789aaa",
|
||||
"collectionToken": "COLL-TEST-2025-XYZ",
|
||||
"info": {
|
||||
"govAddressCode": "TR-34-12345",
|
||||
"buildName": "Aether Residence",
|
||||
"buildNo": "B-12",
|
||||
"maxFloor": 12,
|
||||
"undergroundFloor": 2,
|
||||
"buildDate": "2020-06-15T00:00:00.000Z",
|
||||
"decisionPeriodDate": "2020-05-01T00:00:00.000Z",
|
||||
"taxNo": "12345678901",
|
||||
"liftCount": 3,
|
||||
"heatingSystem": true,
|
||||
"coolingSystem": true,
|
||||
"hotWaterSystem": true,
|
||||
"blockServiceManCount": 2,
|
||||
"securityServiceManCount": 1,
|
||||
"garageCount": 30,
|
||||
"managementRoomId": 101
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query ListBuild($input: ListArguments!) {
|
||||
builds(input: $input) {
|
||||
data {
|
||||
_id
|
||||
buildType {
|
||||
token
|
||||
typeToken
|
||||
type
|
||||
}
|
||||
collectionToken
|
||||
info {
|
||||
govAddressCode
|
||||
buildName
|
||||
buildNo
|
||||
maxFloor
|
||||
undergroundFloor
|
||||
buildDate
|
||||
decisionPeriodDate
|
||||
taxNo
|
||||
liftCount
|
||||
heatingSystem
|
||||
coolingSystem
|
||||
hotWaterSystem
|
||||
blockServiceManCount
|
||||
securityServiceManCount
|
||||
garageCount
|
||||
managementRoomId
|
||||
}
|
||||
}
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
|
||||
query GetBuildsAreas($id: String!, $input: ListArguments!) {
|
||||
getBuildsAreas(id: $id, input: $input) {
|
||||
data {
|
||||
_id
|
||||
uuid
|
||||
areaName
|
||||
areaCode
|
||||
areaType
|
||||
areaNetSize
|
||||
areaDirection
|
||||
areaGrossSize
|
||||
}
|
||||
totalCount
|
||||
__typename
|
||||
}
|
||||
}
|
||||
|
|
@ -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 { }
|
||||
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
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 { ListCompanyResponse } from './dto/list-company.response';
|
||||
import { ListArguments } from '@/dto/list.input';
|
||||
import { UpdateCompanyInput } from './dto/update-company.input';
|
||||
import type { GraphQLResolveInfo } from 'graphql';
|
||||
import graphqlFields from 'graphql-fields';
|
||||
|
||||
@Resolver()
|
||||
export class CompanyResolver {
|
||||
|
||||
constructor(private readonly companyService: CompanyService) { }
|
||||
|
||||
@Query(() => ListCompanyResponse, { name: 'getCompanies' })
|
||||
async getCompanies(@Info() info: GraphQLResolveInfo, @Args('input') input: ListArguments): Promise<ListCompanyResponse> {
|
||||
const fields = graphqlFields(info); const projection = this.companyService.buildProjection(fields?.data); const { skip, limit, sort, filters } = input;
|
||||
return await this.companyService.findAll(projection, skip, limit, sort, filters);
|
||||
}
|
||||
|
||||
@Query(() => Company, { name: 'getCompany', 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) }
|
||||
|
||||
@Mutation(() => Company, { name: 'updateCompany' })
|
||||
async updateCompany(@Args('uuid') uuid: string, @Args('input') input: UpdateCompanyInput): Promise<Company> { return this.companyService.update(uuid, input) }
|
||||
|
||||
@Mutation(() => Boolean, { name: 'deleteCompany' })
|
||||
async deleteCompany(@Args('uuid') uuid: string): Promise<boolean> { return this.companyService.delete(uuid) }
|
||||
|
||||
}
|
||||
|
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
import { ExpiryBaseInput } from '@/models/base.model';
|
||||
import { InputType, Field, ID } from '@nestjs/graphql';
|
||||
|
||||
@InputType()
|
||||
export class CreateCompanyInput extends ExpiryBaseInput {
|
||||
|
||||
@Field()
|
||||
formal_name: string;
|
||||
|
||||
@Field()
|
||||
company_type: string;
|
||||
|
||||
@Field()
|
||||
commercial_type: string;
|
||||
|
||||
@Field()
|
||||
tax_no: string;
|
||||
|
||||
@Field()
|
||||
public_name: string;
|
||||
|
||||
@Field()
|
||||
company_tag: string;
|
||||
|
||||
@Field({ defaultValue: 'TR' })
|
||||
default_lang_type: string;
|
||||
|
||||
@Field({ defaultValue: 'TL' })
|
||||
default_money_type: string;
|
||||
|
||||
@Field({ defaultValue: false })
|
||||
is_commercial?: boolean;
|
||||
|
||||
@Field({ defaultValue: false })
|
||||
is_blacklist?: boolean;
|
||||
|
||||
@Field()
|
||||
parent_id?: string;
|
||||
|
||||
@Field()
|
||||
workplace_no?: string;
|
||||
|
||||
@Field()
|
||||
official_address?: string;
|
||||
|
||||
@Field()
|
||||
top_responsible_company?: string;
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
import { InputType, Field } from '@nestjs/graphql';
|
||||
|
||||
@InputType()
|
||||
export class UpdateCompanyInput {
|
||||
|
||||
@Field({ nullable: true })
|
||||
formal_name?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
company_type?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
commercial_type?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
tax_no?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
public_name?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
company_tag?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
default_lang_type?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
default_money_type?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
is_commercial?: boolean;
|
||||
|
||||
@Field({ nullable: true })
|
||||
is_blacklist?: boolean;
|
||||
|
||||
@Field({ nullable: true })
|
||||
parent_id?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
workplace_no?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
official_address?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
top_responsible_company?: string;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { GraphQLJSONObject } from 'graphql-type-json';
|
||||
import { Field, Int, InputType, ObjectType } from '@nestjs/graphql';
|
||||
|
||||
@InputType()
|
||||
export class ListArguments {
|
||||
|
||||
@Field(() => GraphQLJSONObject, { nullable: true })
|
||||
filters?: any;
|
||||
|
||||
@Field(() => GraphQLJSONObject, { nullable: true })
|
||||
sort?: any;
|
||||
|
||||
@Field(() => Int, { defaultValue: 0 })
|
||||
skip: number;
|
||||
|
||||
@Field(() => Int, { defaultValue: 10 })
|
||||
limit: number;
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import { randomBytes, createHash } from "crypto";
|
||||
|
||||
export function generateResetToken(length: number = 128) {
|
||||
const resetToken = randomBytes(length).toString("hex");
|
||||
const hashedToken = createHash("sha256").update(resetToken).digest("hex");
|
||||
const expires = Date.now() + 1000 * 60 * 60 * 24 * 3;
|
||||
return { resetToken, hashedToken, expires };
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import { Types, Model } from "mongoose";
|
||||
|
||||
type ObjectIdLike = Types.ObjectId | string;
|
||||
|
||||
interface CleanRefArrayParams {
|
||||
parentModel: Model<any>;
|
||||
refModel: Model<any>;
|
||||
parentId: ObjectIdLike;
|
||||
fieldName: string;
|
||||
}
|
||||
|
||||
export async function cleanRefArrayField({ parentModel, refModel, parentId, fieldName }: CleanRefArrayParams): Promise<{ keptIds: Types.ObjectId[]; removedIds: Types.ObjectId[] }> {
|
||||
const parent = await parentModel.findById(parentId).lean();
|
||||
if (!parent) { throw new Error("Parent document not found") }
|
||||
const rawIds: ObjectIdLike[] = parent[fieldName] || [];
|
||||
if (!Array.isArray(rawIds) || rawIds.length === 0) { return { keptIds: [], removedIds: [] } }
|
||||
const ids = rawIds.map((id) => typeof id === "string" ? new Types.ObjectId(id) : id);
|
||||
const existing = await refModel.find({ _id: { $in: ids } }).select("_id").lean();
|
||||
const existingSet = new Set(existing.map((d) => String(d._id)));
|
||||
const keptIds = ids.filter((id) => existingSet.has(String(id)));
|
||||
const removedIds = ids.filter((id) => !existingSet.has(String(id)));
|
||||
await parentModel.updateOne({ _id: parentId }, { $set: { [fieldName]: keptIds } });
|
||||
return { keptIds, removedIds };
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import { ExpiryBaseInput } from '@/models/base.model';
|
||||
import { InputType, Field } from '@nestjs/graphql';
|
||||
|
||||
@InputType()
|
||||
export class CreateLivingSpaceInput extends ExpiryBaseInput {
|
||||
|
||||
@Field()
|
||||
buildID: string;
|
||||
|
||||
@Field()
|
||||
partID: string;
|
||||
|
||||
@Field()
|
||||
userTypeID: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
companyID?: string;
|
||||
|
||||
@Field()
|
||||
personID: string;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import { InputType, Field } from '@nestjs/graphql';
|
||||
|
||||
@InputType()
|
||||
export class GetLivingSpaceInput {
|
||||
|
||||
@Field()
|
||||
buildID: string;
|
||||
|
||||
@Field()
|
||||
uuid: string;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
import { Field, ObjectType } from "@nestjs/graphql";
|
||||
import { Int } from "@nestjs/graphql";
|
||||
import { LivingSpaces } from "@/models/living-spaces.model";
|
||||
|
||||
@ObjectType()
|
||||
export class ListLivingSpaceResponse {
|
||||
|
||||
@Field(() => [LivingSpaces], { nullable: true })
|
||||
data?: LivingSpaces[];
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
totalCount?: number;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
import { ExpiryBaseInput } from '@/models/base.model';
|
||||
import { InputType, Field } from '@nestjs/graphql';
|
||||
|
||||
@InputType()
|
||||
export class UpdateLivingSpaceInput extends ExpiryBaseInput {
|
||||
|
||||
@Field({ nullable: true })
|
||||
partID?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
userTypeID?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
companyID?: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
personID?: string;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { LivingSpaceService } from './living-space.service';
|
||||
import { LivingSpaceResolver } from './living-space.resolver';
|
||||
import { MongooseModule } from '@nestjs/mongoose';
|
||||
import { LivingSpaces, LivingSpacesSchema } from '@/models/living-spaces.model';
|
||||
import { UserType, UserTypeSchema } from '@/models/user-type.model';
|
||||
import { Build, BuildSchema } from '@/models/build.model';
|
||||
|
||||
@Module({
|
||||
imports: [MongooseModule.forFeature([
|
||||
{ name: LivingSpaces.name, schema: LivingSpacesSchema },
|
||||
{ name: UserType.name, schema: UserTypeSchema },
|
||||
{ name: Build.name, schema: BuildSchema },
|
||||
])],
|
||||
providers: [LivingSpaceService, LivingSpaceResolver]
|
||||
})
|
||||
export class LivingSpaceModule { }
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { LivingSpaceResolver } from './living-space.resolver';
|
||||
|
||||
describe('LivingSpaceResolver', () => {
|
||||
let resolver: LivingSpaceResolver;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [LivingSpaceResolver],
|
||||
}).compile();
|
||||
|
||||
resolver = module.get<LivingSpaceResolver>(LivingSpaceResolver);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(resolver).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
import { Resolver, Args, ID, Info, Mutation, Query } from '@nestjs/graphql';
|
||||
import { Types } from 'mongoose';
|
||||
import { ListArguments } from '@/dto/list.input';
|
||||
import { LivingSpaces } from '@/models/living-spaces.model';
|
||||
import { ListLivingSpaceResponse } from './dto/list-living-space.response';
|
||||
import { CreateLivingSpaceInput } from './dto/create-living-space.input';
|
||||
import { UpdateLivingSpaceInput } from './dto/update-living-space.input';
|
||||
import { LivingSpaceService } from './living-space.service';
|
||||
import type { GraphQLResolveInfo } from 'graphql';
|
||||
import graphqlFields from 'graphql-fields';
|
||||
import { GetLivingSpaceInput } from './dto/get-living-space.input';
|
||||
|
||||
@Resolver()
|
||||
export class LivingSpaceResolver {
|
||||
|
||||
constructor(private readonly livingSpaceService: LivingSpaceService) { }
|
||||
|
||||
@Query(() => ListLivingSpaceResponse, { name: 'getLivingSpaces' })
|
||||
async getLivingSpaces(@Info() info: GraphQLResolveInfo, @Args('buildID') buildID: string, @Args('input') input: ListArguments): Promise<ListLivingSpaceResponse> {
|
||||
const fields = graphqlFields(info); const projection = this.livingSpaceService.buildProjection(fields?.data); const { skip, limit, sort, filters } = input;
|
||||
return await this.livingSpaceService.findAll(buildID, projection, skip, limit, sort, filters);
|
||||
}
|
||||
|
||||
@Query(() => LivingSpaces, { name: 'getLivingSpace', nullable: true })
|
||||
async getLivingSpace(@Args('id', { type: () => ID }) id: string, @Args('buildID') buildID: string, @Info() info: GraphQLResolveInfo): Promise<LivingSpaces | null> {
|
||||
const fields = graphqlFields(info); const projection = this.livingSpaceService.buildProjection(fields); return this.livingSpaceService.findById(buildID, new Types.ObjectId(id), projection);
|
||||
}
|
||||
|
||||
@Query(() => LivingSpaces, { name: 'getLivingSpaceDetail', nullable: true })
|
||||
async getLivingSpaceDetail(@Args('uuid') uuid: string, @Args('buildID') buildID: string): Promise<LivingSpaces | null> { return this.livingSpaceService.getDetail(buildID, uuid) }
|
||||
|
||||
@Mutation(() => LivingSpaces, { name: 'createLivingSpace' })
|
||||
async createLivingSpace(@Args('input') input: CreateLivingSpaceInput): Promise<LivingSpaces> { return this.livingSpaceService.create(input) }
|
||||
|
||||
@Mutation(() => LivingSpaces, { name: 'updateLivingSpace' })
|
||||
async updateLivingSpace(@Args('buildID') buildID: string, @Args('uuid') uuid: string, @Args('input') input: UpdateLivingSpaceInput): Promise<LivingSpaces> { return this.livingSpaceService.update(buildID, uuid, input) }
|
||||
|
||||
@Mutation(() => Boolean, { name: 'deleteLivingSpace' })
|
||||
async deleteLivingSpace(@Args('buildID') buildID: string, @Args('uuid') uuid: string): Promise<boolean> { return this.livingSpaceService.delete(buildID, uuid) }
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { LivingSpaceService } from './living-space.service';
|
||||
|
||||
describe('LivingSpaceService', () => {
|
||||
let service: LivingSpaceService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [LivingSpaceService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<LivingSpaceService>(LivingSpaceService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { Types, Connection, Model } from 'mongoose';
|
||||
import { getDynamicLivingSpaceModel, LivingSpacesDocument } from '@/models/living-spaces.model';
|
||||
import { ListLivingSpaceResponse } from './dto/list-living-space.response';
|
||||
import { CreateLivingSpaceInput } from './dto/create-living-space.input';
|
||||
import { UpdateLivingSpaceInput } from './dto/update-living-space.input';
|
||||
import { InjectConnection, InjectModel } from '@nestjs/mongoose';
|
||||
import { UserTypeDocument } from '@/models/user-type.model';
|
||||
import { BuildDocument } from '@/models/build.model';
|
||||
|
||||
interface UpdateInput {
|
||||
userType?: Types.ObjectId;
|
||||
part?: Types.ObjectId | null;
|
||||
company?: Types.ObjectId;
|
||||
person?: Types.ObjectId;
|
||||
expiryStarts?: Date;
|
||||
expiryEnds?: Date;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class LivingSpaceService {
|
||||
|
||||
constructor(
|
||||
@InjectConnection() private readonly connection: Connection,
|
||||
@InjectModel('UserType') private readonly userTypeModel: Model<UserTypeDocument>,
|
||||
@InjectModel('Build') private readonly buildModel: Model<BuildDocument>
|
||||
) { }
|
||||
|
||||
async findAll(buildID: string, projection: any, skip: number, limit: number, sort?: Record<string, 1 | -1>, filters?: Record<string, any>): Promise<ListLivingSpaceResponse> {
|
||||
const selectedModel = getDynamicLivingSpaceModel(buildID, this.connection);
|
||||
const query: any = {}; if (filters && Object.keys(filters).length > 0) { Object.assign(query, filters) };
|
||||
const totalCount = await selectedModel.countDocuments(query).exec();
|
||||
const data = await selectedModel.find(query, projection, { lean: false })
|
||||
.populate({ path: 'build', select: { ...projection?.build, _id: 0 } })
|
||||
.populate({ path: 'person', select: { ...projection?.person, _id: 0 } })
|
||||
.populate({ path: 'company', select: { ...projection?.company, _id: 0 } })
|
||||
.populate({ path: 'userType', select: { ...projection?.userType, _id: 0 } })
|
||||
.populate({ path: 'part', select: { ...projection?.part, _id: 0 } })
|
||||
.skip(skip).limit(limit).sort(sort).exec();
|
||||
return { data, totalCount };
|
||||
}
|
||||
|
||||
async getDetail(buildID: string, uuid: string): Promise<any | null> {
|
||||
const buildObjectID = new Types.ObjectId(buildID); const build = await this.buildModel.findById(buildObjectID); if (!build) { throw new Error('Build not found') };
|
||||
const selectedModel = getDynamicLivingSpaceModel(buildID, this.connection); const data = await selectedModel.findOne({ uuid }, { lean: false }).exec();
|
||||
if (!data) { throw new Error('Living space not found') }; return data;
|
||||
}
|
||||
|
||||
async findById(buildID: string, id: Types.ObjectId, projection?: any): Promise<LivingSpacesDocument | null> {
|
||||
const selectedModel = getDynamicLivingSpaceModel(buildID, this.connection);
|
||||
return selectedModel.findById(id, projection, { lean: false }).populate({ path: 'company', select: projection?.company }).exec();
|
||||
}
|
||||
|
||||
async create(input: CreateLivingSpaceInput): Promise<LivingSpacesDocument> {
|
||||
if (!input.buildID) { throw new Error('Build ID is required') }
|
||||
const LivingSpaceModel = getDynamicLivingSpaceModel(input.buildID, this.connection);
|
||||
const docInput: Partial<LivingSpacesDocument> = {
|
||||
build: new Types.ObjectId(input.buildID), part: new Types.ObjectId(input.partID), userType: new Types.ObjectId(input.userTypeID),
|
||||
company: !!input.companyID ? new Types.ObjectId(input.companyID) : undefined, person: new Types.ObjectId(input.personID),
|
||||
expiryStarts: input.expiryStarts ? new Date(input.expiryStarts) : new Date(), expiryEnds: input.expiryEnds ? new Date(input.expiryEnds) : new Date('2099-12-31'),
|
||||
}; const doc = new LivingSpaceModel(docInput); return await doc.save()
|
||||
}
|
||||
|
||||
async update(buildID: string, uuid: string, input: UpdateLivingSpaceInput): Promise<LivingSpacesDocument> {
|
||||
if (!buildID) { throw new Error('Build ID is required') }
|
||||
const selectedModel = getDynamicLivingSpaceModel(buildID, this.connection);
|
||||
const livingSpace = await selectedModel.findOne({ uuid }); const userTypeSelected = await this.userTypeModel.findById(new Types.ObjectId(input.userTypeID)).exec(); const newInput: UpdateInput = {}
|
||||
if (userTypeSelected?.isProperty) { if (!!input?.partID) { newInput.part = new Types.ObjectId(input.partID) } } else { newInput.part = null }
|
||||
if (!!input?.companyID) { newInput.company = new Types.ObjectId(input.companyID) }
|
||||
if (!!input?.personID) { newInput.person = new Types.ObjectId(input.personID) }; if (!!input?.userTypeID) { newInput.userType = new Types.ObjectId(input.userTypeID) }
|
||||
if (!!input?.expiryStarts) { newInput.expiryStarts = input.expiryStarts }; if (!!input?.expiryEnds) { newInput.expiryEnds = input.expiryEnds }
|
||||
if (!livingSpace) { throw new Error('Company not found') }; livingSpace.set(newInput); return livingSpace.save();
|
||||
}
|
||||
|
||||
async delete(buildID: string, uuid: string): Promise<boolean> { if (!buildID) { throw new Error('Build ID is required') } const selectedModel = getDynamicLivingSpaceModel(buildID, this.connection); const company = await selectedModel.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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
import { NestFactory } from '@nestjs/core';
|
||||
import { AppModule } from './app.module';
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create(AppModule);
|
||||
await app.listen(process.env.PORT ?? 3001);
|
||||
}
|
||||
bootstrap();
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
import { Prop } from '@nestjs/mongoose';
|
||||
import { randomUUID } from 'crypto';
|
||||
import { ObjectType, InputType, Field } from '@nestjs/graphql';
|
||||
|
||||
@ObjectType({ isAbstract: true })
|
||||
export class Base {
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Prop({ default: () => randomUUID(), unique: true })
|
||||
uuid: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Prop({ default: () => new Date(Date.now()) })
|
||||
createdAt: Date;
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Prop({ default: () => new Date(Date.now()) })
|
||||
updatedAt: Date;
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Prop({ default: false, required: false })
|
||||
isConfirmed?: boolean;
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Prop({ default: false, required: false })
|
||||
deleted?: boolean;
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Prop({ default: true, required: false })
|
||||
active?: boolean;
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Prop({ default: randomUUID })
|
||||
crypUuId: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Prop({ default: randomUUID })
|
||||
createdCredentialsToken: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Prop({ default: randomUUID })
|
||||
updatedCredentialsToken: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Prop({ default: randomUUID })
|
||||
confirmedCredentialsToken: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Prop({ default: false, required: false })
|
||||
isNotificationSend?: boolean;
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Prop({ default: false, required: false })
|
||||
isEmailSend?: boolean;
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Prop({ default: 0 })
|
||||
refInt: number;
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Prop({ default: randomUUID })
|
||||
refId: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Prop({ default: 0 })
|
||||
replicationId: number;
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Prop({ default: () => new Date(Date.now()), required: false })
|
||||
expiryStarts?: Date;
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Prop({ default: () => new Date('2099-12-31'), required: false })
|
||||
expiryEnds?: Date;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ObjectType({ isAbstract: true })
|
||||
export class CreatedBase {
|
||||
|
||||
@Field()
|
||||
@Prop({ default: () => new Date(Date.now()), required: false })
|
||||
createdAt?: Date;
|
||||
|
||||
@Field()
|
||||
@Prop({ default: () => new Date(Date.now()), required: false })
|
||||
updatedAt?: Date;
|
||||
|
||||
}
|
||||
|
||||
@ObjectType({ isAbstract: true })
|
||||
export class ExpiryBase {
|
||||
|
||||
@Field()
|
||||
@Prop({ default: () => new Date(Date.now()), required: false })
|
||||
expiryStarts?: Date;
|
||||
|
||||
@Field()
|
||||
@Prop({ default: () => new Date('2099-12-31'), required: false })
|
||||
expiryEnds?: Date;
|
||||
|
||||
}
|
||||
|
||||
@InputType()
|
||||
export class ExpiryBaseInput {
|
||||
|
||||
@Field({ nullable: true, defaultValue: new Date(Date.now()).toISOString() })
|
||||
expiryStarts?: Date;
|
||||
|
||||
@Field({ nullable: false, defaultValue: new Date('2099-12-31').toISOString() })
|
||||
expiryEnds?: Date;
|
||||
|
||||
}
|
||||
|
||||
@ObjectType({ isAbstract: true })
|
||||
export class ChangableBase {
|
||||
|
||||
@Field()
|
||||
@Prop({ default: () => new Date(Date.now()), required: false })
|
||||
expiryStarts?: Date;
|
||||
|
||||
@Field()
|
||||
@Prop({ default: () => new Date('2099-12-31'), required: false })
|
||||
expiryEnds?: Date;
|
||||
|
||||
@Field()
|
||||
@Prop({ default: false, required: false })
|
||||
isConfirmed?: boolean;
|
||||
|
||||
@Field()
|
||||
@Prop({ default: false, required: false })
|
||||
deleted?: boolean;
|
||||
|
||||
@Field()
|
||||
@Prop({ default: true, required: false })
|
||||
active?: boolean;
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
|
||||
import { Document, Types } from 'mongoose';
|
||||
import { ObjectType, Field, ID, Float } from '@nestjs/graphql';
|
||||
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;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
doorNumber: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
floorNumber: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
commentAddress: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
letterAddress: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
shortLetterAddress: string;
|
||||
|
||||
@Field(() => Float)
|
||||
@Prop({ required: true })
|
||||
latitude: number;
|
||||
|
||||
@Field(() => Float)
|
||||
@Prop({ required: true })
|
||||
longitude: number;
|
||||
|
||||
@Field(() => ID, { nullable: true })
|
||||
@Prop({ type: Types.ObjectId, ref: 'Street', required: false })
|
||||
street?: Types.ObjectId;
|
||||
|
||||
}
|
||||
|
||||
export type BuildAddressDocument = BuildAddress & Document;
|
||||
export const BuildAddressSchema = SchemaFactory.createForClass(BuildAddress);
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
|
||||
import { ObjectType, Field, ID, Float } from '@nestjs/graphql';
|
||||
import { Base } from '@/models/base.model';
|
||||
import { Document, Types } from 'mongoose';
|
||||
|
||||
@ObjectType()
|
||||
@Schema({ timestamps: true })
|
||||
export class BuildArea extends Base {
|
||||
|
||||
@Field(() => ID)
|
||||
readonly _id: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
areaName: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
areaCode: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
areaType: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
areaDirection: string;
|
||||
|
||||
@Field(() => Float)
|
||||
@Prop({ required: true })
|
||||
areaGrossSize: number;
|
||||
|
||||
@Field(() => Float)
|
||||
@Prop({ required: true })
|
||||
areaNetSize: number;
|
||||
|
||||
@Field(() => Float)
|
||||
@Prop({ required: true })
|
||||
width: number;
|
||||
|
||||
@Field(() => Float)
|
||||
@Prop({ required: true })
|
||||
size: number;
|
||||
|
||||
@Field(() => ID, { nullable: true })
|
||||
@Prop({ type: Types.ObjectId, ref: 'Build', required: false })
|
||||
buildId?: Types.ObjectId;
|
||||
|
||||
@Field(() => ID, { nullable: true })
|
||||
@Prop({ type: Types.ObjectId, ref: 'BuildType', required: false })
|
||||
partTypeId?: Types.ObjectId;
|
||||
|
||||
}
|
||||
|
||||
export type BuildAreaDocument = BuildArea & Document;
|
||||
export const BuildAreaSchema = SchemaFactory.createForClass(BuildArea);
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
|
||||
import { Document, Types } from 'mongoose';
|
||||
import { ObjectType, Field, ID, Float } from '@nestjs/graphql';
|
||||
import { Base } from '@/models/base.model';
|
||||
|
||||
@ObjectType()
|
||||
@Schema({ timestamps: true })
|
||||
export class BuildParts extends Base {
|
||||
|
||||
@Field(() => ID)
|
||||
readonly _id: string;
|
||||
|
||||
@Field(() => ID, { nullable: true })
|
||||
@Prop({ type: Types.ObjectId, ref: 'Build', required: false })
|
||||
buildId?: Types.ObjectId;
|
||||
|
||||
@Field(() => ID, { nullable: true })
|
||||
@Prop({ type: Types.ObjectId, ref: 'ApiEnumDropdown', required: false })
|
||||
directionId?: Types.ObjectId;
|
||||
|
||||
@Field(() => ID, { nullable: true })
|
||||
@Prop({ type: Types.ObjectId, ref: 'ApiEnumDropdown', required: false })
|
||||
typeId?: Types.ObjectId;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
addressGovCode: string;
|
||||
|
||||
@Field(() => Float)
|
||||
@Prop({ required: true })
|
||||
no: number;
|
||||
|
||||
@Field(() => Float)
|
||||
@Prop({ required: true })
|
||||
level: number;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
code: string;
|
||||
|
||||
@Field(() => Float)
|
||||
@Prop({ required: true })
|
||||
grossSize: number;
|
||||
|
||||
@Field(() => Float)
|
||||
@Prop({ required: true })
|
||||
netSize: number;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
defaultAccessory: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
humanLivability: boolean;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
key: string;
|
||||
|
||||
}
|
||||
|
||||
export type BuildPartsDocument = BuildParts & Document;
|
||||
export const BuildPartsSchema = SchemaFactory.createForClass(BuildParts);
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
|
||||
import { Types, Document } from 'mongoose';
|
||||
import { ObjectType, Field, ID } from '@nestjs/graphql';
|
||||
import { Base } from '@/models/base.model';
|
||||
|
||||
@ObjectType()
|
||||
@Schema({ timestamps: true })
|
||||
export class BuildSites extends Base {
|
||||
|
||||
@Field(() => ID)
|
||||
readonly _id: string;
|
||||
|
||||
@Field(() => String)
|
||||
@Prop({ required: true })
|
||||
siteName: string;
|
||||
|
||||
@Field(() => String)
|
||||
@Prop({ required: true })
|
||||
siteNo: string;
|
||||
|
||||
@Field(() => ID, { nullable: true })
|
||||
@Prop({ type: Types.ObjectId, ref: 'BuildAddress', required: false })
|
||||
address?: Types.ObjectId;
|
||||
|
||||
}
|
||||
|
||||
export type BuildSiteDocument = BuildSites & Document;
|
||||
export const BuildSiteSchema = SchemaFactory.createForClass(BuildSites);
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
import { ObjectType, Field, ID } from '@nestjs/graphql';
|
||||
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
|
||||
import { Document } from 'mongoose';
|
||||
import { Base } from '@/models/base.model';
|
||||
|
||||
@ObjectType()
|
||||
@Schema({ timestamps: true })
|
||||
export class BuildTypes extends Base {
|
||||
|
||||
@Field(() => ID)
|
||||
readonly _id: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
type: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
token: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
typeToken: string;
|
||||
|
||||
@Field({ nullable: true })
|
||||
@Prop({ required: false, default: '' })
|
||||
description: string;
|
||||
|
||||
}
|
||||
|
||||
export type BuildTypesDocument = BuildTypes & Document;
|
||||
export const BuildTypesSchema = SchemaFactory.createForClass(BuildTypes);
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
|
||||
import { Document, Types } from 'mongoose';
|
||||
import { ObjectType, Field, ID, Int } from '@nestjs/graphql';
|
||||
import { Base, CreatedBase } from '@/models/base.model';
|
||||
import { BuildTypes } from './build-types.model';
|
||||
|
||||
@ObjectType()
|
||||
@Schema({ timestamps: true })
|
||||
export class BuildIban extends Base {
|
||||
|
||||
@Field(() => ID)
|
||||
readonly _id: string;
|
||||
|
||||
@Field(() => ID, { nullable: true })
|
||||
@Prop({ type: Types.ObjectId, ref: 'Build', required: false })
|
||||
buildId?: Types.ObjectId;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
iban: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
startDate: Date;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
stopDate: Date;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true, default: 'TR0000000000000' })
|
||||
bankCode: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true, default: '????' })
|
||||
xcomment: string;
|
||||
|
||||
}
|
||||
|
||||
@ObjectType()
|
||||
export class BuildResponsible {
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@Prop({ type: String, default: '' })
|
||||
company?: string;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@Prop({ type: String, default: '' })
|
||||
person?: string;
|
||||
|
||||
}
|
||||
|
||||
@ObjectType()
|
||||
export class BuildInfo {
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
govAddressCode: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
buildName: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
buildNo: string;
|
||||
|
||||
@Field(() => Int)
|
||||
@Prop({ required: true })
|
||||
maxFloor: number;
|
||||
|
||||
@Field(() => Int)
|
||||
@Prop({ required: true })
|
||||
undergroundFloor: number;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
buildDate: Date;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
decisionPeriodDate: Date;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
taxNo: string;
|
||||
|
||||
@Field(() => Int)
|
||||
@Prop({ required: true })
|
||||
liftCount: number;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
heatingSystem: boolean;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
coolingSystem: boolean;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
hotWaterSystem: boolean;
|
||||
|
||||
@Field(() => Int)
|
||||
@Prop({ required: true })
|
||||
blockServiceManCount: number;
|
||||
|
||||
@Field(() => Int)
|
||||
@Prop({ required: true })
|
||||
securityServiceManCount: number;
|
||||
|
||||
@Field(() => Int)
|
||||
@Prop({ required: true })
|
||||
garageCount: number;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@Prop({ required: false })
|
||||
managementRoomId?: string;
|
||||
|
||||
}
|
||||
|
||||
@ObjectType()
|
||||
@Schema({ timestamps: true })
|
||||
export class Build extends CreatedBase {
|
||||
|
||||
@Field()
|
||||
readonly _id: string;
|
||||
|
||||
@Field(() => BuildTypes)
|
||||
@Prop({ type: Types.ObjectId, ref: BuildTypes.name, required: true })
|
||||
buildType: Types.ObjectId;
|
||||
|
||||
@Field(() => BuildInfo, { nullable: true })
|
||||
@Prop({ type: BuildInfo, required: true })
|
||||
info: BuildInfo;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@Prop({ type: String })
|
||||
site?: string;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@Prop({ type: String })
|
||||
address?: string;
|
||||
|
||||
@Field(() => [String], { nullable: true, defaultValue: [] })
|
||||
@Prop({ type: [String], default: [] })
|
||||
areas?: string[];
|
||||
|
||||
// collect String(ObjectID) to
|
||||
@Field(() => [String], { nullable: true, defaultValue: [] })
|
||||
@Prop({ type: [String], default: [] })
|
||||
ibans?: string[];
|
||||
|
||||
@Field(() => [BuildResponsible], { nullable: true, defaultValue: [] })
|
||||
@Prop({ type: [BuildResponsible], default: [] })
|
||||
responsibles?: BuildResponsible[];
|
||||
|
||||
}
|
||||
|
||||
export type BuildIbanDocument = BuildIban & Document;
|
||||
export const BuildIbanSchema = SchemaFactory.createForClass(BuildIban);
|
||||
|
||||
export type BuildDocument = Build & Document;
|
||||
export const BuildSchema = SchemaFactory.createForClass(Build);
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
import { ObjectType, Field, ID } from '@nestjs/graphql';
|
||||
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
|
||||
import { Document, Types } from 'mongoose';
|
||||
import { Base } from '@/models/base.model';
|
||||
|
||||
@ObjectType()
|
||||
@Schema({ timestamps: true })
|
||||
export class Company extends Base {
|
||||
|
||||
@Field(() => ID)
|
||||
readonly _id: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
formal_name: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
company_type: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
commercial_type: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
tax_no: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
public_name: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true })
|
||||
company_tag: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true, default: 'TR' })
|
||||
default_lang_type: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true, default: 'TL' })
|
||||
default_money_type: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true, default: false })
|
||||
is_commercial: boolean;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: true, default: false })
|
||||
is_blacklist: boolean;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: false })
|
||||
parent_id: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: false })
|
||||
workplace_no: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: false })
|
||||
official_address: string;
|
||||
|
||||
@Field()
|
||||
@Prop({ required: false })
|
||||
top_responsible_company: string;
|
||||
|
||||
}
|
||||
|
||||
export type CompanyDocument = Company & Document;
|
||||
export const CompanySchema = SchemaFactory.createForClass(Company);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue