//src/users/users.service.ts
import { Injectable, BadRequestException } from "@nestjs/common";
import { InjectModel } from "@nestjs/mongoose";
import { Model } from "mongoose";
import { plainToClass } from "class-transformer";
import { BaseService } from "../common/base/base.service";
import { IUser, User } from "./objects/user.schema";
import { EmailService } from "../email/email.service";
import {
HasPostCreate,
HasPreCreate,
HasPostUpdate,
HasPreUpdate,
} from "../common/base/pre.post.action";
import { EmailDto } from "../email/objects/email.dto";
import {
UserRegisteredEmailForSponsor,
UserRegisteredEmailForSme,
LoginCredentialEmail,
KycApprovedforSme,
KycApprovedforSponsor,
KycRejectedforSme,
KycRejectedforSponsor,
KycPendingEmail,
} from "./objects/user.registered.email";
import { JwtService } from "@nestjs/jwt";
import {
JWT_EXPIRY,
CRM_URL_HEADERS,
BIGCHAINDB_API_PATH,
} from "../common/constants/config";
import { EntityDetailsService } from "../entity-details/entity-details.service";
import {
CreateEntityDetailsDto,
EntityDetailsDto,
} from "../entity-details/objects/entity-details.dto";
import { IEntityDetails } from "../entity-details/objects/entity-details.schema";
import { UserDto, CreateUserDto } from "./objects/create-user.dto";
import { crmDto } from "./objects/userCrm.dto";
import {
USER_TYPES,
ACTIVITY_FEED_EVENTS_SPONSOR,
ACTIVITY_FEED_EVENTS_SME,
KYC_VERIFICATION_STATUS,
USER_STATUS,
SME,
INVESTOR,
BIGCHAINDB_TRANSACTION_TYPE,
ROLES_ACCESS_ACTION,
} from "../common/constants/enum";
import { SetFormattedId } from "../common/base/set.formattedId";
import { OtpService } from "../auth/otp/otp.service";
import * as request from "request-promise-native";
import * as cloneDeep from "lodash.clonedeep";
import { AnyFilesInterceptor } from "@nestjs/platform-express";
import { CanLoadVirtual } from "../common/interfaces/can.load.virtual";
import { IsBoolean } from "class-validator";
import { json } from "express";
import { IamUser } from "aws-sdk/clients/macie2";
import { IamUserArn } from "aws-sdk/clients/codedeploy";
import { CRM_URL_HEADERS_UPDATE } from "../common/constants/config";
import { CrmService } from "./crm/crm.service";
import { EmailNotificationService } from "./email-notification/email-notification.service";
import { result } from "lodash";
import { ActivityFeedService } from "../activity-feed/activity-feed.service";
import { UpdateBlogDTO } from "../blog/objects/blog.dto";
import { SmeActivityFeedService } from "../sme-activity-feed/sme-activity-feed.service";
import {
KYC_PENDING_STATUS_CHANGE_ERROR,
KYC_PENDING_STATUS_CHANGE_ERROR_WITH_ONBOARDING_FALSE,
KYC_APPROVED_STATUS_CHANGE_ERROR,
KYC_REJECTED_STATUS_CHANGE_ERROR,
USER_KYC_INCOMPLETE_STATUS_CHANGE_ERROR,
USER_CLOSED_STATUS_CHANGE_ERROR,
USER_IN_REVIEW_STATUS_CHANGE_ERROR,
USER_ACTIVE_STATUS_CHANGE_ERROR,
} from "../common/constants/string";
import { generateKeyPair } from "crypto";
import { BigchainDbService } from "../bigchain-db/bigchain-db.service";
import { type } from "os";
import { RolesService } from "../roles/roles.service";
export function delay(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
@Injectable()
export class UsersService extends BaseService<IUser>
implements
HasPreCreate,
HasPostCreate,
HasPreUpdate,
HasPostUpdate,
CanLoadVirtual {
constructor(
@InjectModel("User") private readonly userModel: Model<User>,
private emailService: EmailService,
private jwtService: JwtService,
private entityDetailsService: EntityDetailsService,
private otpService: OtpService,
private crmService: CrmService,
private emailnotificationService: EmailNotificationService,
private activityFeedService: ActivityFeedService,
private smeactivityFeedService: SmeActivityFeedService,
private bigchaindbService: BigchainDbService,
private rolesservice: RolesService
) {
super(userModel);
}
async doPostCreate(user: IUser): Promise<void> {
let update = { forcePasswordChange: true };
await this.edit(user.code, {
verification: update,
});
}
async doPostUpdate(idOrCode, model) {
/*
let update = { forcePasswordChange: true };
await this.edit(user.code, {
verification: update,
});
*/
let result = await this.emailnotificationService.edit(notify.code, {
isKycApproved: false,
isKycRejected: false,
isKycPending: true,
});
}
//src/users/objects/user.schema.ts
export const UserSchema: Schema = createModel("Users", {
verification: {
mobile: {
type: Boolean,
default: true,
},
email: {
type: Boolean,
default: true,
},
isProfileCompleted: {
type: Number,
enum: Object.values({ ...KYC_VERIFICATION_STATUS }),
default: KYC_VERIFICATION_STATUS.PENDING,
},
isOnboardingComplete: {
type: Boolean,
default: false,
},
forcePasswordChange: {
type: Boolean,
default: false,
},
}
});
//src/users/email-notification/email-notification.schema.ts
export const EmailNotificationSchema: Schema = createModel(
"EmailNotification",
{
isOnboardingInitiated: { type: Boolean, default: false },
isKycApproved: { type: Boolean, default: false },
isKycRejected: { type: Boolean, default: false },
isKycPending: { type: Boolean, default: false },
isDocumentsSubmitted: { type: Boolean, default: false },
project: {
isProjectCreated: { type: Boolean, default: false },
isProjectPending: { type: Boolean, default: false },
isProjectApproved: { type: Boolean, default: false },
isProjectRejected: { type: Boolean, default: false },
},
creator: { type: String },
}
);
// src/common/base/base.controller.ts
import {
Body,
Delete,
Get,
Post,
Put,
Request,
UseInterceptors,
NotFoundException,
Query,
} from "@nestjs/common";
import { AbstractControllerOptions } from "./base.interface";
import { AbstractClassTransformerPipe } from "../pipes/class-transformer.pipe";
import { plainToClass } from "class-transformer";
import { ApplicationExceptionInterceptor } from "../application.interceptor";
import {
IdOrCodeParser,
LastUpdatedTime,
RequestUser,
} from "../utils/controller.decorator";
import { BaseService } from "./base.service";
import { IEntity } from "./base.model";
import { success } from "./httpResponse.interface";
import { BASEROUTES, Status } from "../constants/enum";
import { createMongoSearchQuery } from "../utils/helper";
import {
normalizePaginateResult,
normalizePagination,
Paginate,
} from "../interfaces/pagination";
import * as dot from "dot-object";
export function abstractBaseControllerFactory<T>(
options?: AbstractControllerOptions<T>
): any {
const { DTO, CreateDTO, UpdateDTO, DisabledRoutes } = options;
const routeAvailability = (routeTag: number): void => {
if (DisabledRoutes && DisabledRoutes.includes(routeTag)) {
throw new NotFoundException();
}
};
@UseInterceptors(ApplicationExceptionInterceptor)
abstract class AbstractController {
protected _service: BaseService<IEntity>;
protected constructor(service: any) {
this._service = service;
}
@Put(":idOrCode")
public async update(
@IdOrCodeParser("idOrCode") idOrCode: string,
@LastUpdatedTime() lastUpdatedTime: number,
@Body(AbstractClassTransformerPipe(UpdateDTO)) updateDto,
@RequestUser() user
) {
if (user) {
updateDto.updatedBy = user.code;
}
routeAvailability(BASEROUTES.UPDATEONE);
let data = await this._service.edit(
idOrCode,
updateDto,
lastUpdatedTime,
user
);
data = plainToClass(DTO, data, { excludeExtraneousValues: true });
return success(data);
}
@Delete(":idOrCode")
public async delete(@IdOrCodeParser("idOrCode") idOrCode: string) {
routeAvailability(BASEROUTES.DETELEONE);
let data = await this._service.remove(idOrCode);
data = plainToClass(DTO, data, { excludeExtraneousValues: true });
return success(data);
}
}
return AbstractController;
}
//src/common/base/base.service.ts
import { NotFoundException } from "@nestjs/common";
import { Model } from "mongoose";
import * as moment from "moment";
import { APP_ENV, Status } from "../constants/enum";
import { NODE_ENV } from "../constants/config";
import { NOT_FOUND, NOT_SYNCED } from "../constants/string";
import { UniqueValidator } from "../validator/unique.validator";
import * as _ from "lodash";
import * as flatter from "flat";
import {
HasPreCreate,
HasPostCreate,
HasPreUpdate,
HasPostUpdate,
HasPreDelete,
HasPostDelete,
HasPreGetAll,
} from "./pre.post.action";
import { SetFormattedId, getFormatedId } from "./set.formattedId";
import { CanLoadVirtual } from "../interfaces/can.load.virtual";
import { Paginate } from "../interfaces/pagination";
import { User } from "src/users/objects/user.schema";
export abstract class BaseService<T> extends UniqueValidator {
private PreCreate = !!(<HasPreCreate>(<any>this)).doPreCreate
? <HasPreCreate>(<any>this)
: null;
private PreGetAll = !!(<HasPreGetAll>(<any>this)).doPreGetAll
? <HasPreGetAll>(<any>this)
: null;
private PostCreate = !!(<HasPostCreate>(<any>this)).doPostCreate
? <HasPostCreate>(<any>this)
: null;
private PreUpdate = !!(<HasPreUpdate>(<any>this)).doPreUpdate
? <HasPreUpdate>(<any>this)
: null;
private PostUpdate = !!(<HasPostUpdate>(<any>this)).doPostUpdate
? <HasPostUpdate>(<any>this)
: null;
private PreDelete = !!(<HasPreDelete>(<any>this)).doPreDelete
? <HasPreDelete>(<any>this)
: null;
private PostDelete = !!(<HasPostDelete>(<any>this)).doPostDelete
? <HasPostDelete>(<any>this)
: null;
private CanLoadVirtual = !!(<CanLoadVirtual>(<any>this)).getVirtualForItem
? <CanLoadVirtual>(<any>this)
: null;
private SetFormattedId = !!(<SetFormattedId>(<any>this)).getPrefixForId
? <SetFormattedId>(<any>this)
: null;
private readonly validVirtual = [];
protected constructor(baseModel: Model) {
// debugger;
super(baseModel);
this.setVirtual();
}
async edit(
idOrCode: string,
editDto: any,
lastUpdatedTime?: number,
user?: any
) {
debugger;
await this.validate(editDto, idOrCode);
let model = await this.findOne(idOrCode);
if (
NODE_ENV !== APP_ENV.development &&
!moment(model.updatedTime).isSame(moment(lastUpdatedTime))
) {
// throw new Error(NOT_SYNCED);
}
if (this.PreUpdate) {
debugger;
await this.PreUpdate.doPreUpdate(idOrCode, editDto, model, user);
}
editDto = flatter.flatten(editDto);
await this.baseModel.updateOne(
{
code: model.code,
},
{
$set: {
...editDto,
},
}
);
model = await this.findOne(idOrCode);
if (this.PostUpdate) {
debugger;
await this.PostUpdate.doPostUpdate(idOrCode, model, user);
}
return model;
}
}
编辑功能包含在base.service.ts中,如上所示。 链接到源代码:(https://gitlab.com/adh.ranjan/nestjs) 就像在调用了edit函数的postCreate方法中一样,我也想在postUpdate方法中调用edit函数。我面临的问题是执行将导致无限循环。我想在同一UserSchema中添加“ isKycPending”。一种解决方案可能是创建一个新的架构,如EmailNotificationSchema并调用emailnotificationService,如上所示。可能有什么解决方案?