chore: update user profile
This commit is contained in:
@@ -76,6 +76,15 @@ export const enum UserMessage {
|
||||
INVALID_EMAIL_TOKEN = "توکن ایمیل نامعتبر است",
|
||||
EXPIRED_EMAIL_TOKEN = "توکن ایمیل منقضی شده است",
|
||||
PHONE_EXIST = "شماره تلفن قبلا ثبت شده است",
|
||||
ADDRESS_REQUIRED = "آدرس نمیتواند خالی باشد",
|
||||
ADDRESS_SHOULD_BE_STRING = "آدرس باید یک رشته باشد",
|
||||
ADDRESS_LENGTH = "آدرس باید بین ۵ تا ۲۵۵ کاراکتر باشد",
|
||||
POSTAL_CODE_REQUIRED = "کد پستی نمیتواند خالی باشد",
|
||||
POSTAL_CODE_SHOULD_BE_STRING = "کد پستی باید یک رشته باشد",
|
||||
POSTAL_CODE_LENGTH = "کد پستی باید ۱۰ رقم باشد",
|
||||
CITY_REQUIRED = "شهر نمیتواند خالی باشد",
|
||||
CITY_NOT_FOUND = "شهر یافت نشد",
|
||||
CITY_SHOULD_BE_UUID = "شناسه شهر باید یک UUID باشد",
|
||||
}
|
||||
|
||||
export const enum CommonMessage {
|
||||
|
||||
@@ -310,34 +310,39 @@ export class InvoicesService {
|
||||
}
|
||||
|
||||
async cancelDiscount(invoiceId: string, userId: string) {
|
||||
// Find the invoice by ID and ensure it is in a PENDING status
|
||||
const invoice = await this.invoiceRepository.findOneBy({ id: invoiceId, status: InvoiceStatus.PENDING });
|
||||
if (!invoice) throw new BadRequestException(InvoiceMessage.NOT_FOUND_BY_ID);
|
||||
|
||||
// Find the usage discount associated with the user and invoice
|
||||
const usage = await this.usageDiscountRepository.findOne({
|
||||
where: {
|
||||
users: {
|
||||
id: userId,
|
||||
},
|
||||
users: { id: userId },
|
||||
discount: { invoice: { id: invoice.id } },
|
||||
},
|
||||
relations: {
|
||||
discount: true,
|
||||
users: true,
|
||||
},
|
||||
});
|
||||
|
||||
console.log(usage);
|
||||
if (!usage) throw new BadRequestException(DiscountMessage.NOT_FOUND);
|
||||
|
||||
// Find the discount associated with the usage
|
||||
const discount = await this.discountRepository.findOneBy({ id: usage.discount.id });
|
||||
if (!discount) throw new BadRequestException(DiscountMessage.NOT_FOUND);
|
||||
|
||||
// Calculate the discount amount to be removed from the invoice
|
||||
const discountAmount =
|
||||
discount.calculationType === "PERCENTAGE"
|
||||
? new Decimal(invoice.totalPrice).mul(discount.amount).div(100)
|
||||
: new Decimal(discount.amount);
|
||||
|
||||
// Update the invoice's total price by adding the discount amount (effectively removing the discount)
|
||||
invoice.totalPrice = new Decimal(invoice.totalPrice).add(discountAmount);
|
||||
await this.invoiceRepository.save(invoice);
|
||||
|
||||
// Delete the usage discount record
|
||||
await this.usageDiscountRepository.delete(usage.id);
|
||||
|
||||
return {
|
||||
|
||||
@@ -12,9 +12,28 @@ export class UpdateProfileDto extends PartialType(PickType(CompleteRegistrationD
|
||||
@ApiPropertyOptional({ description: "User name", example: "mamad24" })
|
||||
userName?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: "Profile picture", example: "https://www.google.com" })
|
||||
@IsOptional()
|
||||
@IsNotEmpty({ message: UserMessage.PROFILE_PIC_REQUIRED })
|
||||
@IsUrl({ protocols: ["http", "https"], require_protocol: true }, { message: UserMessage.PROFILE_PIC_URL })
|
||||
@ApiPropertyOptional({ description: "Profile picture", example: "https://www.google.com" })
|
||||
profilePic?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: "User address", example: "123 Main St" })
|
||||
@IsOptional()
|
||||
@IsNotEmpty({ message: UserMessage.ADDRESS_REQUIRED })
|
||||
@IsString({ message: UserMessage.ADDRESS_SHOULD_BE_STRING })
|
||||
@Length(5, 255, { message: UserMessage.ADDRESS_LENGTH })
|
||||
userAddress?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: "Postal code", example: "1234567890" })
|
||||
@IsOptional()
|
||||
@IsNotEmpty({ message: UserMessage.POSTAL_CODE_REQUIRED })
|
||||
@IsString({ message: UserMessage.POSTAL_CODE_SHOULD_BE_STRING })
|
||||
@Length(10, 10, { message: UserMessage.POSTAL_CODE_LENGTH })
|
||||
postalCode?: string;
|
||||
|
||||
@ApiPropertyOptional({ description: "City id" })
|
||||
@IsOptional()
|
||||
@IsNotEmpty({ message: UserMessage.CITY_REQUIRED })
|
||||
cityId: string;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Exclude } from "class-transformer";
|
||||
import { Column, Entity, JoinColumn, JoinTable, ManyToMany, OneToMany, OneToOne } from "typeorm";
|
||||
import { Column, Entity, JoinColumn, JoinTable, ManyToMany, ManyToOne, OneToMany, OneToOne } from "typeorm";
|
||||
|
||||
import { LegalUser } from "./legal-user.entity";
|
||||
import { RealUser } from "./real-user.entity";
|
||||
@@ -7,6 +7,7 @@ import { Role } from "./role.entity";
|
||||
import { UserGroup } from "./user-group.entity";
|
||||
import { BaseEntity } from "../../../common/entities/base.entity";
|
||||
import { Address } from "../../address/entities/address.entity";
|
||||
import { City } from "../../address/entities/city.entity";
|
||||
import { UserAnnouncement } from "../../announcements/entities/user-announcement.entity";
|
||||
import { Criticism } from "../../criticisms/entities/criticism.entity";
|
||||
import { DanakServiceReview } from "../../danak-services/entities/danak-service-review.entity";
|
||||
@@ -54,10 +55,18 @@ export class User extends BaseEntity {
|
||||
|
||||
@Column({ type: "boolean", default: false })
|
||||
emailVerified: boolean;
|
||||
|
||||
@Column({ type: "varchar", length: 255, nullable: true })
|
||||
userAddress: string;
|
||||
|
||||
@Column({ type: "varchar", length: 10, nullable: true })
|
||||
postalCode: string;
|
||||
//-----------------------------------------
|
||||
|
||||
@ManyToOne(() => City, { eager: true, nullable: true })
|
||||
city: City;
|
||||
// @ManyToOne(() => Role, { eager: true, onDelete: "RESTRICT", nullable: false })
|
||||
// role: Role;
|
||||
|
||||
@ManyToMany(() => Role, (role) => role.users)
|
||||
@JoinTable({ name: "user_role_relation" })
|
||||
roles: Role[];
|
||||
|
||||
@@ -80,7 +80,7 @@ export class UsersService {
|
||||
/************************************************************ */
|
||||
|
||||
async getMe(userId: string) {
|
||||
const user = await this.userRepository.findOne({ where: { id: userId }, relations: { roles: true } });
|
||||
const user = await this.userRepository.findOne({ where: { id: userId }, relations: { roles: true, city: { province: true } } });
|
||||
if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
|
||||
return { user };
|
||||
}
|
||||
@@ -104,9 +104,17 @@ export class UsersService {
|
||||
/************************************************************ */
|
||||
|
||||
async updateProfile(userId: string, updateProfileDto: UpdateProfileDto) {
|
||||
let city;
|
||||
|
||||
const user = await this.userRepository.findOneBy({ id: userId });
|
||||
if (!user) throw new BadRequestException(UserMessage.USER_NOT_FOUND);
|
||||
|
||||
if (updateProfileDto.cityId) {
|
||||
const { city: existCity } = await this.addressService.getCity(+updateProfileDto.cityId);
|
||||
if (!existCity) throw new BadRequestException(UserMessage.CITY_NOT_FOUND);
|
||||
city = existCity;
|
||||
}
|
||||
|
||||
//
|
||||
if (updateProfileDto.userName) {
|
||||
updateProfileDto.userName = slugify(updateProfileDto.userName, { lower: true, trim: true });
|
||||
@@ -114,7 +122,7 @@ export class UsersService {
|
||||
if (existUserName) throw new BadRequestException(UserMessage.USERNAME_EXIST);
|
||||
}
|
||||
|
||||
await this.userRepository.save({ ...user, ...updateProfileDto });
|
||||
await this.userRepository.save({ ...user, ...updateProfileDto, city });
|
||||
//
|
||||
return {
|
||||
message: CommonMessage.UPDATE_SUCCESS,
|
||||
|
||||
Reference in New Issue
Block a user