Skip to content

Commit 0cff03d

Browse files
authored
Merge pull request #98 from atlp-rwanda/ft-chat
Ft chat
2 parents f85074f + 516da73 commit 0cff03d

17 files changed

+280
-121
lines changed

Diff for: package-lock.json

+23-6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: package.json

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"sequelize-typescript": "^2.1.6",
4848
"sinon": "^18.0.0",
4949
"socket.io": "^4.7.5",
50+
"stripe": "^16.2.0",
5051
"supertest": "^7.0.0",
5152
"swagger-jsdoc": "^6.2.8",
5253
"swagger-ui-express": "^5.0.0",

Diff for: src/controllers/Payment.ts

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import express, { Request, Response } from "express";
2+
import Stripe from "stripe";
3+
import dotenv from "dotenv";
4+
import { findOrderById, findProductById } from "../services/paymentService";
5+
6+
dotenv.config();
7+
8+
const stripe = new Stripe(`${process.env.STRIPE_SECRET_KEY}`);
9+
export const checkout = async (req: Request, res: Response) => {
10+
try {
11+
const orderId = req.params.id;
12+
const order = await findOrderById(orderId);
13+
if (!order) {
14+
return res.status(404).json({ message: "Order not found" });
15+
}
16+
const line_items: any[] = await Promise.all(
17+
order.products.map(async (item: any) => {
18+
const productDetails:any = await findProductById(item.productId);
19+
const unit_amount = Math.round(productDetails!.price * 100);
20+
return {
21+
price_data: {
22+
currency: "usd",
23+
product_data: {
24+
name: productDetails?.name,
25+
images: [productDetails?.image[0]],
26+
},
27+
unit_amount: unit_amount,
28+
},
29+
quantity: item.quantity,
30+
};
31+
})
32+
);
33+
console.log(line_items)
34+
35+
36+
const session = await stripe.checkout.sessions.create({
37+
line_items,
38+
mode: "payment",
39+
success_url: process.env.SUCCESS_PAYMENT_URL,
40+
cancel_url: process.env.CANCEL_PAYMENT_URL,
41+
metadata: {
42+
orderId: orderId,
43+
},
44+
});
45+
46+
47+
res.status(200).json({ url: session.url });
48+
} catch (error: any) {
49+
res.status(500).json({ message: error.message });
50+
}
51+
};
52+
53+
export const webhook = async (req: Request, res: Response) => {
54+
const sig: any = req.headers["stripe-signature"];
55+
const webhookSecret: any = process.env.WEBHOOK_SECRET_KEY;
56+
let event: any;
57+
try {
58+
event = stripe.webhooks.constructEvent(req.body, sig, webhookSecret);
59+
} catch (err: any) {
60+
console.log(`⚠️ Webhook signature verification failed.`, err.message);
61+
return res.status(400).send(`Webhook Error: ${err.message}`);
62+
}
63+
64+
switch (event.type) {
65+
case "checkout.session.completed":
66+
const session = event.data.object;
67+
68+
try {
69+
const lineItems = await stripe.checkout.sessions.listLineItems(
70+
session.id
71+
);
72+
73+
const orderId = session.metadata.orderId;
74+
const order = await findOrderById(orderId);
75+
if (order) {
76+
order.status = "paid";
77+
await order.save();
78+
} else {
79+
console.error("Order not found:", orderId);
80+
}
81+
} catch (err) {
82+
console.error("Error processing session completed event:", err);
83+
}
84+
break;
85+
86+
case "payment_intent.succeeded":
87+
const paymentIntent = event.data.object;
88+
console.log("Payment Intent succeeded: ", paymentIntent);
89+
break;
90+
case "payment_method.attached":
91+
const paymentMethod = event.data.object;
92+
console.log("Payment Method attached: ", paymentMethod);
93+
break;
94+
95+
default:
96+
console.log(`Unhandled event type ${event.type}`);
97+
}
98+
res.json({ received: true });
99+
};

