diff --git a/src/app.module.ts b/src/app.module.ts index f7e7dad..8ab914f 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -17,9 +17,11 @@ import { AuthModule } from "./modules/auth/auth.module"; import { ContactUsModule } from "./modules/contact-us/contact-us.module"; import { CriticismModule } from "./modules/criticisms/criticisms.module"; import { DanakServicesModule } from "./modules/danak-services/danak-services.module"; +import { InvoicesModule } from "./modules/invoices/invoices.module"; import { NotificationModule } from "./modules/notifications/notifications.module"; import { PaymentsModule } from "./modules/payments/payments.module"; import { SettingModule } from "./modules/settings/settings.module"; +import { SubscriptionsModule } from "./modules/subscriptions/subscriptions.module"; import { TicketsModule } from "./modules/tickets/tickets.module"; import { UploaderModule } from "./modules/uploader/uploader.module"; import { UsersModule } from "./modules/users/users.module"; @@ -46,6 +48,8 @@ import { WalletsModule } from "./modules/wallets/wallets.module"; WalletsModule, PaymentsModule, NotificationModule, + InvoicesModule, + SubscriptionsModule, ], controllers: [], providers: [], diff --git a/src/modules/danak-services/entities/danak-service.entity.ts b/src/modules/danak-services/entities/danak-service.entity.ts index eb29768..bbc5702 100644 --- a/src/modules/danak-services/entities/danak-service.entity.ts +++ b/src/modules/danak-services/entities/danak-service.entity.ts @@ -1,11 +1,11 @@ -import { Column, Entity, ManyToMany, ManyToOne, OneToMany } from "typeorm"; +import { Column, Entity, ManyToOne, OneToMany } from "typeorm"; import { DanakServiceCategory } from "./danak-service-category.entity"; import { DanakServiceImage } from "./danak-service-image.entity"; import { BaseEntity } from "../../../common/entities/base.entity"; import { Announcement } from "../../announcements/entities/announcement.entity"; +import { SubscriptionPlan } from "../../subscriptions/entities/subscription.entity"; import { Ticket } from "../../tickets/entities/ticket.entity"; -import { User } from "../../users/entities/user.entity"; import { ServicesLanguage } from "../enums/services-language.enum"; @Entity() @@ -61,6 +61,9 @@ export class DanakService extends BaseEntity { @OneToMany(() => Ticket, (ticket) => ticket.danakService) tickets: Ticket[]; - @ManyToMany(() => User, (user) => user.danakServices) - users: User[]; + @OneToMany(() => SubscriptionPlan, (plan) => plan.service, { cascade: true }) + subscriptionPlans: SubscriptionPlan[]; } + +// @ManyToMany(() => User, (user) => user.danakServices) +// users: User[]; diff --git a/src/modules/invoices/entities/invoice.entity.ts b/src/modules/invoices/entities/invoice.entity.ts new file mode 100644 index 0000000..5e7a7c4 --- /dev/null +++ b/src/modules/invoices/entities/invoice.entity.ts @@ -0,0 +1,24 @@ +import { Column, Entity, ManyToOne } from "typeorm"; + +import { BaseEntity } from "../../../common/entities/base.entity"; +import { SubscriptionPlan } from "../../subscriptions/entities/subscription.entity"; +import { User } from "../../users/entities/user.entity"; +import { InvoiceStatus } from "../enums/invoice-status.enum"; + +@Entity() +export class Invoice extends BaseEntity { + @ManyToOne(() => User, (user) => user.invoices, { nullable: true, onDelete: "RESTRICT" }) + user: User; + + @ManyToOne(() => SubscriptionPlan, { nullable: true, onDelete: "SET NULL" }) + subscriptionPlan?: SubscriptionPlan; + + @Column({ type: "decimal", precision: 10, scale: 2, nullable: false }) + amount: number; + + @Column({ type: "enum", enum: InvoiceStatus, default: InvoiceStatus.PENDING }) + status: InvoiceStatus; + + @Column({ type: "timestamp", nullable: true }) + paidAt?: Date; +} diff --git a/src/modules/invoices/enums/invoice-status.enum.ts b/src/modules/invoices/enums/invoice-status.enum.ts new file mode 100644 index 0000000..5fb5e40 --- /dev/null +++ b/src/modules/invoices/enums/invoice-status.enum.ts @@ -0,0 +1,5 @@ +export enum InvoiceStatus { + PENDING = "PENDING", + PAID = "PAID", + CANCELED = "CANCELED", +} diff --git a/src/modules/invoices/invoices.controller.ts b/src/modules/invoices/invoices.controller.ts new file mode 100644 index 0000000..cfe4b97 --- /dev/null +++ b/src/modules/invoices/invoices.controller.ts @@ -0,0 +1,4 @@ +import { Controller } from "@nestjs/common"; + +@Controller("invoices") +export class InvoicesController {} diff --git a/src/modules/invoices/invoices.module.ts b/src/modules/invoices/invoices.module.ts new file mode 100644 index 0000000..6faf6f7 --- /dev/null +++ b/src/modules/invoices/invoices.module.ts @@ -0,0 +1,15 @@ +import { Module } from "@nestjs/common"; +import { TypeOrmModule } from "@nestjs/typeorm"; + +import { Invoice } from "./entities/invoice.entity"; +import { InvoicesController } from "./invoices.controller"; +import { InvoicesService } from "./providers/invoices.service"; +import { InvoicesRepository } from "./repositories/invoices.repository"; + +@Module({ + imports: [TypeOrmModule.forFeature([Invoice])], + providers: [InvoicesService, InvoicesRepository], + controllers: [InvoicesController], + exports: [InvoicesService], +}) +export class InvoicesModule {} diff --git a/src/modules/invoices/providers/invoices.service.ts b/src/modules/invoices/providers/invoices.service.ts new file mode 100644 index 0000000..ed02092 --- /dev/null +++ b/src/modules/invoices/providers/invoices.service.ts @@ -0,0 +1,4 @@ +import { Injectable } from "@nestjs/common"; + +@Injectable() +export class InvoicesService {} diff --git a/src/modules/invoices/repositories/invoices.repository.ts b/src/modules/invoices/repositories/invoices.repository.ts new file mode 100644 index 0000000..d7090bc --- /dev/null +++ b/src/modules/invoices/repositories/invoices.repository.ts @@ -0,0 +1,12 @@ +import { Injectable } from "@nestjs/common"; +import { InjectRepository } from "@nestjs/typeorm"; +import { Repository } from "typeorm"; + +import { Invoice } from "../entities/invoice.entity"; + +@Injectable() +export class InvoicesRepository extends Repository { + constructor(@InjectRepository(Invoice) invoicesRepository: Repository) { + super(invoicesRepository.target, invoicesRepository.manager, invoicesRepository.queryRunner); + } +} diff --git a/src/modules/subscriptions/entities/subscription.entity.ts b/src/modules/subscriptions/entities/subscription.entity.ts new file mode 100644 index 0000000..f7e6e9e --- /dev/null +++ b/src/modules/subscriptions/entities/subscription.entity.ts @@ -0,0 +1,22 @@ +import { Column, Entity, ManyToOne } from "typeorm"; + +import { BaseEntity } from "../../../common/entities/base.entity"; +import { DanakService } from "../../danak-services/entities/danak-service.entity"; + +@Entity() +export class SubscriptionPlan extends BaseEntity { + @Column({ type: "varchar", length: 100, nullable: false }) + name: string; + + @Column({ type: "int", nullable: false }) + duration: number; + + @Column({ type: "decimal", precision: 10, scale: 2, nullable: false }) + price: number; + + @Column({ type: "boolean", default: true }) + isActive: boolean; + + @ManyToOne(() => DanakService, (danakService) => danakService.subscriptionPlans, { nullable: false, onDelete: "CASCADE" }) + service: DanakService; +} diff --git a/src/modules/subscriptions/entities/user-subscription.entity.ts b/src/modules/subscriptions/entities/user-subscription.entity.ts new file mode 100644 index 0000000..ec4228a --- /dev/null +++ b/src/modules/subscriptions/entities/user-subscription.entity.ts @@ -0,0 +1,23 @@ +import { Column, Entity, ManyToOne } from "typeorm"; + +import { SubscriptionPlan } from "./subscription.entity"; +import { BaseEntity } from "../../../common/entities/base.entity"; +import { User } from "../../users/entities/user.entity"; + +@Entity() +export class UserSubscription extends BaseEntity { + @ManyToOne(() => User, (user) => user.subscriptions, { nullable: false, onDelete: "CASCADE" }) + user: User; + + @ManyToOne(() => SubscriptionPlan, { nullable: false, onDelete: "CASCADE" }) + plan: SubscriptionPlan; + + @Column({ type: "timestamp", nullable: false }) // When the subscription started + startDate: Date; + + @Column({ type: "timestamp", nullable: false }) // When it expires + endDate: Date; + + @Column({ type: "boolean", default: false }) // Whether the user canceled it + isCanceled: boolean; +} diff --git a/src/modules/subscriptions/providers/subscriptions.service.ts b/src/modules/subscriptions/providers/subscriptions.service.ts new file mode 100644 index 0000000..6851936 --- /dev/null +++ b/src/modules/subscriptions/providers/subscriptions.service.ts @@ -0,0 +1,4 @@ +import { Injectable } from "@nestjs/common"; + +@Injectable() +export class SubscriptionsService {} diff --git a/src/modules/subscriptions/repositories/subscriptions.repository.ts b/src/modules/subscriptions/repositories/subscriptions.repository.ts new file mode 100644 index 0000000..f3480ac --- /dev/null +++ b/src/modules/subscriptions/repositories/subscriptions.repository.ts @@ -0,0 +1,12 @@ +import { Injectable } from "@nestjs/common"; +import { InjectRepository } from "@nestjs/typeorm"; +import { Repository } from "typeorm"; + +import { SubscriptionPlan } from "../entities/subscription.entity"; + +@Injectable() +export class SubscriptionsRepository extends Repository { + constructor(@InjectRepository(SubscriptionPlan) subscriptionPlanRepository: Repository) { + super(subscriptionPlanRepository.target, subscriptionPlanRepository.manager, subscriptionPlanRepository.queryRunner); + } +} diff --git a/src/modules/subscriptions/repositories/user-subscriptions.repository.ts b/src/modules/subscriptions/repositories/user-subscriptions.repository.ts new file mode 100644 index 0000000..d9708f8 --- /dev/null +++ b/src/modules/subscriptions/repositories/user-subscriptions.repository.ts @@ -0,0 +1,10 @@ +import { Injectable } from "@nestjs/common"; +import { InjectRepository } from "@nestjs/typeorm"; +import { Repository } from "typeorm"; + +@Injectable() +export class UserSubscriptionsRepository extends Repository { + constructor(@InjectRepository(UserSubscriptionsRepository) userSubscriptionsRepository: Repository) { + super(userSubscriptionsRepository.target, userSubscriptionsRepository.manager, userSubscriptionsRepository.queryRunner); + } +} diff --git a/src/modules/subscriptions/subscriptions.controller.ts b/src/modules/subscriptions/subscriptions.controller.ts new file mode 100644 index 0000000..6f7183f --- /dev/null +++ b/src/modules/subscriptions/subscriptions.controller.ts @@ -0,0 +1,4 @@ +import { Controller } from "@nestjs/common"; + +@Controller("subscriptions") +export class SubscriptionsController {} diff --git a/src/modules/subscriptions/subscriptions.module.ts b/src/modules/subscriptions/subscriptions.module.ts new file mode 100644 index 0000000..56d9c7a --- /dev/null +++ b/src/modules/subscriptions/subscriptions.module.ts @@ -0,0 +1,17 @@ +import { Module } from "@nestjs/common"; +import { TypeOrmModule } from "@nestjs/typeorm"; + +import { SubscriptionPlan } from "./entities/subscription.entity"; +import { UserSubscription } from "./entities/user-subscription.entity"; +import { SubscriptionsService } from "./providers/subscriptions.service"; +import { SubscriptionsRepository } from "./repositories/subscriptions.repository"; +import { UserSubscriptionsRepository } from "./repositories/user-subscriptions.repository"; +import { SubscriptionsController } from "./subscriptions.controller"; + +@Module({ + imports: [TypeOrmModule.forFeature([SubscriptionPlan, UserSubscription])], + providers: [SubscriptionsService, SubscriptionsRepository, UserSubscriptionsRepository], + controllers: [SubscriptionsController], + exports: [SubscriptionsService], +}) +export class SubscriptionsModule {} diff --git a/src/modules/users/entities/user.entity.ts b/src/modules/users/entities/user.entity.ts index 6a64771..033e945 100644 --- a/src/modules/users/entities/user.entity.ts +++ b/src/modules/users/entities/user.entity.ts @@ -1,15 +1,16 @@ import { Exclude } from "class-transformer"; -import { Column, Entity, JoinTable, ManyToMany, ManyToOne, OneToMany, OneToOne } from "typeorm"; +import { Column, Entity, ManyToMany, ManyToOne, OneToMany, OneToOne } from "typeorm"; import { Role } from "./role.entity"; import { UserGroup } from "./user-group.entity"; import { BaseEntity } from "../../../common/entities/base.entity"; import { UserAnnouncement } from "../../announcements/entities/user-announcement.entity"; import { Criticism } from "../../criticisms/entities/criticism.entity"; -import { DanakService } from "../../danak-services/entities/danak-service.entity"; +import { Invoice } from "../../invoices/entities/invoice.entity"; import { Notification } from "../../notifications/entities/notification.entity"; import { Payment } from "../../payments/entities/payment.entity"; import { UserSetting } from "../../settings/entities/user-setting.entity"; +import { UserSubscription } from "../../subscriptions/entities/user-subscription.entity"; import { TicketMessage } from "../../tickets/entities/ticket-message.entity"; import { Ticket } from "../../tickets/entities/ticket.entity"; import { Wallet } from "../../wallets/entities/wallet.entity"; @@ -41,6 +42,7 @@ export class User extends BaseEntity { @Column({ type: "varchar", length: 100, unique: true, nullable: false }) nationalCode: string; + //----------------------------------------- @ManyToOne(() => Role, { eager: true, onDelete: "RESTRICT", nullable: false }) role: Role; @@ -56,10 +58,6 @@ export class User extends BaseEntity { @OneToMany(() => Criticism, (criticism) => criticism.user) criticisms: Criticism[]; - @ManyToMany(() => DanakService, (danakService) => danakService.users) - @JoinTable() - danakServices: DanakService[]; - @OneToMany(() => UserAnnouncement, (userAnnouncement) => userAnnouncement.user) userAnnouncements: UserAnnouncement[]; @@ -74,4 +72,14 @@ export class User extends BaseEntity { @OneToMany(() => Notification, (notification) => notification.recipient) notifications: Notification[]; + + @OneToMany(() => UserSubscription, (subscription) => subscription.user) + subscriptions: UserSubscription[]; + + @OneToMany(() => Invoice, (invoice) => invoice.user) + invoices: Invoice[]; } + +// @ManyToMany(() => DanakService, (danakService) => danakService.users) +// @JoinTable() +// danakServices: DanakService[];