Compare commits

...

4 Commits

Author SHA1 Message Date
fc23e01275 Notification investasi mobile done
### No Issue
2026-01-22 17:53:35 +08:00
20d05c1cc7 component sender wa to all device ( apps & web ) 2026-01-22 11:58:37 +08:00
2c269db250 API – Investment (Admin & User)
- src/app/api/mobile/admin/investment/[id]/route.ts
- src/app/api/mobile/admin/investment/[id]/invoice/route.ts
- src/app/api/mobile/investment/[id]/invoice/route.ts
- src/app/api/mobile/investment/[id]/document/route.ts

Routing Helper
- src/lib/mobile/route-page-mobile.ts

### No Issue
2026-01-21 15:34:19 +08:00
fea94df7bb refactor(invesment): penyesuaian endpoint admin, invoice, dan navigasi mobile
- src/app/api/mobile/admin/investment/[id]/route.ts
- src/app/api/mobile/investment/[id]/invoice/route.ts
- src/app/api/mobile/investment/route.ts
- src/lib/mobile/route-page-mobile.ts

### No Issue
2026-01-20 17:48:42 +08:00
12 changed files with 422 additions and 84 deletions

View File

@@ -2,12 +2,13 @@ import { prisma } from "@/lib";
import { randomOTP } from "@/app_modules/auth/fun/rondom_otp";
import backendLogger from "@/util/backendLogger";
import { NextResponse } from "next/server";
import { sendCodeOtp } from "@/lib/code-otp-sender";
export async function POST(req: Request) {
if (req.method !== "POST") {
return NextResponse.json(
{ success: false, message: "Method Not Allowed" },
{ status: 405 }
{ status: 405 },
);
}
@@ -26,29 +27,21 @@ export async function POST(req: Request) {
if (!createOtpId)
return NextResponse.json(
{ success: false, message: "Gagal mengirim kode OTP" },
{ status: 400 }
{ status: 400 },
);
const msg = `HIPMI%20-%20Kode%20ini%20bersifat%20RAHASIA%20dan%20JANGAN%20DI%20BAGIKAN%20KEPADA%20SIAPAPUN%2C%20termasuk%20anggota%20ataupun%20pengurus%20HIPMI%20lainnya.%5Cn%5Cn%3E%3E%20Kode%20OTP%20anda%3A%20${codeOtp}.`;
// const encodedMsg = encodeURIComponent(msg);
const resSendCode = await sendCodeOtp({
nomor,
codeOtp: codeOtp.toString(),
});
const res = await fetch(
`https://cld-dkr-prod-wajs-server.wibudev.com/api/wa/code?nom=${nomor}&text=${msg}`,
{
cache: "no-cache",
headers: {
Authorization: `Bearer ${process.env.WA_SERVER_TOKEN}`,
},
}
);
if (res.status !== 200)
if (resSendCode.status !== 200)
return NextResponse.json(
{ success: false, message: "Nomor Whatsapp Tidak Aktif" },
{ status: 400 }
{ status: 400 },
);
const sendWa = await res.text();
const sendWa = await resSendCode.text();
console.log("WA Response:", sendWa);
return NextResponse.json(
@@ -57,7 +50,7 @@ export async function POST(req: Request) {
message: "Kode verifikasi terkirim",
kodeId: createOtpId.id,
},
{ status: 200 }
{ status: 200 },
);
} catch (error) {
backendLogger.log("Error Login", error);
@@ -67,7 +60,7 @@ export async function POST(req: Request) {
message: "Terjadi masalah saat login",
reason: error as Error,
},
{ status: 500 }
{ status: 500 },
);
}
}

View File

