mirror of
https://github.com/i701/sarlink-portal.git
synced 2025-07-03 06:48:21 +00:00
refactor: update payment types and user interface, enhance error handling, and adjust API base URL
Some checks failed
Build and Push Docker Images / Build and Push Docker Images (push) Failing after 3m14s
Some checks failed
Build and Push Docker Images / Build and Push Docker Images (push) Failing after 3m14s
This commit is contained in:
@ -1,29 +1,146 @@
|
||||
"use server";
|
||||
|
||||
import type { PaymentType } from "@/lib/types";
|
||||
import { formatMacAddress } from "@/lib/utils";
|
||||
import { authOptions } from "@/app/auth";
|
||||
import type { ApiResponse, NewPayment, Payment } from "@/lib/backend-types";
|
||||
import type { User } from "@/lib/types/user";
|
||||
import { tryCatch } from "@/utils/tryCatch";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { revalidatePath } from "next/cache";
|
||||
import { redirect } from "next/navigation";
|
||||
import { addDevicesToGroup } from "./omada-actions";
|
||||
|
||||
export async function createPayment(data: PaymentType) {
|
||||
export async function createPayment(data: NewPayment) {
|
||||
const session = await getServerSession(authOptions);
|
||||
console.log("data", data);
|
||||
// const payment = await prisma.payment.create({
|
||||
// data: {
|
||||
// amount: data.amount,
|
||||
// numberOfMonths: data.numberOfMonths,
|
||||
// paid: data.paid,
|
||||
// userId: data.userId,
|
||||
// devices: {
|
||||
// connect: data.deviceIds.map((id) => {
|
||||
// return {
|
||||
// id,
|
||||
// };
|
||||
// }),
|
||||
// },
|
||||
// },
|
||||
// });
|
||||
// redirect(`/payments/${payment.id}`);
|
||||
const response = await fetch(
|
||||
`${
|
||||
process.env.SARLINK_API_BASE_URL // });
|
||||
}/api/billing/payment/`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Token ${session?.apiToken}`,
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
},
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json();
|
||||
// Throw an error with the message from the API
|
||||
throw new Error(errorData.message || "Something went wrong.");
|
||||
}
|
||||
const payment = (await response.json()) as Payment;
|
||||
revalidatePath("/devices");
|
||||
redirect(`/payments/${payment.id}`);
|
||||
}
|
||||
|
||||
export async function getPayment({ id }: { id: string }) {
|
||||
const session = await getServerSession(authOptions);
|
||||
const response = await fetch(
|
||||
`${process.env.SARLINK_API_BASE_URL}/api/billing/payment/${id}`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Token ${session?.apiToken}`,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json();
|
||||
// Throw an error with the message from the API
|
||||
throw new Error(errorData.message || "Something went wrong.");
|
||||
}
|
||||
const payment = (await response.json()) as Payment;
|
||||
return payment;
|
||||
}
|
||||
|
||||
export async function getPayments() {
|
||||
const session = await getServerSession(authOptions);
|
||||
const respose = await fetch(
|
||||
`${process.env.SARLINK_API_BASE_URL}/api/billing/payment/`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Token ${session?.apiToken}`,
|
||||
},
|
||||
},
|
||||
);
|
||||
const data = (await respose.json()) as ApiResponse<Payment>;
|
||||
return data;
|
||||
}
|
||||
|
||||
type UpdatePayment = Pick<
|
||||
Payment,
|
||||
"id" | "paid" | "paid_at" | "method" | "number_of_months"
|
||||
>;
|
||||
export async function updatePayment({
|
||||
id,
|
||||
method,
|
||||
paid,
|
||||
paid_at,
|
||||
number_of_months,
|
||||
}: UpdatePayment) {
|
||||
const session = await getServerSession(authOptions);
|
||||
const response = await fetch(
|
||||
`${process.env.SARLINK_API_BASE_URL}/api/billing/payment/${id}/update/`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Token ${session?.apiToken}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
method,
|
||||
paid,
|
||||
paid_at,
|
||||
number_of_months,
|
||||
}),
|
||||
},
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json();
|
||||
// Throw an error with the message from the API
|
||||
throw new Error(errorData.message || "Something went wrong.");
|
||||
}
|
||||
const payment = (await response.json()) as Payment;
|
||||
return payment;
|
||||
}
|
||||
|
||||
type TUpdateWalletBalance = Pick<User, "id" | "wallet_balance">;
|
||||
export async function updateWalletBalance({
|
||||
id,
|
||||
wallet_balance,
|
||||
}: TUpdateWalletBalance) {
|
||||
const session = await getServerSession(authOptions);
|
||||
console.log("wallet bal in server action", wallet_balance);
|
||||
const response = await fetch(
|
||||
`${process.env.SARLINK_API_BASE_URL}/api/auth/update-wallet/${id}/`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Token ${session?.apiToken}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
wallet_balance: Number.parseFloat(wallet_balance?.toFixed(2) ?? "0"),
|
||||
}),
|
||||
},
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json();
|
||||
// Throw an error with the message from the API
|
||||
throw new Error(errorData.message || "Something went wrong.");
|
||||
}
|
||||
const message = (await response.json()) as {
|
||||
message: "Wallet balance updated successfully.";
|
||||
};
|
||||
return message;
|
||||
}
|
||||
|
||||
type VerifyPaymentType = {
|
||||
@ -43,45 +160,45 @@ class InsufficientFundsError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
async function processWalletPayment(
|
||||
user: { id: string; walletBalance: number } | null,
|
||||
payment: PaymentWithDevices | null,
|
||||
amount: number,
|
||||
) {
|
||||
if (!user || !payment) {
|
||||
export async function processWalletPayment({
|
||||
payment,
|
||||
amount,
|
||||
}: { payment: Payment | undefined; amount: number }) {
|
||||
const session = await getServerSession(authOptions);
|
||||
if (!session?.user || !payment) {
|
||||
throw new Error("User or payment not found");
|
||||
}
|
||||
|
||||
const walletBalance = user.walletBalance ?? 0;
|
||||
const walletBalance = session.user.wallet_balance ?? 0;
|
||||
if (walletBalance < amount) {
|
||||
throw new InsufficientFundsError();
|
||||
}
|
||||
|
||||
const expiryDate = new Date();
|
||||
expiryDate.setMonth(expiryDate.getMonth() + payment.numberOfMonths);
|
||||
await prisma.$transaction([
|
||||
prisma.payment.update({
|
||||
where: { id: payment.id },
|
||||
data: {
|
||||
paid: true,
|
||||
paidAt: new Date(),
|
||||
method: "WALLET",
|
||||
devices: {
|
||||
updateMany: payment.devices.map((device) => ({
|
||||
where: { id: device.id },
|
||||
data: {
|
||||
isActive: true,
|
||||
expiryDate: expiryDate,
|
||||
},
|
||||
})),
|
||||
},
|
||||
},
|
||||
const [updatePaymentError, _] = await tryCatch(
|
||||
updatePayment({
|
||||
id: payment.id,
|
||||
method: "WALLET",
|
||||
paid: true,
|
||||
paid_at: new Date().toISOString(),
|
||||
number_of_months: payment.number_of_months,
|
||||
}),
|
||||
prisma.user.update({
|
||||
where: { id: user.id },
|
||||
data: { walletBalance: walletBalance - amount },
|
||||
);
|
||||
if (updatePaymentError) {
|
||||
throw new Error(updatePaymentError.message);
|
||||
}
|
||||
console.log("Wallet balance before update:", walletBalance);
|
||||
const updated_balance = walletBalance - amount;
|
||||
const [walletUpdateError, response] = await tryCatch(
|
||||
updateWalletBalance({
|
||||
id: session.user.id,
|
||||
wallet_balance: Number.parseFloat(updated_balance?.toFixed(2) ?? "0"),
|
||||
}),
|
||||
]);
|
||||
);
|
||||
if (walletUpdateError) {
|
||||
throw new Error(walletUpdateError.message);
|
||||
}
|
||||
revalidatePath("/payments/[paymentsId]", "page");
|
||||
return response;
|
||||
}
|
||||
|
||||
type VerifyPaymentResponse =
|
||||
@ -99,98 +216,98 @@ type VerifyPaymentResponse =
|
||||
};
|
||||
};
|
||||
|
||||
async function verifyExternalPayment(
|
||||
data: VerifyPaymentType,
|
||||
payment: PaymentWithDevices | null,
|
||||
): Promise<VerifyPaymentResponse> {
|
||||
console.log("payment verify data ->", data);
|
||||
const response = await fetch(
|
||||
"https://verifypaymentsapi.baraveli.dev/verify-payment",
|
||||
{
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(data),
|
||||
},
|
||||
);
|
||||
// async function verifyExternalPayment(
|
||||
// data: VerifyPaymentType,
|
||||
// payment: PaymentWithDevices | null,
|
||||
// ): Promise<VerifyPaymentResponse> {
|
||||
// console.log("payment verify data ->", data);
|
||||
// const response = await fetch(
|
||||
// "https://verifypaymentsapi.baraveli.dev/verify-payment",
|
||||
// {
|
||||
// method: "POST",
|
||||
// headers: { "Content-Type": "application/json" },
|
||||
// body: JSON.stringify(data),
|
||||
// },
|
||||
// );
|
||||
|
||||
const json = await response.json();
|
||||
console.log(json);
|
||||
if (!payment) {
|
||||
throw new Error("Payment verification failed or payment not found");
|
||||
}
|
||||
// const json = await response.json();
|
||||
// console.log(json);
|
||||
// if (!payment) {
|
||||
// throw new Error("Payment verification failed or payment not found");
|
||||
// }
|
||||
|
||||
if (json.success) {
|
||||
const expiryDate = new Date();
|
||||
expiryDate.setMonth(expiryDate.getMonth() + payment.numberOfMonths);
|
||||
await prisma.payment.update({
|
||||
where: { id: payment.id },
|
||||
data: {
|
||||
paid: true,
|
||||
paidAt: new Date(),
|
||||
method: "TRANSFER",
|
||||
devices: {
|
||||
updateMany: payment.devices.map((device) => ({
|
||||
where: { id: device.id },
|
||||
data: {
|
||||
isActive: true,
|
||||
expiryDate: expiryDate,
|
||||
},
|
||||
})),
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
// if (json.success) {
|
||||
// const expiryDate = new Date();
|
||||
// expiryDate.setMonth(expiryDate.getMonth() + payment.numberOfMonths);
|
||||
// await prisma.payment.update({
|
||||
// where: { id: payment.id },
|
||||
// data: {
|
||||
// paid: true,
|
||||
// paidAt: new Date(),
|
||||
// method: "TRANSFER",
|
||||
// devices: {
|
||||
// updateMany: payment.devices.map((device) => ({
|
||||
// where: { id: device.id },
|
||||
// data: {
|
||||
// isActive: true,
|
||||
// expiryDate: expiryDate,
|
||||
// },
|
||||
// })),
|
||||
// },
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
|
||||
return json;
|
||||
}
|
||||
// return json;
|
||||
// }
|
||||
|
||||
async function updateDevices(payment: PaymentWithDevices | null) {
|
||||
if (!payment) return;
|
||||
// async function updateDevices(payment: PaymentWithDevices | null) {
|
||||
// if (!payment) return;
|
||||
|
||||
const newDevices = payment.devices.map((d) => ({
|
||||
name: d.name,
|
||||
macAddress: formatMacAddress(d.mac),
|
||||
}));
|
||||
// const newDevices = payment.devices.map((d) => ({
|
||||
// name: d.name,
|
||||
// macAddress: formatMacAddress(d.mac),
|
||||
// }));
|
||||
|
||||
return await addDevicesToGroup({
|
||||
groupId: process.env.OMADA_GROUP_ID,
|
||||
siteId: process.env.OMADA_SITE_ID,
|
||||
newDevices,
|
||||
});
|
||||
}
|
||||
// return await addDevicesToGroup({
|
||||
// groupId: process.env.OMADA_GROUP_ID,
|
||||
// siteId: process.env.OMADA_SITE_ID,
|
||||
// newDevices,
|
||||
// });
|
||||
// }
|
||||
|
||||
export async function verifyPayment(data: VerifyPaymentType) {
|
||||
try {
|
||||
const [payment, user] = await Promise.all([
|
||||
prisma.payment.findUnique({
|
||||
where: { id: data.paymentId },
|
||||
include: { devices: true },
|
||||
}),
|
||||
prisma.user.findUnique({
|
||||
where: { id: data.userId },
|
||||
}),
|
||||
]);
|
||||
// export async function verifyPayment(data: VerifyPaymentType) {
|
||||
// try {
|
||||
// const [payment, user] = await Promise.all([
|
||||
// prisma.payment.findUnique({
|
||||
// where: { id: data.paymentId },
|
||||
// include: { devices: true },
|
||||
// }),
|
||||
// prisma.user.findUnique({
|
||||
// where: { id: data.userId },
|
||||
// }),
|
||||
// ]);
|
||||
|
||||
if (data.type === "WALLET") {
|
||||
console.log("WALLET");
|
||||
await processWalletPayment(user, payment, Number(data.absAmount));
|
||||
redirect("/payments");
|
||||
}
|
||||
if (data.type === "TRANSFER") {
|
||||
console.log({ data, payment });
|
||||
const verificationResult = await verifyExternalPayment(data, payment);
|
||||
await updateDevices(payment);
|
||||
// if (data.type === "WALLET") {
|
||||
// console.log("WALLET");
|
||||
// await processWalletPayment(user, payment, Number(data.absAmount));
|
||||
// redirect("/payments");
|
||||
// }
|
||||
// if (data.type === "TRANSFER") {
|
||||
// console.log({ data, payment });
|
||||
// const verificationResult = await verifyExternalPayment(data, payment);
|
||||
// await updateDevices(payment);
|
||||
|
||||
revalidatePath("/payment[paymentId]");
|
||||
// revalidatePath("/payment[paymentId]");
|
||||
|
||||
return verificationResult;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Payment verification failed:", error);
|
||||
throw error; // Re-throw to handle at a higher level
|
||||
}
|
||||
}
|
||||
// return verificationResult;
|
||||
// }
|
||||
// } catch (error) {
|
||||
// console.error("Payment verification failed:", error);
|
||||
// throw error; // Re-throw to handle at a higher level
|
||||
// }
|
||||
// }
|
||||
|
||||
export async function addDevicesToOmada() {
|
||||
console.log("hi");
|
||||
}
|
||||
// export async function addDevicesToOmada() {
|
||||
// console.log("hi");
|
||||
// }
|
||||
|
Reference in New Issue
Block a user