add:barname
Build and Deploy Docker Images / build_and_deploy (push) Has been cancelled

This commit is contained in:
2026-06-03 11:24:14 +03:30
parent 44d1c39a67
commit 0718bd1230
16 changed files with 84 additions and 105 deletions
+2 -2
View File
@@ -16,6 +16,7 @@ import { rateLimitConfig } from "./configs/rateLimit.config";
import { HTTPLogger } from "./core/middlewares/logger.middleware";
import { AnnouncementsModule } from "./modules/announcements/announcement.module";
import { AuthModule } from "./modules/auth/auth.module";
import { BarnameModule } from "./modules/barname/barname.module";
import { BillsModule } from "./modules/bills/bills.module";
import { BusinessesModule } from "./modules/businesses/businesses.module";
import { ChatbotModule } from "./modules/chatbot/chatbot.module";
@@ -31,7 +32,6 @@ import { TicketsModule } from "./modules/tickets/tickets.module";
import { UploaderModule } from "./modules/uploader/uploader.module";
import { UsersModule } from "./modules/users/users.module";
import { UtilsModule } from "./modules/utils/utils.module";
import { BarnameModule } from "./modules/barname/barname.module";
@Module({
imports: [
@@ -68,7 +68,7 @@ import { BarnameModule } from "./modules/barname/barname.module";
ChatbotModule,
SearchModule,
BillsModule,
BarnameModule
BarnameModule,
],
})
export class AppModule implements NestModule {
+3 -3
View File
@@ -530,9 +530,9 @@ export const enum IndustryMessage {
}
export const enum CompanyMessage {
RENT_CONTRACT_IMAGE_IS_REQUIRED="تصویر اجاره نامه الزامی است",
RENT_END_IS_REQUIRED="تاریخ پایان قرارداد الزامی است",
RENT_CONTRACT_IS_EXPIRED="تاریخ قرارداد پایان یافته است",
RENT_CONTRACT_IMAGE_IS_REQUIRED = "تصویر اجاره نامه الزامی است",
RENT_END_IS_REQUIRED = "تاریخ پایان قرارداد الزامی است",
RENT_CONTRACT_IS_EXPIRED = "تاریخ قرارداد پایان یافته است",
ADDRESS_MUST_BE_STRING = "آدرس شرکت باید یک رشته باشد",
ADDRESS_REQUIRED = "آدرس شرکت مورد نیاز است",
CHIEF_EXECUTIVE_MUST_BE_STRING = "نام مدیرعامل باید یک رشته باشد",
+1 -1
View File
@@ -26,7 +26,7 @@ export class AuthService {
private readonly notificationQueue: NotificationQueue,
private readonly smsService: SmsService,
private readonly em: EntityManager,
) { }
) {}
//****************** */
//****************** */
async initiateRegistration(requestOtpDto: RequestOtpDto, businessId: string) {
+7 -11
View File
@@ -1,36 +1,32 @@
import {
Body, Controller, Delete, Get, Param, Post,Patch,
Query, UseInterceptors
} from "@nestjs/common";
import { Body, Controller, Delete, Get, Param, Patch, Post, Query, UseInterceptors } from "@nestjs/common";
import { ApiHeader, ApiOperation } from "@nestjs/swagger";
import { BarnameService } from "./barname.service";
import { BillListQueryDto } from "./dto/bill-list-query.dto";
import { CreateBarnameDto } from "./dto/create-barname.dto";
import { UpdateBarnameAsWatcherDto } from "./dto/update-barname-watcher.dto";
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
import { BusinessDec } from "../../common/decorators/business.decorator";
import { UserDec } from "../../common/decorators/user.decorator";
import { ParamDto } from "../../common/DTO/param.dto";
import { BusinessInterceptor } from "../../core/interceptors/business.interceptor";
import { Business } from "../businesses/entities/business.entity";
import { UserDec } from "../../common/decorators/user.decorator";
import { RoleEnum } from "../users/enums/role.enum";
import { UpdateBarnameAsWatcherDto } from "./dto/update-barname-watcher.dto";
import { User } from "../users/entities/user.entity";
import { RoleEnum } from "../users/enums/role.enum";
@Controller("barname")
@UseInterceptors(BusinessInterceptor)
@AuthGuards()
export class BarnameController {
constructor(private readonly barnameService: BarnameService) { }
constructor(private readonly barnameService: BarnameService) {}
@ApiOperation({ summary: "Create barname" })
@Post()
@ApiHeader({ name: "x-business-id" })
createWaterBill(@Body() dto: CreateBarnameDto, @BusinessDec() business: Business, @UserDec("id") userId: string,) {
createWaterBill(@Body() dto: CreateBarnameDto, @BusinessDec() business: Business, @UserDec("id") userId: string) {
return this.barnameService.createBarname(dto, business, userId);
}
@ApiOperation({ summary: "Get all barname with filters and pagination" })
@Get()
@ApiHeader({ name: "x-business-id" })
@@ -46,7 +42,7 @@ export class BarnameController {
@ApiOperation({ summary: "Update Barname by watcher" })
@Patch(":id/watcher")
update(@Param('id') id: string, @BusinessDec() business: Business, @Body() dto: UpdateBarnameAsWatcherDto, @UserDec("role") role: RoleEnum) {
update(@Param("id") id: string, @BusinessDec() business: Business, @Body() dto: UpdateBarnameAsWatcherDto, @UserDec("role") role: RoleEnum) {
return this.barnameService.updateBarnameAsWatcher(id, dto, business, role);
}
+23 -26
View File
@@ -1,19 +1,18 @@
import { EntityManager } from "@mikro-orm/postgresql";
import { BadRequestException, ForbiddenException, Injectable } from "@nestjs/common";
import dayjs from "dayjs";
import { BillListQueryDto } from "./dto/bill-list-query.dto";
import { CreateBarnameDto } from "./dto/create-barname.dto";
import { UpdateBarnameAsWatcherDto } from "./dto/update-barname-watcher.dto";
import { Barname } from "./entities/barname.entity";
import { BarnameStatus } from "./enums/bill-type.enum";
import { BarnameRepository } from "./repositories/barname.repository";
import { CompanyMessage } from "../../common/enums/message.enum";
import { Business } from "../businesses/entities/business.entity";
import { Company } from "../companies/entities/company.entity";
import { BarnameStatus } from "./enums/bill-type.enum";
import { UpdateBarnameAsWatcherDto } from "./dto/update-barname-watcher.dto";
import { RoleEnum } from "../users/enums/role.enum";
import { User } from "../users/entities/user.entity";
import dayjs from "dayjs";
import { RoleEnum } from "../users/enums/role.enum";
@Injectable()
export class BarnameService {
@@ -23,7 +22,7 @@ export class BarnameService {
constructor(
private readonly em: EntityManager,
private readonly barnameRepository: BarnameRepository,
) { }
) {}
async createBarname(dto: CreateBarnameDto, business: Business, userId: string) {
const { description, driverName, driverPhone, carType, exitAt, origin, plaque, attachments } = dto;
@@ -31,17 +30,17 @@ export class BarnameService {
const company = await this.em.findOne(Company, { business, user: { id: userId }, deletedAt: null });
if (!company) throw new BadRequestException(CompanyMessage.COMPANY_NOT_FOUND);
if (company.isRented) { // validate for rented company
if (company.isRented) {
// validate for rented company
if (!company.rentEndAt) {
throw new BadRequestException(CompanyMessage.RENT_END_IS_REQUIRED)
throw new BadRequestException(CompanyMessage.RENT_END_IS_REQUIRED);
}
if (dayjs().isAfter(company.rentEndAt)) {
throw new BadRequestException(CompanyMessage.RENT_CONTRACT_IS_EXPIRED)
throw new BadRequestException(CompanyMessage.RENT_CONTRACT_IS_EXPIRED);
}
}
const bill = this.em.create(Barname,
{
const bill = this.em.create(Barname, {
carType,
exitAt,
origin,
@@ -52,39 +51,37 @@ export class BarnameService {
driverPhone,
company,
attachments,
status: BarnameStatus.PENDING
status: BarnameStatus.PENDING,
});
await this.em.persistAndFlush(bill);
return bill
return bill;
}
async updateBarnameAsWatcher(id: string, dto: UpdateBarnameAsWatcherDto, business: Business, role: RoleEnum) {
if (role != RoleEnum.WATCHER) {
throw new ForbiddenException("you are not allowed")
throw new ForbiddenException("you are not allowed");
}
const { exitedAt, watcherDescription } = dto;
const barname = await this.findOne(id, business.id)
const barname = await this.findOne(id, business.id);
barname.exitedAt = exitedAt
barname.exitedAt = exitedAt;
barname.status = BarnameStatus.COMPLETED
barname.status = BarnameStatus.COMPLETED;
if (watcherDescription) {
barname.watcherDescription = watcherDescription
barname.watcherDescription = watcherDescription;
}
await this.em.flush();
return barname
return barname;
}
async findAll(queryDto: BillListQueryDto, business: Business, user: User) {
const companyId = undefined
const companyId = undefined;
if (user.role.name == RoleEnum.USER) {
const company = await this.em.findOne(Company, { business, user: { id: user.id }, deletedAt: null });
@@ -100,9 +97,9 @@ export class BarnameService {
}
async findOne(id: string, businessId: string) {
const barname = await this.findOneOrFail(id)
const barname = await this.findOneOrFail(id);
if (barname.business.id !== businessId) {
throw new BadRequestException("This business doenst belongs to you")
throw new BadRequestException("This business doenst belongs to you");
}
return barname;
}
@@ -121,10 +118,10 @@ export class BarnameService {
}
async findOneOrFail(id: string) {
const barname = await this.barnameRepository.findOne({ id }, { populate: ['company', 'business'] });
const barname = await this.barnameRepository.findOne({ id }, { populate: ["company", "business"] });
if (!barname) {
throw new BadRequestException("barname not found");
}
return barname
return barname;
}
}
@@ -1,6 +1,5 @@
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
import { IsArray, IsDateString, IsNotEmpty, IsOptional, IsString, } from "class-validator";
import { IsArray, IsDateString, IsNotEmpty, IsOptional, IsString } from "class-validator";
export class CreateBarnameDto {
@ApiProperty({ description: "Barname title" })
@@ -26,7 +25,6 @@ export class CreateBarnameDto {
@IsOptional()
origin: string;
@ApiPropertyOptional()
@IsString()
@IsOptional()
@@ -37,10 +35,7 @@ export class CreateBarnameDto {
@IsArray()
attachments: string[];
@ApiProperty()
@IsDateString()
exitAt: string;
}
@@ -1,7 +1,6 @@
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
import { IsDateString, IsOptional, IsString } from "class-validator";
export class UpdateBarnameAsWatcherDto {
@ApiProperty()
@IsDateString()
@@ -12,4 +11,3 @@ export class UpdateBarnameAsWatcherDto {
@IsOptional()
watcherDescription: string;
}
+11 -11
View File
@@ -2,9 +2,9 @@ import { Entity, EntityRepositoryType, ManyToOne, Opt, Property } from "@mikro-o
import { BaseEntity } from "../../../common/entities/base.entity";
import { Business } from "../../businesses/entities/business.entity";
import { BarnameRepository } from "../repositories/barname.repository";
import { Company } from "../../companies/entities/company.entity";
import { BarnameStatus } from "../enums/bill-type.enum";
import { BarnameRepository } from "../repositories/barname.repository";
@Entity({ repository: () => BarnameRepository })
export class Barname extends BaseEntity {
@@ -14,28 +14,28 @@ export class Barname extends BaseEntity {
@ManyToOne(() => Company, { nullable: false, deleteRule: "cascade" })
company!: Company;
@Property({ type: 'numeric', autoincrement: true })
@Property({ type: "numeric", autoincrement: true })
number!: number & Opt;
@Property({ type: 'string' })
@Property({ type: "string" })
driverName: string;
@Property({ type: 'string' })
@Property({ type: "string" })
driverPhone: string;
@Property({ type: 'string', nullable: true })
@Property({ type: "string", nullable: true })
origin?: string;
@Property({ type: 'string' })
@Property({ type: "string" })
carType: string;
@Property({ type: 'string' })
@Property({ type: "string" })
plaque: string;
@Property({ type: 'string', nullable: true })
@Property({ type: "string", nullable: true })
description?: string;
@Property({ type: 'json' })
@Property({ type: "json" })
attachments: string[];
@Property({ nullable: true })
@@ -45,9 +45,9 @@ export class Barname extends BaseEntity {
exitedAt?: string;
@Property()
status: BarnameStatus & Opt
status: BarnameStatus & Opt;
@Property({ type: 'string', nullable: true })
@Property({ type: "string", nullable: true })
watcherDescription?: string;
[EntityRepositoryType]?: BarnameRepository;
+2 -2
View File
@@ -1,4 +1,4 @@
export enum BarnameStatus {
PENDING='pending',
COMPLETED='completed'
PENDING = "pending",
COMPLETED = "completed",
}
@@ -18,23 +18,22 @@ export class BarnameRepository extends EntityRepository<Barname> {
}
if (queryDto.since) {
where.createdAt = { $gte: queryDto.since }
where.createdAt = { $gte: queryDto.since };
}
if (queryDto.companyId) {
where.company = { id: queryDto.companyId }
where.company = { id: queryDto.companyId };
}
if (queryDto.to) {
where.createdAt = { $lte: queryDto.to }
where.createdAt = { $lte: queryDto.to };
}
return this.findAndCount(where, {
populate: ["company"],
limit,
offset: skip,
orderBy: { createdAt: "DESC" }
orderBy: { createdAt: "DESC" },
});
}
}
@@ -141,7 +141,7 @@ export class CreateCompanyRequestDto extends PickType(CreateCompanyDto, [
"metrage",
"isRented",
"contractImages",
"rentEndAt"
"rentEndAt",
]) {
@IsNotEmpty({ message: CompanyMessage.CHIEF_EXECUTIVE_REQUIRED })
@IsString({ message: CompanyMessage.CHIEF_EXECUTIVE_MUST_BE_STRING })
@@ -30,7 +30,7 @@ export class CompaniesService {
private readonly passwordService: PasswordService,
private readonly em: EntityManager,
private readonly companyRequestRepository: CompanyRequestRepository,
) { }
) {}
async create(createDto: CreateCompanyDto, business: Business) {
const em = this.em.fork();
@@ -416,7 +416,7 @@ export class CompaniesService {
private async createCompany(createDto: CreateCompanyDto | CreateCompanyRequestDto, user: User, business: Business, em: EntityManager) {
if (createDto.isRented) {
if (!createDto.rentEndAt) {
throw new BadRequestException(CompanyMessage.RENT_END_IS_REQUIRED)
throw new BadRequestException(CompanyMessage.RENT_END_IS_REQUIRED);
}
}
@@ -459,7 +459,7 @@ export class CompaniesService {
business,
chiefExecutiveOfficer: "chiefExecutiveOfficer" in createDto ? createDto.chiefExecutiveOfficer : `${createDto.firstName} ${createDto.lastName}`,
email: createDto.email,
phone: createDto.phone
phone: createDto.phone,
});
await em.persistAndFlush(company);
@@ -12,7 +12,6 @@ export class CreateWatcherDto {
@ApiProperty({ description: "phone number", default: "09922320740" })
phone: string;
@IsNotEmpty({ message: AuthMessage.FIRST_NAME_NOT_EMPTY })
@IsString({ message: AuthMessage.FIRST_NAME_NOT_EMPTY })
@Length(2, 50, { message: AuthMessage.FIRST_NAME_SHOULD_BE_BETWEEN_2_AND_50 })
@@ -25,7 +24,6 @@ export class CreateWatcherDto {
@ApiProperty({ description: "Last name", example: "jamshidi" })
lastName: string;
@IsNotEmpty({ message: AuthMessage.NATIONAL_NOT_EMPTY })
@IsNumberString({ no_symbols: true }, { message: AuthMessage.NATIONAL_CODE_INCORRECT })
@Length(10, 10, { message: AuthMessage.NATIONAL_CODE_INCORRECT })
+10 -13
View File
@@ -6,19 +6,19 @@ import { UserMessage } from "../../../common/enums/message.enum";
import { CompleteRegistrationDto } from "../../auth/DTO/complete-register.dto";
import { Business } from "../../businesses/entities/business.entity";
import { CreateCompanyDto } from "../../companies/DTO/create-company.dto";
import { PasswordService } from "../../utils/providers/password.service";
import { CreateWatcherDto } from "../DTO/create-watcher.dto";
import { Role } from "../entities/role.entity";
import { User } from "../entities/user.entity";
import { RoleEnum } from "../enums/role.enum";
import { UserRepository } from "../repositories/user.repository";
import { CreateWatcherDto } from "../DTO/create-watcher.dto";
import { PasswordService } from "../../utils/providers/password.service";
@Injectable()
export class UsersService {
constructor(
private readonly userRepository: UserRepository,
private readonly passwordService: PasswordService,
private readonly em: EntityManager,
) { }
) {}
/*******************************/
@@ -157,7 +157,6 @@ export class UsersService {
if (existPhone) throw new BadRequestException(UserMessage.PHONE_EXIST);
if (existUser) throw new BadRequestException(UserMessage.NATIONAL_CODE_EXIST);
const userName = slugify(`${dto.firstName} ${Date.now().toString().slice(-5)}`, { lower: true, trim: true });
const watcher = em.create(User, {
@@ -173,8 +172,6 @@ export class UsersService {
await em.commit();
return watcher;
} catch (error) {
await em.rollback();
throw error;
@@ -183,25 +180,25 @@ export class UsersService {
/*******************************/
async getWatchers(business: Business) {
return this.userRepository.find({ business: { id: business.id }, role: { name: RoleEnum.WATCHER }, deletedAt: null })
return this.userRepository.find({ business: { id: business.id }, role: { name: RoleEnum.WATCHER }, deletedAt: null });
}
/*******************************/
async getWatcherById(id: string, business: Business) {
return this.userRepository.find({ id, business: { id: business.id }, role: { name: RoleEnum.WATCHER } })
return this.userRepository.find({ id, business: { id: business.id }, role: { name: RoleEnum.WATCHER } });
}
/*******************************/
async deleteWatcherById(id: string, business: Business) {
const watcher = await this.userRepository.findOne({ id, business: { id: business.id } })
const watcher = await this.userRepository.findOne({ id, business: { id: business.id } });
if (!watcher) {
throw new BadRequestException("Not found")
throw new BadRequestException("Not found");
}
watcher.deletedAt = new Date()
watcher.deletedAt = new Date();
await this.em.flush()
await this.em.flush();
return watcher
return watcher;
}
}
+4 -5
View File
@@ -1,19 +1,19 @@
import { Body, Controller, Delete, Get, Param, Post, UseInterceptors } from "@nestjs/common";
import { ApiOperation } from "@nestjs/swagger";
import { CreateWatcherDto } from "./DTO/create-watcher.dto";
import { UsersService } from "./services/users.service";
import { AuthGuards } from "../../common/decorators/auth-guard.decorator";
import { UserDec } from "../../common/decorators/user.decorator";
import { CreateWatcherDto } from "./DTO/create-watcher.dto";
import { BusinessDec } from "../../common/decorators/business.decorator";
import { Business } from "../businesses/entities/business.entity";
import { UserDec } from "../../common/decorators/user.decorator";
import { BusinessInterceptor } from "../../core/interceptors/business.interceptor";
import { Business } from "../businesses/entities/business.entity";
@Controller("users")
@AuthGuards()
@UseInterceptors(BusinessInterceptor)
export class UsersController {
constructor(private readonly usersService: UsersService) { }
constructor(private readonly usersService: UsersService) {}
@ApiOperation({ summary: "Get user profile" })
@Get("me")
@@ -44,5 +44,4 @@ export class UsersController {
deleteWatcher(@Param("id") watcherId: string, @BusinessDec() business: Business) {
return this.usersService.deleteWatcherById(watcherId, business);
}
}
+1 -1
View File
@@ -14,4 +14,4 @@ import { UtilsModule } from "../utils/utils.module";
providers: [UsersService],
exports: [UsersService],
})
export class UsersModule { }
export class UsersModule {}