@@ -1,6 +1,7 @@
import { prisma } from "@/lib";
import { randomOTP } from "@/app_modules/auth/fun/rondom_otp";
import { NextResponse } from "next/server";
import { sendCodeOtp } from "@/lib/code-otp-sender";
export async function POST(req: Request) {
try {
@@ -31,30 +32,21 @@ export async function POST(req: Request) {
if (!createOtpId)
return NextResponse.json(
{ success: false, message: "Gagal mengirim kode OTP" },
{ status: 400 }
{ status: 400 },
);
// const msg = `HIPMI - Kode ini bersifat RAHASIA dan JANGAN DI BAGIKAN KEPAADA SIAPAPUN, termasuk anggota ataupun pengurus HIPMI lainnya.\n\n\n> Kode OTP anda: ${codeOtp}.`;
// const encodedMsg = encodeURIComponent(msg);
const msg = `HIPMI%20-%20Kode%20ini%20bersifat%20RAHASIA%20dan%20JANGAN%20DI%20BAGIKAN%20KEPADA%20SIAPAPUN%2C%20termasuk%20anggota%20ataupun%20pengurus%20HIPMI%20lainnya.%20Kode%20OTP%20anda%3A%20${codeOtp}.`;
const resSendCode = await sendCodeOtp({
nomor,
codeOtp: codeOtp.toString(),
});
const res = await fetch(
`https://cld-dkr-prod-wajs-server.wibudev.com/api/wa/code?nom=${nomor}&text=${msg}`,
{
cache: "no-cache",
headers: {
Authorization: `Bearer ${process.env.WA_SERVER_TOKEN}`,
},
}
);
if (res.status !== 200)
if (resSendCode.status !== 200)
return NextResponse.json(
{ success: false, message: "Nomor Whatsapp Tidak Aktif" },
{ status: 400 }
{ status: 400 },
);
const sendWa = await res.text();
const sendWa = await resSendCode.text();
console.log("WA Response:", sendWa);
return NextResponse.json(
@@ -64,7 +56,7 @@ export async function POST(req: Request) {
kodeId: createOtpId.id,
isAcceptTerms: user.termsOfServiceAccepted,
},
{ status: 200 }
{ status: 200 },
);
} catch (error) {
return NextResponse.json(
@@ -73,7 +65,7 @@ export async function POST(req: Request) {
message: "Terjadi masalah saat login",
reason: error as Error,
},
{ status: 500 }
{ status: 500 },
);
}
}

View File

@@ -2,12 +2,13 @@ import { prisma } from "@/lib";
import { randomOTP } from "@/app_modules/auth/fun/rondom_otp";
import backendLogger from "@/util/backendLogger";
import { NextResponse } from "next/server";
import { sendCodeOtp } from "@/lib/code-otp-sender";
export async function POST(req: Request) {
if (req.method !== "POST") {
return NextResponse.json(
{ success: false, message: "Method Not Allowed" },
{ status: 405 }
{ status: 405 },
);
}
@@ -16,25 +17,18 @@ export async function POST(req: Request) {
const body = await req.json();
const { nomor } = body;
const msg = `HIPMI%20-%20Kode%20ini%20bersifat%20RAHASIA%20dan%20JANGAN%20DI%20BAGIKAN%20KEPADA%20SIAPAPUN%2C%20termasuk%20anggota%20ataupun%20pengurus%20HIPMI%20lainnya.%5Cn%5Cn%3E%3E%20Kode%20OTP%20anda%3A%20${codeOtp}.`;
const resSendCode = await sendCodeOtp({
nomor,
codeOtp: codeOtp.toString(),
});
const res = await fetch(
`https://cld-dkr-prod-wajs-server.wibudev.com/api/wa/code?nom=${nomor}&text=${msg}`,
{
cache: "no-cache",
headers: {
Authorization: `Bearer ${process.env.WA_SERVER_TOKEN}`,
},
}
);
if (res.status !== 200)
if (resSendCode.status !== 200)
return NextResponse.json(
{ success: false, message: "Nomor Whatsapp Tidak Aktif" },
{ status: 400 }
{ status: 400 },
);
const sendWa = await res.text();
const sendWa = await resSendCode.text();
console.log("WA Response:", sendWa);
const createOtpId = await prisma.kodeOtp.create({
@@ -50,7 +44,7 @@ export async function POST(req: Request) {
success: false,
message: "Gagal Membuat Kode OTP",
},
{ status: 400 }
{ status: 400 },
);
return NextResponse.json(
@@ -59,7 +53,7 @@ export async function POST(req: Request) {
message: "Kode Verifikasi Dikirim",
kodeId: createOtpId.id,
},
{ status: 200 }
{ status: 200 },
);
} catch (error) {
backendLogger.error(" Error Resend OTP", error);
@@ -68,7 +62,7 @@ export async function POST(req: Request) {
success: false,
message: "Server Whatsapp Error !!",
},
{ status: 500 }
{ status: 500 },
);
} finally {
await prisma.$disconnect();

View File

@@ -1,5 +1,11 @@
import { NextResponse } from "next/server";
import { prisma } from "@/lib";
import { sendNotificationMobileToOneUser } from "@/lib/mobile/notification/send-notification";
import {
NotificationMobileBodyType,
NotificationMobileTitleType,
} from "../../../../../../../../types/type-mobile-notification";
import { routeUserMobile } from "@/lib/mobile/route-page-mobile";
export { GET, PUT };
@@ -65,19 +71,39 @@ async function PUT(req: Request, { params }: { params: { id: string } }) {
data: {
statusInvoiceId: "4",
},
// select: {
// StatusInvoice: true,
// authorId: true,
// },
select: {
Investasi: {
select: {
title: true,
},
},
authorId: true,
},
});
// SEND NOTIFICAtION
await sendNotificationMobileToOneUser({
recipientId: updt?.authorId as string,
senderId: data?.senderId || "",
payload: {
title: "Transaksi Tertolak" as NotificationMobileTitleType,
body: `Maaf transaksi kamu telah ditolak ! ${updt?.Investasi?.title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "INVESTASI",
deepLink: routeUserMobile.investmentTransaction,
},
});
fixData = updt;
} else if (category === "accept") {
const dataInvestasi: any = await prisma.investasi.findFirst({
const findInvestasi = await prisma.investasi.findFirst({
where: {
id: data.investasiId,
},
select: {
id: true,
title: true,
authorId: true,
totalLembar: true,
sisaLembar: true,
lembarTerbeli: true,
@@ -85,30 +111,33 @@ async function PUT(req: Request, { params }: { params: { id: string } }) {
});
// Hitung TOTAL SISA LEMBAR
const investasi_sisaLembar = Number(dataInvestasi?.sisaLembar);
const investasi_sisaLembar = Number(findInvestasi?.sisaLembar);
const invoice_lembarTerbeli = Number(data.lembarTerbeli);
const resultSisaLembar = investasi_sisaLembar - invoice_lembarTerbeli;
// TAMBAH LEMBAR TERBELI
const investasi_lembarTerbeli = Number(dataInvestasi?.lembarTerbeli);
const investasi_lembarTerbeli = Number(findInvestasi?.lembarTerbeli);
const resultLembarTerbeli =
investasi_lembarTerbeli + invoice_lembarTerbeli;
// Progress
const investasi_totalLembar = Number(dataInvestasi?.totalLembar);
const investasi_totalLembar = Number(findInvestasi?.totalLembar);
const progress = (resultLembarTerbeli / investasi_totalLembar) * 100;
const resultProgres = Number(progress).toFixed(2);
const updt = await prisma.investasi_Invoice.update({
const updateInvoice = await prisma.investasi_Invoice.update({
where: {
id: id,
},
data: {
statusInvoiceId: "1",
},
select: {
authorId: true,
},
});
if (!updt) {
if (!updateInvoice) {
return NextResponse.json(
{
success: false,
@@ -144,7 +173,35 @@ async function PUT(req: Request, { params }: { params: { id: string } }) {
);
}
fixData = updt;
// SEND NOTIFICATION: to investor
await sendNotificationMobileToOneUser({
recipientId: updateInvoice?.authorId as string,
senderId: data?.senderId || "",
payload: {
title: "Transaksi Berhasil" as NotificationMobileTitleType,
body: `Selamat anda menjadi investor pada investasi ${findInvestasi?.title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "INVESTASI",
deepLink: routeUserMobile.investmentTransaction,
},
});
// SEND NOTIFICATION: to creator
await sendNotificationMobileToOneUser({
recipientId: findInvestasi?.authorId as any,
senderId: data?.senderId || "",
payload: {
title: "Ada Investor Baru !" as NotificationMobileTitleType,
body: `Cek daftar investor pada ${findInvestasi?.title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "INVESTASI",
deepLink: routeUserMobile.investmentDetailPublish({
id: findInvestasi?.id as string,
}),
},
});
fixData = updateInvoice;
} else {
return NextResponse.json(
{

View File

@@ -1,11 +1,20 @@
import { NextResponse } from "next/server";
import { prisma } from "@/lib";
import {
sendNotificationMobileToManyUser,
sendNotificationMobileToOneUser,
} from "@/lib/mobile/notification/send-notification";
import { routeUserMobile } from "@/lib/mobile/route-page-mobile";
import {
NotificationMobileBodyType,
NotificationMobileTitleType,
} from "../../../../../../../types/type-mobile-notification";
export { GET, PUT };
async function GET(request: Request, { params }: { params: { id: string } }) {
const { id } = params;
try {
const data = await prisma.investasi.findUnique({
where: {
@@ -78,14 +87,19 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
async function PUT(request: Request, { params }: { params: { id: string } }) {
const { id } = params;
const { data } = await request.json();
const { catatan, senderId } = data;
console.log("[DATA]", data);
console.log("[CATATAN]", catatan);
console.log("[SENDER ID]", senderId);
const { searchParams } = new URL(request.url);
const status = searchParams.get("status");
console.log("[=======Start Investment console=======]");
console.log("[ID]", id);
console.log("[DATA]", data);
console.log("[STATUS]", status);
console.log("[=======End Investment console=======]");
// console.log("[=======Start Investment console=======]");
// console.log("[ID]", id);
// console.log("[STATUS]", status);
// console.log("[=======End Investment console=======]");
const publishTime = new Date();
@@ -96,9 +110,26 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
id: id,
},
data: {
catatan: data,
catatan: catatan,
masterStatusInvestasiId: "4",
},
select: {
authorId: true,
title: true,
},
});
// SEND NOTIFICATION
await sendNotificationMobileToOneUser({
recipientId: updatedData.authorId as any,
senderId: senderId,
payload: {
title: "Pengajuan Review Ditolak",
body: "Mohon perbaiki data sesuai catatan penolakan !",
type: "announcement",
kategoriApp: "INVESTASI",
deepLink: routeUserMobile.investmentPortofolioByStatus({ status: "reject" }),
},
});
console.log("[UPDATE REJECT]", updatedData);
@@ -114,6 +145,39 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
},
});
// SEND NOTIFICAtION
await sendNotificationMobileToOneUser({
recipientId: updatedData.authorId as any,
senderId: senderId,
payload: {
title: "Review Selesai",
body: `Investasi kamu telah dipublikasikan ! ${updatedData.title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "INVESTASI",
deepLink: routeUserMobile.investmentPortofolioByStatus({ status: "publish" }),
},
});
const allUsers = await prisma.user.findMany({
where: {
NOT: { id: updatedData.authorId as any },
active: true,
},
select: { id: true },
});
await sendNotificationMobileToManyUser({
recipientIds: allUsers.map((user) => user.id),
senderId: senderId,
payload: {
title: "Ayo Cek Investasi Terbaru" as NotificationMobileTitleType,
body: `${updatedData.title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "INVESTASI",
deepLink: routeUserMobile.investmentDetailPublish({ id: id }),
},
});
console.log("[UPDATE PUBLISH]", updatedData);
}

View File

@@ -1,5 +1,11 @@
import { NextResponse } from "next/server";
import { prisma } from "@/lib";
import { sendNotificationMobileToManyUser } from "@/lib/mobile/notification/send-notification";
import {
NotificationMobileBodyType,
NotificationMobileTitleType,
} from "../../../../../../../types/type-mobile-notification";
import { routeAdminMobile, routeUserMobile } from "@/lib/mobile/route-page-mobile";
export { POST, GET, DELETE };
@@ -10,7 +16,7 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
console.log("[POST DOCUMENT DATA]", data);
try {
const create = await prisma.dokumenInvestasi.upsert({
const createdDocs = await prisma.dokumenInvestasi.upsert({
where: {
id: id,
},
@@ -23,9 +29,49 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
title: data.title,
fileId: data.fileId,
},
select: {
investasiId: true,
investasi: {
select: {
title: true,
authorId: true,
},
},
},
});
if (!create)
console.log("[CREATED DOCS]", createdDocs);
const findInvestor = await prisma.investasi_Invoice.findMany({
where: {
investasiId: id,
StatusInvoice: {
name: "Berhasil",
},
},
select: {
authorId: true,
},
});
console.log("[FIND INVESTOR]", findInvestor);
// SEND NOTIFICATION
await sendNotificationMobileToManyUser({
recipientIds: findInvestor.map((e) => e.authorId!),
senderId: createdDocs.investasi?.authorId as string,
payload: {
title: "Cek Dokumen" as NotificationMobileTitleType,
body: `Ada dokumen terupdate pada ${createdDocs.investasi?.title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "INVESTASI",
deepLink: routeUserMobile.investmentDetailPublish({
id: createdDocs.investasiId as string,
}),
},
});
if (!createdDocs)
return NextResponse.json({
status: 201,
success: true,
@@ -93,7 +139,7 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
async function DELETE(
request: Request,
{ params }: { params: { id: string } }
{ params }: { params: { id: string } },
) {
const { id } = params;
@@ -111,9 +157,9 @@ async function DELETE(
headers: {
Authorization: `Bearer ${process.env.WS_APIKEY}`,
},
}
},
);
return NextResponse.json({
status: 200,
success: true,

View File

@@ -1,6 +1,12 @@
import { prisma } from "@/lib";
import { sendNotificationMobileToManyUser } from "@/lib/mobile/notification/send-notification";
import { routeAdminMobile } from "@/lib/mobile/route-page-mobile";
import _ from "lodash";
import { NextResponse } from "next/server";
import {
NotificationMobileTitleType,
NotificationMobileBodyType,
} from "../../../../../../../types/type-mobile-notification";
export { POST, GET, PUT };
@@ -49,7 +55,6 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
const authorId = searchParams.get("authorId");
console.log("[ID INVOICE]", id);
let fixData;
@@ -198,8 +203,49 @@ async function PUT(request: Request, { params }: { params: { id: string } }) {
statusInvoiceId: checkStatus.id,
imageId: data.imageId,
},
select: {
investasiId: true,
},
});
if (fixStatus === "Proses") {
// kirim notif ke author investasi
const findInvestasi = await prisma.investasi.findUnique({
where: {
id: update.investasiId as any,
},
select: {
title: true,
authorId: true,
},
});
const findUsers = await prisma.user.findMany({
where: {
masterUserRoleId: "2",
active: true,
NOT: { id: findInvestasi?.authorId as any },
},
select: { id: true },
});
// SEND NOTIFICATION
await sendNotificationMobileToManyUser({
recipientIds: findUsers.map((user) => user.id),
senderId: data.authorId,
payload: {
title: "Ada Investor Baru !" as NotificationMobileTitleType,
body: `Cek data investor pada ${findInvestasi?.title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "INVESTASI",
deepLink: routeAdminMobile.investmentDetailPublish({
id: update.investasiId as string,
status: "publish",
}),
},
});
}
console.log("[UPDATE]", update);
return NextResponse.json({

View File

@@ -1,6 +1,7 @@
import _ from "lodash";
import { prisma } from "@/lib";
import { NextResponse } from "next/server";
import { sendNotificationInvestmentAddNews } from "@/lib/mobile/notification/notification-add-news-investment";
export { POST, GET, DELETE };
@@ -21,6 +22,21 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
deskripsi: data.deskripsi,
imageId: data.imageId,
},
select: {
investasiId: true,
investasi: {
select: {
title: true,
authorId: true,
},
},
},
});
await sendNotificationInvestmentAddNews({
invesmentId: createWithFile.investasiId,
senderId: createWithFile.investasi.authorId as string,
title: createWithFile.investasi.title,
});
fixData = createWithFile;
@@ -31,6 +47,21 @@ async function POST(request: Request, { params }: { params: { id: string } }) {
title: _.startCase(data.title),
deskripsi: data.deskripsi,
},
select: {
investasiId: true,
investasi: {
select: {
title: true,
authorId: true,
},
},
},
});
await sendNotificationInvestmentAddNews({
invesmentId: createWitOutFile.investasiId,
senderId: createWitOutFile.investasi.authorId as string,
title: createWitOutFile.investasi.title,
});
fixData = createWitOutFile;
@@ -111,7 +142,7 @@ async function GET(request: Request, { params }: { params: { id: string } }) {
async function DELETE(
request: Request,
{ params }: { params: { id: string } }
{ params }: { params: { id: string } },
) {
const { id } = params;
console.log("id", id);

View File

@@ -2,6 +2,9 @@ import _ from "lodash";
import { NextResponse } from "next/server";
import prisma from "@/lib/prisma";
import moment from "moment";
import { sendNotificationMobileToManyUser } from "@/lib/mobile/notification/send-notification";
import { NotificationMobileBodyType } from "../../../../../types/type-mobile-notification";
import { routeAdminMobile } from "@/lib/mobile/route-page-mobile";
export { POST, GET };
@@ -9,12 +12,14 @@ async function POST(request: Request) {
const { data } = await request.json();
console.log(["DATA INVESTASI"], data);
const fixTitle = _.startCase(data.title)
try {
const create = await prisma.investasi.create({
data: {
masterStatusInvestasiId: "2",
authorId: data.authorId,
title: _.startCase(data.title),
title: fixTitle,
targetDana: data.targetDana,
hargaLembar: data.hargaLembar,
totalLembar: data.totalLembar,
@@ -30,6 +35,24 @@ async function POST(request: Request) {
console.log("[CREATE INVESTASI]", create);
const adminUsers = await prisma.user.findMany({
where: { masterUserRoleId: "2", NOT: { id: data.authorId } },
select: { id: true },
});
// SEND NOTIFICATION
await sendNotificationMobileToManyUser({
recipientIds: adminUsers.map((user) => user.id),
senderId: data.authorId,
payload: {
title: "Pengajuan Review Baru",
body: fixTitle as NotificationMobileBodyType,
type: "announcement",
deepLink: routeAdminMobile.investmentByStatus({ status: "review" }),
kategoriApp: "INVESTASI",
},
});
return NextResponse.json({
status: 201,
success: true,

View File

@@ -0,0 +1,28 @@
const sendCodeOtp = async ({
nomor,
codeOtp,
}: {
nomor: string;
codeOtp: string;
}) => {
const msg = `HIPMI%20-%20Kode%20ini%20bersifat%20RAHASIA%20dan%20JANGAN%20DI%20BAGIKAN%20KEPADA%20SIAPAPUN%2C%20termasuk%20anggota%20ataupun%20pengurus%20HIPMI%20lainnya.%20Kode%20OTP%20anda%3A%20${codeOtp}.`;
const res = await fetch(
`https://cld-dkr-prod-wajs-server.wibudev.com/api/wa/code?nom=${nomor}&text=${msg}`,
{
cache: "no-cache",
headers: {
Authorization: `Bearer ${process.env.WA_SERVER_TOKEN}`,
},
},
);
// const res = await fetch(
// `https://wa.wibudev.com/code?nom=${nomor}&text=HIPMI - Kode ini bersifat RAHASIA dan JANGAN DI BAGIKAN KEPADA SIAPAPUN, termasuk anggota ataupun pengurus HIPMI lainnya.
// \n
// >> Kode OTP anda: ${codeOtp}.
// `,
// );
return res;
};
export { sendCodeOtp };

View File

@@ -0,0 +1,46 @@
import {
NotificationMobileBodyType,
NotificationMobileTitleType,
} from "../../../../types/type-mobile-notification";
import { sendNotificationMobileToManyUser } from "./send-notification";
import { routeUserMobile } from "../route-page-mobile";
import prisma from "@/lib/prisma";
export const sendNotificationInvestmentAddNews = async ({
invesmentId,
senderId,
title,
}: {
invesmentId: string;
senderId: string;
title: string;
}) => {
const findInvestor = await prisma.investasi_Invoice.findMany({
where: {
investasiId: invesmentId,
StatusInvoice: {
name: "Berhasil",
},
},
select: {
authorId: true,
},
});
console.log("[FIND INVESTOR]", findInvestor);
// SEND NOTIFICATION
await sendNotificationMobileToManyUser({
recipientIds: findInvestor.map((e) => e.authorId!),
senderId: senderId,
payload: {
title: "Berita terbaru" as NotificationMobileTitleType,
body: `Ada berita yang terupdate pada ${title}` as NotificationMobileBodyType,
type: "announcement",
kategoriApp: "INVESTASI",
deepLink: routeUserMobile.investmentDetailPublish({
id: invesmentId,
}),
},
});
};

View File

@@ -19,6 +19,16 @@ const routeAdminMobile = {
// FORUM
forumPreviewReportPosting: `/admin/forum/report-posting`,
forumPreviewReportComment: `/admin/forum/report-comment`,
// INVESTMENT
investmentByStatus: ({ status }: { status: StatusApp }) => `/admin/investment/${status}/status`,
investmentDetailPublish: ({
id,
status,
}: {
id: string;
status: StatusApp;
}) => `/admin/investment/${id}/${status}`,
};
const routeUserMobile = {
@@ -41,6 +51,14 @@ const routeUserMobile = {
// FORUM
forumBeranda: `/forum`,
forumDetail: ({ id }: { id: string }) => `/forum/${id}`,
forumPreviewReportPosting: ({ id }: { id: string }) => `/forum/${id}/preview-report-posting`,
forumPreviewReportComment: ({ id }: { id: string }) => `/forum/${id}/preview-report-comment`,
forumPreviewReportPosting: ({ id }: { id: string }) =>
`/forum/${id}/preview-report-posting`,
forumPreviewReportComment: ({ id }: { id: string }) =>
`/forum/${id}/preview-report-comment`,
// INVESTMENT
investmentPortofolioByStatus: ({ status }: { status?: StatusApp }) =>
`/investment/(tabs)/portofolio?status=${status}`,
investmentDetailPublish: ({ id }: { id: string }) => `/investment/${id}`,
investmentTransaction: `/investment/(tabs)/transaction`
};