Diff for: src/controllers/cart.controller.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,10 @@ export const getCart = async (req: Request, res: Response) => {
6666
if (!cart) {
6767
return res.status(404).json({ message: "Cart not found" });
6868
}
69-
const cartitem = await CartItem.findAll({ where: { cartId: cart.cartId } });
69+
const cartitem = await CartItem.findAll({ where: { cartId: cart.cartId }, include: {
70+
model: Product,
71+
as: "Product"
72+
} });
7073

7174
return res.status(200).json({ cartitem });
7275
} catch (error: any) {

Diff for: src/controllers/checkout.controller.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { v4 as uuidv4 } from 'uuid';
66

77

88
export const createOrder = async (req: Request, res: Response) => {
9-
const { userId, deliveryAddress, paymentMethod } = req.body;
9+
const { userId, deliveryAddress, paymentMethod,client } = req.body;
1010
if(!userId || !deliveryAddress || !paymentMethod) {
1111
return res.status(400).json({ message: 'All fields are required' })
1212
}
@@ -37,7 +37,8 @@ export const createOrder = async (req: Request, res: Response) => {
3737
paymentMethod,
3838
status: 'pending',
3939
products: orderItems,
40-
totalAmount: totalAmount
40+
totalAmount: totalAmount,
41+
client
4142
});
4243
await CartItem.destroy({ where: { cartId: cart.cartId } });
4344
res.status(201).json({ message: 'Order placed successfully', order });

Diff for: src/controllers/product.controller.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ export const createProduct = async (req: Request, res: Response) => {
4747
category,
4848
expiringDate,
4949
} = req.body;
50+
console.log(image)
5051
if (!name || !image || !description || !price || !quantity || !category) {
5152
return res.status(200).json("All Field are required");
5253
}
@@ -55,11 +56,11 @@ export const createProduct = async (req: Request, res: Response) => {
5556
return res.status(400).json({ message: "Exactly 4 images are required" });
5657
}
5758

58-
const imageArray: string[] = image;
59+
5960

6061
const data = {
6162
name,
62-
images: imageArray,
63+
image: image,
6364
description,
6465
discount: discount ? discount : 0,
6566
price,
@@ -205,6 +206,7 @@ export const deleteProduct = async (req: Request, res: Response) => {
205206
const tokenData = (req as any).token;
206207
const productId = req.params.id;
207208
const { vendorId } = req.body;
209+
console.log(productId)
208210

209211
const permissionCheck: any = await checkVendorModifyPermission(
210212
tokenData,

Diff for: src/controllers/review.controller.ts

-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,6 @@ export const sales_products = async (req: Request, res: Response) => {
167167
}
168168
}
169169
}
170-
171170
return res.status(200).json({ product: product_purchase });
172171
} catch (error:any) {
173172
return res.status(500).json({ message: error.message });

Diff for: src/controllers/vendor.controller.ts

+63
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { Request, Response } from "express";
22
import Vendor from "../database/models/vendor";
33
import { deleteVendorById, saveVendor, updateVendor } from "../services/vendorServices";
44
import User from "../database/models/user";
5+
import Order from "../database/models/order";
6+
import { Op, Sequelize } from "sequelize";
57

68
export const registerVendor = async (req: Request, res: Response) => {
79
const { userId, storeName, address, TIN, bankAccount, paymentDetails } = req.body
@@ -67,6 +69,67 @@ export const editVendor = async (req: Request, res: Response) => {
6769
}
6870
};
6971

72+
export const selectVendorInfo = async(req:Request,res:Response)=>{
73+
try {
74+
const vendor = await Vendor.findOne({where:{userId:req.params.id}});
75+
if(!vendor){
76+
return res.status(404).json({message:'Vendor not found'})
77+
}
78+
res.status(200).json({vendor})
79+
80+
} catch (error) {
81+
res.status(500).json({message: error})
82+
83+
}
84+
}
85+
86+
const getOrdersByVendorId = async (vendorId) => {
87+
try {
88+
const orders = await Order.findAll({
89+
where: {
90+
products: {
91+
[Op.contains]: [{
92+
vendorId: vendorId
93+
}]
94+
}
95+
}
96+
});
97+
return orders;
98+
} catch (error) {
99+
console.error("Error fetching orders:", error);
100+
throw error;
101+
}
102+
};
103+
104+
export const vendorOrder = async (req: Request, res: Response) => {
105+
const { vendorId } = req.params;
106+
107+
try {
108+
// Fetch orders that contain products from the specified vendor
109+
const orders = await Order.findAll({
110+
where: {
111+
products: {
112+
[Op.contains]: [{
113+
vendorId: vendorId
114+
}]
115+
}
116+
}
117+
});
118+
119+
const filteredOrders = orders.map(order => {
120+
const filteredProducts = order.products.filter(product => product.vendorId === vendorId);
121+
return {
122+
...order.toJSON(),
123+
products: filteredProducts
124+
};
125+
});
126+
127+
res.status(200).json(filteredOrders);
128+
} catch (error) {
129+
console.error("Error fetching vendor orders:", error);
130+
res.status(500).json({ error: "Internal Server Error" });
131+
}
132+
};
70133

71134
export const allRequests = async (req: Request, res: Response) => {
72135
try {

0 commit comments

Comments
 (0)