diff --git a/src/api/property/dto/create-property.input.ts b/src/api/property/dto/create-property.input.ts deleted file mode 100644 index 197fa87..0000000 --- a/src/api/property/dto/create-property.input.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { Field, InputType, Int } from '@nestjs/graphql'; -import { IsNotEmpty, IsOptional } from 'class-validator'; -import { PROPERTY_TYPE } from '../entities/property.entity'; -import { FixedCostInput } from './fixed-cost.input'; -import { PropertyOwnerInput } from './property-owner.input'; -import { PropertyServiceProviderInput } from './property-service-provider.input'; - -@InputType() -export class CreatePropertyInput { - @Field(() => String, { description: 'Property name' }) - @IsNotEmpty() - name: string; - - @Field(() => String, { nullable: true }) - @IsOptional() - address?: string; - - @Field(() => Int, { nullable: true }) - @IsOptional() - numberOfUnits?: number; - - @Field(() => Int, { nullable: true }) - @IsOptional() - defaultUnitRentAmount?: number; - - @Field(() => PROPERTY_TYPE, { nullable: true }) - @IsOptional() - type?: string; - - @Field(() => [String], { nullable: true }) - @IsOptional() - photos?: string[]; - - @Field(() => [PropertyOwnerInput], { nullable: true }) - @IsOptional() - owners?: PropertyOwnerInput[]; - - @Field(() => [String], { nullable: true }) - @IsOptional() - managerIds?: string[]; - - @Field(() => [PropertyServiceProviderInput], { nullable: true }) - @IsOptional() - serviceProviders?: PropertyServiceProviderInput[]; - - @Field(() => [String], { nullable: true }) - @IsOptional() - variableCosts?: string[]; - - @Field(() => [FixedCostInput], { nullable: true }) - @IsOptional() - fixedCosts?: FixedCostInput[]; - - @Field(() => [String], { nullable: true }) - @IsOptional() - tags?: string[]; -} diff --git a/src/api/property/dto/fixed-cost.input.ts b/src/api/property/dto/fixed-cost.input.ts deleted file mode 100644 index 1e879a3..0000000 --- a/src/api/property/dto/fixed-cost.input.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Field, InputType, Int } from '@nestjs/graphql'; -import { IsNotEmpty } from 'class-validator'; - -@InputType() -export class FixedCostInput { - @Field(() => String) - @IsNotEmpty() - name: string; - - @Field(() => Int) - @IsNotEmpty() - amount: number; - - @Field(() => String) - @IsNotEmpty() - note: string; -} diff --git a/src/api/property/dto/property-list.input.ts b/src/api/property/dto/property-list.input.ts deleted file mode 100644 index 1f585f9..0000000 --- a/src/api/property/dto/property-list.input.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { CommonPaginationDto } from '@/shared/dto/CommonPaginationDto'; -import { InputType } from '@nestjs/graphql'; - -@InputType() -export class PropertyListQueryInput extends CommonPaginationDto {} diff --git a/src/api/property/dto/property-owner.input.ts b/src/api/property/dto/property-owner.input.ts deleted file mode 100644 index 707b561..0000000 --- a/src/api/property/dto/property-owner.input.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Field, InputType } from '@nestjs/graphql'; -import { IsNotEmpty } from 'class-validator'; - -@InputType() -export class PropertyOwnerInput { - @Field(() => String) - @IsNotEmpty() - public ownerUID?: string; - - @Field(() => Number) - @IsNotEmpty() - public ownershipPercentage?: number; -} diff --git a/src/api/property/dto/property-service-provider.input.ts b/src/api/property/dto/property-service-provider.input.ts deleted file mode 100644 index 9d5bc6c..0000000 --- a/src/api/property/dto/property-service-provider.input.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Field, InputType } from '@nestjs/graphql'; -import { IsNotEmpty, IsOptional } from 'class-validator'; -import { SERVICE_PROVIDER_TYPE } from '../entities/service-provider.entity'; - -@InputType() -export class PropertyServiceProviderInput { - @Field(() => String) - @IsNotEmpty() - name: string; - - @Field(() => SERVICE_PROVIDER_TYPE, { nullable: true }) - @IsOptional() - type?: SERVICE_PROVIDER_TYPE; - - @Field(() => String, { nullable: true }) - @IsOptional() - note?: string; -} diff --git a/src/api/property/dto/update-property.input.ts b/src/api/property/dto/update-property.input.ts deleted file mode 100644 index 908436f..0000000 --- a/src/api/property/dto/update-property.input.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Field, InputType, PartialType } from '@nestjs/graphql'; -import { IsNotEmpty } from 'class-validator'; -import { CreatePropertyInput } from './create-property.input'; - -@InputType() -export class UpdatePropertyInput extends PartialType(CreatePropertyInput) { - @Field(() => String) - @IsNotEmpty() - id: string; -} diff --git a/src/api/property/entities/fixed-cost.entity.ts b/src/api/property/entities/fixed-cost.entity.ts deleted file mode 100644 index 5c966cf..0000000 --- a/src/api/property/entities/fixed-cost.entity.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Field, Int, ObjectType } from '@nestjs/graphql'; -import { Prop, Schema } from '@nestjs/mongoose'; - -@ObjectType() -@Schema({ timestamps: true }) -export class FixedCost { - @Prop() - @Field(() => String) - name: string; - - @Prop() - @Field(() => Int) - amount: number; - - @Prop() - @Field(() => String) - note: string; -} diff --git a/src/api/property/entities/property-owner.entity.ts b/src/api/property/entities/property-owner.entity.ts deleted file mode 100644 index 6bccbe5..0000000 --- a/src/api/property/entities/property-owner.entity.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { User } from '@/api/users/entities/user.entity'; -import { Field, Int, ObjectType } from '@nestjs/graphql'; -import { Prop, Schema } from '@nestjs/mongoose'; -import { Schema as MongooseSchema } from 'mongoose'; - -@ObjectType() -@Schema({ timestamps: true }) -export class PropertyOwner { - @Prop({ type: MongooseSchema.Types.ObjectId, ref: 'User' }) - @Field(() => User) - public user?: User; - - @Prop() - @Field(() => Int) - public ownershipPercentage?: number; -} diff --git a/src/api/property/entities/property.entity.ts b/src/api/property/entities/property.entity.ts deleted file mode 100644 index 578a973..0000000 --- a/src/api/property/entities/property.entity.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { User } from '@/api/users/entities/user.entity'; -import { Paginated } from '@/shared/object-types/paginationObject'; -import { Field, ID, Int, ObjectType, registerEnumType } from '@nestjs/graphql'; -import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; -import { HydratedDocument } from 'mongoose'; -import { FixedCost } from './fixed-cost.entity'; -import { PropertyOwner } from './property-owner.entity'; -import { PropertyServiceProvider } from './service-provider.entity'; -import { Schema as MongooseSchema } from 'mongoose'; - -export enum PROPERTY_TYPE { - APARTMENT = 'APARTMENT', - HOUSE = 'HOUSE', - COMMERCIAL = 'COMMERCIAL', - INDUSTRIAL = 'INDUSTRIAL', - OFFICE = 'OFFICE', -} - -registerEnumType(PROPERTY_TYPE, { - name: 'PROPERTY_TYPE', -}); - -@ObjectType() -@Schema({ timestamps: true }) -export class Property { - @Field(() => ID) - _id?: string; - - @Prop() - @Field(() => String, { description: 'Property name' }) - name: string; - - @Prop() - @Field(() => String, { nullable: true }) - address?: string; - - @Prop() - @Field(() => Int, { nullable: true }) - numberOfUnits?: number; - - @Prop() - @Field(() => Int, { nullable: true }) - defaultUnitRentAmount?: number; - - @Prop() - @Field(() => PROPERTY_TYPE, { nullable: true }) - type?: string; - - @Prop() - @Field(() => [String], { nullable: true }) - photos?: string[]; - - @Prop() - @Field(() => [PropertyOwner], { nullable: true }) - owners?: PropertyOwner[]; - - @Prop({ type: [MongooseSchema.Types.ObjectId], ref: 'User' }) - @Field(() => [User], { nullable: true }) - managers?: User[]; - - @Prop() - @Field(() => [PropertyServiceProvider], { nullable: true }) - serviceProviders?: PropertyServiceProvider[]; - - @Prop() - @Field(() => [String], { nullable: true }) - variableCosts?: string[]; - - @Prop() - @Field(() => [FixedCost], { nullable: true }) - fixedCosts?: FixedCost[]; - - @Field(() => Date) - createdAt?: Date; - - @Field(() => Date) - updatedAt?: Date; - - @Field(() => [String], { nullable: true }) - @Prop() - tags: string[]; -} - -export type PropertyDocument = HydratedDocument; -export const PropertySchema = SchemaFactory.createForClass(Property); - -@ObjectType() -export class PropertyPagination extends Paginated(Property) {} diff --git a/src/api/property/entities/service-provider.entity.ts b/src/api/property/entities/service-provider.entity.ts deleted file mode 100644 index e7a9714..0000000 --- a/src/api/property/entities/service-provider.entity.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Field, ObjectType, registerEnumType } from '@nestjs/graphql'; -import { Prop, Schema } from '@nestjs/mongoose'; - -export enum SERVICE_PROVIDER_TYPE { - SECURITY = 'SECURITY', - CLEANING = 'CLEANING', - MAINTENANCE = 'MAINTENANCE', - OTHER = 'OTHER', -} - -registerEnumType(SERVICE_PROVIDER_TYPE, { - name: 'SERVICE_PROVIDER_TYPE', -}); - -@ObjectType() -@Schema({ timestamps: true }) -export class PropertyServiceProvider { - @Prop() - @Field(() => String) - name: string; - - @Prop() - @Field(() => SERVICE_PROVIDER_TYPE, { nullable: true }) - type?: SERVICE_PROVIDER_TYPE; - - @Prop() - @Field(() => String, { nullable: true }) - note?: string; -} diff --git a/src/api/property/property.module.ts b/src/api/property/property.module.ts deleted file mode 100644 index 09a8a5e..0000000 --- a/src/api/property/property.module.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Module } from '@nestjs/common'; -import { PropertyService } from './property.service'; -import { PropertyResolver } from './property.resolver'; -import { MongooseModule } from '@nestjs/mongoose'; -import { Property, PropertySchema } from './entities/property.entity'; -import { TagModule } from '../tag/tag.module'; - -@Module({ - imports: [ - MongooseModule.forFeature([ - { - name: Property.name, - schema: PropertySchema, - }, - ]), - TagModule, - ], - providers: [PropertyResolver, PropertyService], -}) -export class PropertyModule {} diff --git a/src/api/property/property.resolver.ts b/src/api/property/property.resolver.ts deleted file mode 100644 index 6a7410d..0000000 --- a/src/api/property/property.resolver.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { Resolver, Query, Mutation, Args, Int, Info } from '@nestjs/graphql'; -import { PropertyService } from './property.service'; -import { Property, PropertyPagination } from './entities/property.entity'; -import { CreatePropertyInput } from './dto/create-property.input'; -import { UpdatePropertyInput } from './dto/update-property.input'; -import { PropertyListQueryInput } from './dto/property-list.input'; -import getGqlFields from '@/shared/utils/get-gql-fields'; -import { CommonMatchInput, MatchOperator } from '@/shared/dto/CommonFindOneDto'; -import { ForbiddenException } from '@nestjs/common'; - -@Resolver(() => Property) -export class PropertyResolver { - constructor(private readonly propertyService: PropertyService) {} - - @Query(() => PropertyPagination, { name: 'properties', nullable: true }) - async findAll( - @Args('input', { nullable: true }) input: PropertyListQueryInput, - @Info() info: any, - ) { - const fields = getGqlFields(info, 'nodes'); - return this.propertyService.findAll(input, fields); - } - - @Query(() => Property, { name: 'property', nullable: true }) - findOne(@Args('input') input: CommonMatchInput, @Info() info: any) { - const fields = getGqlFields(info); - return this.propertyService.findOne( - { - [input.key]: { [`$${input.operator}`]: input.value }, - }, - fields, - ); - } - - @Mutation(() => Property, { nullable: true }) - async createProperty( - @Args('input') input: CreatePropertyInput, - @Info() info: any, - ) { - try { - const fields = getGqlFields(info); - const property = await this.propertyService.create(input); - return this.propertyService.findOne({ _id: property._id }, fields); - } catch (error) { - throw new ForbiddenException(error.message); - } - } - - @Mutation(() => Property) - async updateProperty( - @Args('input') input: UpdatePropertyInput, - @Info() info: any, - ) { - try { - const fields = getGqlFields(info); - await this.propertyService.update({ _id: input.id }, input); - return this.propertyService.findOne({ _id: input.id }, fields); - } catch (error) { - throw new ForbiddenException(error.message); - } - } - - @Mutation(() => Boolean) - async removeProperty(@Args('input') input: CommonMatchInput) { - try { - const res = await this.propertyService.remove({ - [input.key]: { [`$${input.operator}`]: input.value }, - }); - return res.deletedCount > 0; - } catch (error) { - throw new ForbiddenException(error.message); - } - } -} diff --git a/src/api/property/property.service.ts b/src/api/property/property.service.ts deleted file mode 100644 index 13b9434..0000000 --- a/src/api/property/property.service.ts +++ /dev/null @@ -1,145 +0,0 @@ -import { AppPaginationResponse } from '@/shared/contracts/app-pagination-response'; -import { SortType } from '@/shared/dto/CommonPaginationDto'; -import { ForbiddenException, Injectable } from '@nestjs/common'; -import { InjectModel } from '@nestjs/mongoose'; -import { FilterQuery, Model } from 'mongoose'; -import { TagService } from '../tag/tag.service'; -import { CreatePropertyInput } from './dto/create-property.input'; -import { PropertyListQueryInput } from './dto/property-list.input'; -import { UpdatePropertyInput } from './dto/update-property.input'; -import { Property, PropertyDocument } from './entities/property.entity'; - -@Injectable() -export class PropertyService { - constructor( - @InjectModel(Property.name) private propertyModel: Model, - private readonly tagService: TagService, - ) {} - - /** - * Create a property - * @param input CreatePropertyInput - * @returns - */ - async create(input: CreatePropertyInput) { - if (input.owners) { - input.owners = input.owners.map((owner) => { - return { - ownershipPercentage: owner.ownershipPercentage, - user: owner.ownerUID, - }; - }); - } - - return this.propertyModel.create({ - ...input, - managers: input.managerIds, - }); - } - - /** - * Create many properties - * @param input CreatePropertyInput[] - * @returns - */ - async createMany(input: CreatePropertyInput[]) { - return this.propertyModel.insertMany(input); - } - - async findAll(input: PropertyListQueryInput, fields: string[] = []) { - const { page = 1, limit = 10 } = input; - const where = { - [input?.where?.key]: { - [`$${input?.where?.operator}`]: input?.where?.value, - }, - }; - - const cursor = this.propertyModel.find(where); - - if (fields.includes('owners')) { - cursor.populate({ - path: 'owners.user', - model: 'User', - }); - } - - if (fields.includes('managers')) { - cursor.populate({ - path: 'managers', - }); - } - - const count = await this.propertyModel.countDocuments(where); - const skip = (page - 1) * limit; - const data = await cursor - .sort({ [input?.sortBy]: input?.sort == SortType.DESC ? -1 : 1 }) - .skip(skip) - .limit(limit); - - return new AppPaginationResponse(data, { - currentPage: page, - hasNextPage: page * limit < count, - totalCount: count, - totalPages: Math.ceil(count / limit), - }); - } - - /** - * Find a property - * @param filter FilterQuery - * @returns - */ - async findOne(filter: FilterQuery, fields: string[] = []) { - const cursor = this.propertyModel.findOne({ ...filter }); - - if (fields.includes('owners')) { - cursor.populate({ - path: 'owners.user', - model: 'User', - }); - } - - if (fields.includes('managers')) { - cursor.populate({ - path: 'managers', - }); - } - - const data = await cursor; - return data; - } - - /** - * Update a property - * @param filter FilterQuery - * @param input - * @returns - */ - async update( - filter: FilterQuery, - input: UpdatePropertyInput, - ) { - if (input.owners) { - input.owners = input.owners.map((owner) => { - return { - ownershipPercentage: owner.ownershipPercentage, - user: owner.ownerUID, - }; - }); - } - - return this.propertyModel.updateOne(filter, { - ...input, - managers: input.managerIds, - }); - } - - /** - * Remove a property - * @param filter FilterQuery - * @returns - */ - async remove(filter: FilterQuery) { - return this.propertyModel.deleteOne(filter); - } -} diff --git a/src/api/tag/dto/create-tag.input.ts b/src/api/tag/dto/create-tag.input.ts deleted file mode 100644 index 034d8d6..0000000 --- a/src/api/tag/dto/create-tag.input.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Field, InputType } from '@nestjs/graphql'; -import { IsNotEmpty, IsOptional } from 'class-validator'; - -@InputType() -export class CreateTagInput { - @Field(() => String) - @IsNotEmpty() - name: string; - - @Field(() => String, { nullable: true }) - @IsOptional() - description: string; - - @Field(() => String, { nullable: true }) - @IsOptional() - type: string; -} diff --git a/src/api/tag/dto/reference-tag.input.ts b/src/api/tag/dto/reference-tag.input.ts deleted file mode 100644 index 619df38..0000000 --- a/src/api/tag/dto/reference-tag.input.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Field, InputType } from '@nestjs/graphql'; - -@InputType() -export class TagReferenceInput { - @Field(() => String) - referenceId: string; - - @Field(() => String) - name: string; - - @Field(() => String, { nullable: true }) - description: string; - - @Field(() => String, { nullable: true }) - type: string; -} diff --git a/src/api/tag/dto/tag-list.input.ts b/src/api/tag/dto/tag-list.input.ts deleted file mode 100644 index aa823af..0000000 --- a/src/api/tag/dto/tag-list.input.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { CommonPaginationDto } from '@/shared/dto/CommonPaginationDto'; -import { InputType } from '@nestjs/graphql'; - -@InputType() -export class TagListQueryInput extends CommonPaginationDto {} diff --git a/src/api/tag/dto/update-tag.input.ts b/src/api/tag/dto/update-tag.input.ts deleted file mode 100644 index 8979653..0000000 --- a/src/api/tag/dto/update-tag.input.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Field, InputType, PartialType } from '@nestjs/graphql'; -import { IsNotEmpty } from 'class-validator'; -import { CreateTagInput } from './create-tag.input'; - -@InputType() -export class UpdateTagInput extends PartialType(CreateTagInput) { - @Field(() => String) - @IsNotEmpty() - id: string; -} diff --git a/src/api/tag/entities/tag-reference.entity.ts b/src/api/tag/entities/tag-reference.entity.ts deleted file mode 100644 index a2f0467..0000000 --- a/src/api/tag/entities/tag-reference.entity.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Field, ObjectType } from '@nestjs/graphql'; -import { Prop } from '@nestjs/mongoose'; -import { HydratedDocument } from 'mongoose'; - -@ObjectType() -export class TagReference { - @Field(() => String) - @Prop() - referenceId: string; - - @Prop() - @Field(() => String) - name: string; - - @Prop() - @Field(() => String, { nullable: true }) - description: string; - - @Prop() - @Field(() => String, { nullable: true }) - type: string; -} - -export type TagReferenceDocument = HydratedDocument; diff --git a/src/api/tag/entities/tag.entity.ts b/src/api/tag/entities/tag.entity.ts deleted file mode 100644 index 6b057c9..0000000 --- a/src/api/tag/entities/tag.entity.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Paginated } from '@/shared/object-types/paginationObject'; -import { Field, ID, ObjectType } from '@nestjs/graphql'; -import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; -import { HydratedDocument } from 'mongoose'; - -@ObjectType() -@Schema({ timestamps: true }) -export class Tag { - @Field(() => ID) - _id: string; - - @Field(() => String) - @Prop() - name: string; - - @Field(() => String, { nullable: true }) - @Prop() - description: string; - - @Field(() => String, { nullable: true }) - @Prop() - type: string; - - @Field(() => Date, { nullable: true }) - createdAt: Date; - - @Field(() => Date, { nullable: true }) - updatedAt: Date; -} - -export type TagDocument = HydratedDocument; -export const TagSchema = SchemaFactory.createForClass(Tag); - -@ObjectType() -export class TagPagination extends Paginated(Tag) {} diff --git a/src/api/tag/tag.module.ts b/src/api/tag/tag.module.ts deleted file mode 100644 index dd1d16d..0000000 --- a/src/api/tag/tag.module.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TagService } from './tag.service'; -import { TagResolver } from './tag.resolver'; -import { MongooseModule } from '@nestjs/mongoose'; -import { TagSchema } from './entities/tag.entity'; - -@Module({ - imports: [MongooseModule.forFeature([{ name: 'Tag', schema: TagSchema }])], - providers: [TagResolver, TagService], - exports: [TagService], -}) -export class TagModule {} diff --git a/src/api/tag/tag.resolver.ts b/src/api/tag/tag.resolver.ts deleted file mode 100644 index 5cc81b6..0000000 --- a/src/api/tag/tag.resolver.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Args, Mutation, Query, Resolver } from '@nestjs/graphql'; -import { CreateTagInput } from './dto/create-tag.input'; -import { TagListQueryInput } from './dto/tag-list.input'; -import { UpdateTagInput } from './dto/update-tag.input'; -import { Tag, TagPagination } from './entities/tag.entity'; -import { TagService } from './tag.service'; - -@Resolver(() => Tag) -export class TagResolver { - constructor(private readonly tagService: TagService) {} - - @Mutation(() => Tag) - createTag(@Args('input') createTagInput: CreateTagInput) { - return this.tagService.create(createTagInput); - } - - @Query(() => TagPagination, { name: 'tags', nullable: true }) - findAll(@Args('input') input: TagListQueryInput) { - return this.tagService.findAll(input); - } - - @Query(() => Tag, { name: 'tag', nullable: true }) - findOne(@Args('id', { type: () => String }) id: string) { - return this.tagService.findOne({ _id: id }); - } - - @Mutation(() => Tag) - async updateTag(@Args('input') input: UpdateTagInput) { - const data = await this.tagService.update({ _id: input.id }, input); - return data; - } - - @Mutation(() => Boolean, { nullable: true }) - removeTag(@Args('id', { type: () => String }) id: string) { - return this.tagService.remove({ _id: id }); - } -} diff --git a/src/api/tag/tag.service.ts b/src/api/tag/tag.service.ts deleted file mode 100644 index fd82564..0000000 --- a/src/api/tag/tag.service.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { AppPaginationResponse } from '@/shared/contracts/app-pagination-response'; -import { SortType } from '@/shared/dto/CommonPaginationDto'; -import { Injectable } from '@nestjs/common'; -import { InjectModel } from '@nestjs/mongoose'; -import { ForbiddenError } from 'apollo-server-express'; -import { FilterQuery, Model } from 'mongoose'; -import { CreateTagInput } from './dto/create-tag.input'; -import { TagListQueryInput } from './dto/tag-list.input'; -import { UpdateTagInput } from './dto/update-tag.input'; -import { Tag, TagDocument } from './entities/tag.entity'; - -@Injectable() -export class TagService { - constructor(@InjectModel(Tag.name) private tagModel: Model) {} - - create(createTagInput: CreateTagInput) { - return this.tagModel.create(createTagInput); - } - - async findAll(input: TagListQueryInput) { - const { page = 1, limit = 10 } = input; - const where = { - [input?.where?.key]: { - [`$${input?.where?.operator}`]: input?.where?.value, - }, - }; - - const cursor = this.tagModel.find(where); - const count = await this.tagModel.countDocuments(where); - const skip = (page - 1) * limit; - const data = await cursor - .sort({ [input?.sortBy]: input?.sort == SortType.DESC ? -1 : 1 }) - .skip(skip) - .limit(limit); - - return new AppPaginationResponse(data, { - totalCount: count, - currentPage: page, - hasNextPage: page * limit < count, - totalPages: Math.ceil(count / limit), - }); - } - - /** - * Find one tag - * @param filter - * @returns - */ - findOne(filter: FilterQuery) { - return this.tagModel.findOne(filter); - } - - findManyByIds(ids: string[]) { - return this.tagModel.find({ _id: { $in: ids } }); - } - - async update(filter: FilterQuery, input: UpdateTagInput) { - try { - await this.tagModel.updateOne(filter, input); - return this.findOne(filter); - } catch (err) { - throw new ForbiddenError(err.message); - } - } - - async remove(filter: FilterQuery) { - try { - const res = await this.tagModel.deleteOne(filter); - return res.deletedCount > 0; - } catch (err) { - return false; - } - } -} diff --git a/src/api/users/dto/create-user.input.ts b/src/api/users/dto/create-user.input.ts index ac034bb..25c61f8 100644 --- a/src/api/users/dto/create-user.input.ts +++ b/src/api/users/dto/create-user.input.ts @@ -1,43 +1,9 @@ import { Field, InputType } from '@nestjs/graphql'; -import { IsEmail, IsNotEmpty, IsOptional } from 'class-validator'; -import { USER_DOMAIN } from '../entities/user.entity'; - -@InputType() -export class UserAdditionalDocumentDTO { - @Field(() => String, { nullable: true }) - public name?: string; - - @Field(() => String, { nullable: true }) - public note?: string; - - @Field(() => String, { nullable: true }) - public file?: string; -} +import { IsOptional } from 'class-validator'; @InputType() export class CreateUserDTO { @Field(() => String) @IsOptional() name: string; - - @Field(() => String) - @IsEmail() - @IsNotEmpty() - email: string; - - @Field(() => String, { nullable: true }) - @IsOptional() - avatar: string; - - @Field(() => [String], { nullable: true }) - @IsOptional() - contactNumbers: string[]; - - @Field(() => [UserAdditionalDocumentDTO], { nullable: true }) - @IsOptional() - additionalDocuments: UserAdditionalDocumentDTO[]; - - @Field(() => USER_DOMAIN, { nullable: true }) - @IsOptional() - domain: USER_DOMAIN; } diff --git a/src/api/users/entities/user-documents.entity.ts b/src/api/users/entities/user-documents.entity.ts deleted file mode 100644 index 6760dfa..0000000 --- a/src/api/users/entities/user-documents.entity.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Field, ObjectType } from '@nestjs/graphql'; -import { Prop, Schema } from '@nestjs/mongoose'; - -@ObjectType() -@Schema({ timestamps: true }) -export class UserAdditionalDocument { - @Prop() - @Field(() => String, { nullable: true }) - public name?: string; - - @Prop() - @Field(() => String, { nullable: true }) - public note?: string; - - @Prop() - @Field(() => String, { nullable: true }) - public file?: string; -} diff --git a/src/api/users/entities/user-payment-information.dto.ts b/src/api/users/entities/user-payment-information.dto.ts deleted file mode 100644 index d448760..0000000 --- a/src/api/users/entities/user-payment-information.dto.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Field, ObjectType } from '@nestjs/graphql'; -import { Prop, Schema } from '@nestjs/mongoose'; - -@Schema({ timestamps: true }) -@ObjectType() -export class UserPaymentInformation { - @Prop() - @Field(() => String, { nullable: true }) - public type?: 'MFS' | 'BANK'; - - @Prop() - @Field(() => String, { nullable: true }) - public providerName?: string; -} diff --git a/src/api/users/entities/user.entity.ts b/src/api/users/entities/user.entity.ts index 1c93fd6..5084705 100644 --- a/src/api/users/entities/user.entity.ts +++ b/src/api/users/entities/user.entity.ts @@ -1,59 +1,19 @@ -import { Paginated } from '@/shared/object-types/paginationObject'; -import { ObjectType, Field, ID, registerEnumType } from '@nestjs/graphql'; -import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; -import { HydratedDocument } from 'mongoose'; -import { UserAdditionalDocument } from './user-documents.entity'; -import { UserPaymentInformation } from './user-payment-information.dto'; - -export enum USER_DOMAIN { - OWNER = 'OWNER', - PROPERTY_OWNER = 'PROPERTY_OWNER', - UNIT_OWNER = 'UNIT_OWNER', - MANAGER = 'MANAGER', - SECURITY_GUARD = 'SECURITY_GUARD', -} - -registerEnumType(USER_DOMAIN, { - name: 'USER_DOMAIN', -}); +import { Field, ID, ObjectType } from '@nestjs/graphql'; @ObjectType() -@Schema({ timestamps: true, collection: 'users' }) export class User { @Field(() => ID) _id?: string; - @Prop() @Field(() => String, { nullable: true }) public name?: string; - @Prop() @Field(() => [String], { nullable: true }) public contactNumbers?: string[]; - @Prop({ required: false }) @Field(() => String, { nullable: true }) public avatar?: string; - @Prop({ required: true }) @Field(() => String, { nullable: false }) public email: string; - - @Prop() - @Field(() => [UserAdditionalDocument], { nullable: true }) - public additionalDocuments?: UserAdditionalDocument[]; - - @Prop() - @Field(() => [UserPaymentInformation], { nullable: true }) - public paymentInformations?: UserPaymentInformation; - - @Prop() - @Field(() => USER_DOMAIN, { nullable: true }) - public domain?: USER_DOMAIN; } - -export type UserDocument = HydratedDocument; -export const UserSchema = SchemaFactory.createForClass(User); - -@ObjectType() -export class UserPagination extends Paginated(User) {} diff --git a/src/api/users/users.module.ts b/src/api/users/users.module.ts index 5e558e6..f12b2a0 100644 --- a/src/api/users/users.module.ts +++ b/src/api/users/users.module.ts @@ -1,18 +1,8 @@ import { Module } from '@nestjs/common'; -import { UsersService } from './users.service'; import { UsersResolver } from './users.resolver'; -import { MongooseModule } from '@nestjs/mongoose'; -import { User, UserSchema } from './entities/user.entity'; @Module({ - imports: [ - MongooseModule.forFeature([ - { - name: User.name, - schema: UserSchema, - }, - ]), - ], - providers: [UsersResolver, UsersService], + imports: [], + providers: [UsersResolver], }) export class UsersModule {} diff --git a/src/api/users/users.resolver.ts b/src/api/users/users.resolver.ts index acca25d..f8367ea 100644 --- a/src/api/users/users.resolver.ts +++ b/src/api/users/users.resolver.ts @@ -1,52 +1,10 @@ -import { CommonMatchInput } from '@/shared/dto/CommonFindOneDto'; -import { ForbiddenException } from '@nestjs/common'; -import { Args, Mutation, Query, Resolver } from '@nestjs/graphql'; -import { CreateUserDTO } from './dto/create-user.input'; -import { UpdateUserInput } from './dto/update-user.input'; +import { Args, Query, Resolver } from '@nestjs/graphql'; import { UserListQueryDto } from './dto/user-list-query.dto'; -import { User, UserPagination } from './entities/user.entity'; -import { UsersService } from './users.service'; -@Resolver(() => User) +@Resolver() export class UsersResolver { - constructor(private readonly usersService: UsersService) {} - - @Mutation(() => User, { nullable: true }) - createUser(@Args('input') input: CreateUserDTO) { - return this.usersService.createUser(input); - } - - @Query(() => UserPagination, { name: 'users', nullable: true }) + @Query(() => String, { name: 'users', nullable: true }) async findAll(@Args('input', { nullable: true }) input: UserListQueryDto) { - return this.usersService.findAll(input); - } - - @Query(() => User, { name: 'user', nullable: true }) - async findOne(@Args('input') input: CommonMatchInput) { - return this.usersService.findOne({ - [input.key]: { [`$${input.operator}`]: input.value }, - }); - } - - @Mutation(() => User, { nullable: true }) - async updateUser(@Args('input') input: UpdateUserInput) { - try { - await this.usersService.updateUser({ _id: input.id }, input); - return this.usersService.findOne({ _id: input.id }); - } catch (error) { - throw new ForbiddenException(error.message); - } - } - - @Mutation(() => Boolean, { nullable: true }) - async removeUser(@Args('input') input: CommonMatchInput) { - try { - const res = await this.usersService.deleteUser({ - [input.key]: { [`$${input.operator}`]: input.value }, - }); - return res.deletedCount > 0; - } catch (error) { - throw new ForbiddenException(error.message); - } + return 'This action returns all users'; } } diff --git a/src/api/users/users.service.ts b/src/api/users/users.service.ts deleted file mode 100644 index a4c33e9..0000000 --- a/src/api/users/users.service.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { AppPaginationResponse } from '@/shared/contracts/app-pagination-response'; -import { SortType } from '@/shared/dto/CommonPaginationDto'; -import { ForbiddenException, Injectable } from '@nestjs/common'; -import { InjectModel } from '@nestjs/mongoose'; -import { FilterQuery, Model } from 'mongoose'; -import { CreateUserDTO } from './dto/create-user.input'; -import { UpdateUserInput } from './dto/update-user.input'; -import { UserListQueryDto } from './dto/user-list-query.dto'; -import { User, UserDocument } from './entities/user.entity'; - -@Injectable() -export class UsersService { - constructor(@InjectModel(User.name) private userModel: Model) { - console.log('UserService created'); - } - - /** - * Find all users - * @param input UserListQueryDto - * @returns - */ - async findAll(input: UserListQueryDto) { - const { page = 1, limit = 10 } = input; - const where = { - [input?.where?.key]: { - [`$${input?.where?.operator}`]: input?.where?.value, - }, - }; - - const cursor = this.userModel.find(where); - const count = await this.userModel.countDocuments(where); - const skip = (page - 1) * limit; - const data = await cursor - .sort({ [input?.sortBy]: input?.sort == SortType.DESC ? -1 : 1 }) - .skip(skip) - .limit(limit); - - return new AppPaginationResponse(data, { - totalCount: count, - currentPage: page, - hasNextPage: page * limit < count, - totalPages: Math.ceil(count / limit), - }); - } - - /** - * Find a user - * @param filter - */ - async findOne(filter: FilterQuery) { - return this.userModel.findOne(filter); - } - - /** - * Create a new user - * @param body - */ - async createUser(body: CreateUserDTO) { - const user = await this.findOne({ - $and: [{ $or: [{ email: body.email }] }], - }); - - if (user) { - throw new ForbiddenException('User already exists'); - } - - return this.userModel.create({ - ...body, - // password: hashSync(body.password, 10), - }); - } - - /** - * Update a user - * @param filter - * @param body - */ - async updateUser(filter: FilterQuery, body: UpdateUserInput) { - return this.userModel.updateOne(filter, body); - } - - /** - * Delete a user - * @param filter - * @returns - */ - async deleteUser(filter: FilterQuery) { - return this.userModel.deleteOne(filter); - } - - /** - * Compare password - * @param user User - * @param password - * @returns - */ - // comparePassword(user: UserDocument, password: string): boolean { - // return compareSync(password, user.password); - // } -} diff --git a/src/app.module.ts b/src/app.module.ts index 276474c..f636a2a 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -7,9 +7,6 @@ import { AppService } from './app.service'; import { UsersModule } from './api/users/users.module'; import { MongooseModule } from '@nestjs/mongoose'; import { ConfigModule } from '@nestjs/config'; -import { PropertyModule } from './api/property/property.module'; -import { TagModule } from './api/tag/tag.module'; - @Module({ imports: [ // --------------------------------------------------------- @@ -31,8 +28,6 @@ import { TagModule } from './api/tag/tag.module'; // Application modules // --------------------------------------------------------- UsersModule, - PropertyModule, - TagModule, ], controllers: [AppController], providers: [AppService], diff --git a/src/schema.gql b/src/schema.gql index 7e6b5e7..a225427 100644 --- a/src/schema.gql +++ b/src/schema.gql @@ -2,131 +2,8 @@ # THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY) # ------------------------------------------------------ -type PagniationMeta { - totalCount: Float! - currentPage: Float! - hasNextPage: Boolean! - totalPages: Float! -} - -type UserAdditionalDocument { - name: String - note: String - file: String -} - -type UserPaymentInformation { - type: String - providerName: String -} - -type User { - _id: ID! - name: String - contactNumbers: [String!] - avatar: String - email: String! - additionalDocuments: [UserAdditionalDocument!] - paymentInformations: [UserPaymentInformation!] - domain: USER_DOMAIN -} - -enum USER_DOMAIN { - OWNER - PROPERTY_OWNER - UNIT_OWNER - MANAGER - SECURITY_GUARD -} - -type UserPagination { - nodes: [User!] - meta: PagniationMeta -} - -type Tag { - _id: ID! - name: String! - description: String - type: String - createdAt: DateTime - updatedAt: DateTime -} - -""" -A date-time string at UTC, such as 2019-12-03T09:54:33Z, compliant with the date-time format. -""" -scalar DateTime - -type TagPagination { - nodes: [Tag!] - meta: PagniationMeta -} - -type FixedCost { - name: String! - amount: Int! - note: String! -} - -type PropertyOwner { - user: User! - ownershipPercentage: Int! -} - -type PropertyServiceProvider { - name: String! - type: SERVICE_PROVIDER_TYPE - note: String -} - -enum SERVICE_PROVIDER_TYPE { - SECURITY - CLEANING - MAINTENANCE - OTHER -} - -type Property { - _id: ID! - - """Property name""" - name: String! - address: String - numberOfUnits: Int - defaultUnitRentAmount: Int - type: PROPERTY_TYPE - photos: [String!] - owners: [PropertyOwner!] - managers: [User!] - serviceProviders: [PropertyServiceProvider!] - variableCosts: [String!] - fixedCosts: [FixedCost!] - createdAt: DateTime! - updatedAt: DateTime! - tags: [String!] -} - -enum PROPERTY_TYPE { - APARTMENT - HOUSE - COMMERCIAL - INDUSTRIAL - OFFICE -} - -type PropertyPagination { - nodes: [Property!] - meta: PagniationMeta -} - type Query { - users(input: UserListQueryDto): UserPagination - user(input: CommonMatchInput!): User - properties(input: PropertyListQueryInput): PropertyPagination - property(input: CommonMatchInput!): Property - tags(input: TagListQueryInput!): TagPagination - tag(id: String!): Tag + users(input: UserListQueryDto): String } input UserListQueryDto { @@ -164,120 +41,4 @@ enum MatchOperator { startsWith endsWith regex -} - -input PropertyListQueryInput { - page: Int - limit: Int - sort: SortType - sortBy: String - where: CommonMatchInput -} - -input TagListQueryInput { - page: Int - limit: Int - sort: SortType - sortBy: String - where: CommonMatchInput -} - -type Mutation { - createUser(input: CreateUserDTO!): User - updateUser(input: UpdateUserInput!): User - removeUser(input: CommonMatchInput!): Boolean - createProperty(input: CreatePropertyInput!): Property - updateProperty(input: UpdatePropertyInput!): Property! - removeProperty(input: CommonMatchInput!): Boolean! - createTag(input: CreateTagInput!): Tag! - updateTag(input: UpdateTagInput!): Tag! - removeTag(id: String!): Boolean -} - -input CreateUserDTO { - name: String! - email: String! - avatar: String - contactNumbers: [String!] - additionalDocuments: [UserAdditionalDocumentDTO!] - domain: USER_DOMAIN -} - -input UserAdditionalDocumentDTO { - name: String - note: String - file: String -} - -input UpdateUserInput { - name: String - email: String - avatar: String - contactNumbers: [String!] - additionalDocuments: [UserAdditionalDocumentDTO!] - domain: USER_DOMAIN - id: String! -} - -input CreatePropertyInput { - """Property name""" - name: String! - address: String - numberOfUnits: Int - defaultUnitRentAmount: Int - type: PROPERTY_TYPE - photos: [String!] - owners: [PropertyOwnerInput!] - managerIds: [String!] - serviceProviders: [PropertyServiceProviderInput!] - variableCosts: [String!] - fixedCosts: [FixedCostInput!] - tags: [String!] -} - -input PropertyOwnerInput { - ownerUID: String! - ownershipPercentage: Float! -} - -input PropertyServiceProviderInput { - name: String! - type: SERVICE_PROVIDER_TYPE - note: String -} - -input FixedCostInput { - name: String! - amount: Int! - note: String! -} - -input UpdatePropertyInput { - """Property name""" - name: String - address: String - numberOfUnits: Int - defaultUnitRentAmount: Int - type: PROPERTY_TYPE - photos: [String!] - owners: [PropertyOwnerInput!] - managerIds: [String!] - serviceProviders: [PropertyServiceProviderInput!] - variableCosts: [String!] - fixedCosts: [FixedCostInput!] - tags: [String!] - id: String! -} - -input CreateTagInput { - name: String! - description: String - type: String -} - -input UpdateTagInput { - name: String - description: String - type: String - id: String! } \ No newline at end of file