invoices module refactoring

master
aliMohtarami 1 month ago
parent 79a36d2b82
commit 1ce941b31c
  1. 37
      src/products/entities/invoice.entity.ts
  2. 33
      src/products/products.controller.ts
  3. 166
      src/products/products.service.ts

@ -0,0 +1,37 @@
import {
Table,
Column,
ForeignKey,
BelongsTo,
DataType,
Model,
HasMany,
} from "sequelize-typescript";
import { User } from "../../users/entities/user.entity";
import { Cart } from "src/cart/entities/cart.entity";
@Table
export class Invoice extends Model<Invoice> {
@ForeignKey(() => User)
@Column
userId: number;
@BelongsTo(() => User, { onDelete: "CASCADE" })
user: User;
@HasMany(() => Cart)
carts: Cart[];
@Column({
type: DataType.INTEGER,
allowNull: false,
})
totalPaymentAmount: number;
@Column({
type: DataType.ENUM("pending", "paid"),
allowNull: false,
defaultValue: "pending",
})
status: string;
}

@ -7,8 +7,6 @@ import { RoleGuard } from "src/guard/role.guard";
import { AddToCartDto } from "./dto/cart/add-to-cart.dto";
import { JwtAuthGuard } from "src/guard/auth.guard";
import { UpdateCartDto } from "./dto/cart/update-cart.dto";
import { PaymentService } from "src/payment/payment.service";
import { InvoiceService } from "src/invoice/invoice.service";
import { InjectModel } from "@nestjs/sequelize";
import { Transaction } from "./entities/transaction.entity";
import { Payment } from "./entities/payment.entity";
@ -17,8 +15,6 @@ import { Payment } from "./entities/payment.entity";
export class ProductsController {
constructor(
private readonly productsService: ProductsService,
private paymentService: PaymentService,
private readonly invoiceService: InvoiceService,
@InjectModel(Transaction) private readonly transactionModel: typeof Transaction,
@InjectModel(Payment) private readonly paymentModel: typeof Payment,
) {}
@ -128,7 +124,7 @@ export class ProductsController {
async addBalance(@Body("amount") amount: number, @Request() req) {
const userId = req.user.id;
const callbackUrl = `http://localhost:3000/payment/verify?userId=${userId}&amount=${amount}`;
const paymentUrl = this.paymentService.requestPayment(amount, "Wallet Charge", callbackUrl);
const paymentUrl = this.productsService.requestPayment(amount, "Wallet Charge", callbackUrl);
return paymentUrl;
}
//get transaction (user)
@ -150,13 +146,13 @@ export class ProductsController {
@Get("payment/request")
async requestPayment(@Request() req) {
const userId = req.user.id;
const invoice = await this.invoiceService.getInvoicePendingByUser(userId);
const invoice = await this.productsService.getInvoicePendingByUser(userId);
const totalAmount = invoice.totalPaymentAmount;
if (totalAmount < 1000) {
return { message: "please enter amount above 1000" };
}
const callbackUrl = `http://localhost:3000/payment/verify?userId=${userId}&amount=${totalAmount}`;
const paymentUrl = await this.paymentService.requestPayment(totalAmount, "Purchase products", callbackUrl);
const paymentUrl = await this.productsService.requestPayment(totalAmount, "Purchase products", callbackUrl);
return { url: paymentUrl };
}
@ -174,7 +170,7 @@ export class ProductsController {
}
const wallet = this.productsService.getWalletInfo(userId);
try {
const refId = await this.paymentService.verifyPayment(Authority, amount);
const refId = await this.productsService.verifyPayment(Authority, amount);
await this.productsService.addBalance(userId, amount);
const wallet = this.productsService.getWalletInfo(userId);
await this.paymentModel.create({
@ -199,4 +195,25 @@ export class ProductsController {
throw new Error(`Error during payment verification: ${error.message}`);
}
}
////////////////////////////////////////invoice////////////////////////////////////////
//get invoice (user)
@UseGuards(JwtAuthGuard)
@Get('invoice')
async getInvoiceByUser(@Request() req) {
const userId = req.user.id;
return this.productsService.getInvoiceByUser(userId);
}
//get invoices list (admin)
@UseGuards(RoleGuard)
@Get('invoice/list')
async getInvoices() {
return this.productsService.getInvoices();
}
//get specific user invoices
@UseGuards(RoleGuard)
@Get(':id')
async getUserInvoice(@Param('id') id:number) {
return this.productsService.getUserInvoices(id);
}
}

@ -463,7 +463,35 @@ export class ProductsService {
throw new HttpException("An error occurred while adding balance to the wallet.", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
//process of payment
async processPayment(userId: number, amount: number): Promise<string> {
const wallet = await this.walletModel.findOne({ where: { userId } });
if (!wallet) {
throw new HttpException("Please Charge your wallet", HttpStatus.NOT_FOUND);
}
if (wallet.balance < amount) {
throw new HttpException("Insufficient funds", HttpStatus.BAD_REQUEST);
}
try {
wallet.balance -= amount;
await this.transactionModel.create({
walletId: wallet.id,
amount: `-${amount}`,
});
await wallet.save();
return "Payment processed successfully";
} catch (error) {
console.error("Error processing payment:", error.message);
throw new HttpException("An error occurred while processing the payment.", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
///////////////////////////////////////////payment//////////////////////////////////////////////
//payment request
async requestPayment(amount: number, description: string, callbackUrl: string): Promise<string> {
try {
const result = await this.zarinpal.PaymentRequest({
@ -482,4 +510,142 @@ export class ProductsService {
throw new InternalServerErrorException(`Error in payment request: ${error.message}`);
}
}
//payment verify
async verifyPayment(authority: string, amount: number): Promise<string> {
try {
const result = await this.zarinpal.PaymentVerification({
Amount: amount,
Authority: authority,
});
if (result.status === 100) {
return result.RefID;
} else {
throw new Error(`Payment verification failed with status: ${result.status}`);
}
} catch (error) {
throw new InternalServerErrorException(`Error in payment verification: ${error.message}`);
}
}
///////////////////////////////////////////invoice//////////////////////////////////////////////
// get invoice by user
async getInvoiceByUser(userId: number) {
try {
if (!userId) {
throw new HttpException("User ID are required.", HttpStatus.BAD_REQUEST);
}
const invoices = await this.invoiceModel.findAll({
where: { userId },
});
if (!invoices) {
throw new HttpException("Invoice not found for this user and cart.", HttpStatus.NOT_FOUND);
}
return { invoices };
} catch (error) {
if (error instanceof HttpException) {
throw error;
}
throw new HttpException("An error occurred while retrieving the invoice.", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
//get list of invoices by admin
async getInvoices() {
try {
const invoices = await this.invoiceModel.findAll();
if (!invoices) {
throw new HttpException("Invoice not found for this user and cart.", HttpStatus.NOT_FOUND);
}
return { invoices };
} catch (error) {
if (error instanceof HttpException) {
throw error;
}
throw new HttpException("An error occurred while retrieving the invoice.", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
//get user invoices
async getUserInvoices(userId: number) {
try {
if (!userId) {
throw new HttpException("User ID are required.", HttpStatus.BAD_REQUEST);
}
const invoices = await this.invoiceModel.findAll({
where: { userId },
});
if (!invoices) {
throw new HttpException("Invoice not found for this user and cart.", HttpStatus.NOT_FOUND);
}
return { invoices };
} catch (error) {
if (error instanceof HttpException) {
throw error;
}
throw new HttpException("An error occurred while retrieving the invoice.", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
//create invoices from cart
async createInvoiceFromCart(userId: number): Promise<Invoice> {
try {
const invoice = await this.invoiceModel.create({
userId,
totalPaymentAmount: 0,
});
if (!invoice) {
throw new HttpException("Failed to create invoice", HttpStatus.INTERNAL_SERVER_ERROR);
}
return invoice;
} catch (error) {
if (error instanceof HttpException) {
throw error;
}
throw new HttpException("An error occurred while creating the invoice.", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
//update total payment
async updateTotalPayment(userId: number) {
const userCartItems = await this.getUserOpenCart(userId);
if (!userCartItems || !userCartItems.cartItems || userCartItems.cartItems.length === 0) {
throw new HttpException("Cart is empty", HttpStatus.BAD_REQUEST);
}
let invoice = await this.invoiceModel.findOne({ where: { userId, status: "pending" } });
if (!invoice) {
throw new HttpException("Invoice not found", HttpStatus.NOT_FOUND);
}
invoice.totalPaymentAmount = userCartItems.totalPrice;
await invoice.save();
}
//get pending user invoices
async getInvoicePendingByUser(userId: number): Promise<Invoice> {
try {
if (!userId) {
throw new HttpException("User ID are required.", HttpStatus.BAD_REQUEST);
}
const invoice = await this.invoiceModel.findOne({
where: { userId, status: "pending" },
});
if (!invoice) {
throw new HttpException("Invoice not found for this user and cart.", HttpStatus.NOT_FOUND);
}
return invoice;
} catch (error) {
if (error instanceof HttpException) {
throw error;
}
throw new HttpException("An error occurred while retrieving the invoice.", HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}

Loading…
Cancel
Save