Compare commits

..

16 Commits

Author SHA1 Message Date
6fb6ab9750 upd: update data pengajuan surat 2025-12-15 15:45:29 +08:00
11a78d7371 upd: update edit pengajuan surat 2025-12-15 14:22:37 +08:00
3baba059ab upd: api update 2025-12-15 12:17:59 +08:00
dcd072034c upd: api update pelayanan pengajuan surat 2025-12-15 11:32:02 +08:00
ee27813da7 upd: update pengajuan surat 2025-12-12 17:32:22 +08:00
29f6ecfd23 upd: api update 2025-12-12 15:13:32 +08:00
d6882d4b3a upd: api update pelayanan surat 2025-12-12 15:08:09 +08:00
286c989bcf upd: api jenna ai
deskripsi:
- update pelayanan surat

No Issues:
2025-12-12 14:41:20 +08:00
031e408640 Merge pull request 'upd: api jenna ai' (#75) from amalia/11-des-25 into main
Reviewed-on: http://wibugit.wibudev.com/wibu/jenna-mcp/pulls/75
2025-12-11 17:06:29 +08:00
c797d1fc46 upd: api jenna ai
Deskripsi:
- detail post pengaduan
- detail post pengajuan surat

No Issues
2025-12-11 17:05:53 +08:00
6f6905a414 Merge pull request 'amalia/11-des-25' (#74) from amalia/11-des-25 into main
Reviewed-on: http://wibugit.wibudev.com/wibu/jenna-mcp/pulls/74
2025-12-11 14:19:34 +08:00
91e5f6a77e upd: console data 2025-12-11 14:18:43 +08:00
3f567b57b2 upd: detail api
Deskripsi
- detail pengaduan by nomer pengaduan
- detail pengajuan surat by nomer pengajuan

No Issues
2025-12-11 14:16:31 +08:00
c98cfd21ce Merge pull request 'upd: list pengaduan dan list pelayanan surat api jenna ai' (#73) from amalia/11-des-25 into main
Reviewed-on: http://wibugit.wibudev.com/wibu/jenna-mcp/pulls/73
2025-12-11 12:05:02 +08:00
fdf7b0a13f upd: list pengaduan dan list pelayanan surat api jenna ai 2025-12-11 12:04:16 +08:00
d76a702d2d Merge pull request 'upd: api pelayanan' (#72) from amalia/10-des-25 into main
Reviewed-on: http://wibugit.wibudev.com/wibu/jenna-mcp/pulls/72
2025-12-10 17:25:04 +08:00
4 changed files with 542 additions and 43 deletions

View File

@@ -343,16 +343,19 @@ function DetailDataPengajuan({ data, syaratDokumen, dataText, onAction }: { data
Setujui
</Button>
</Group>
) : (
<Group justify="center" grow>
<Button
variant="light"
onClick={() => setOpenedPreview(!openedPreview)}
>
Surat
</Button>
</Group>
)
) :
data?.status === "selesai" ?
(
<Group justify="center" grow>
<Button
variant="light"
onClick={() => setOpenedPreview(!openedPreview)}
>
Surat
</Button>
</Group>
)
: <></>
}
</Grid.Col>
</Grid>

View File

@@ -70,7 +70,7 @@ export default function DetailPengaduanPage() {
);
}
function DetailDataPengaduan({ data, onAction }: { data: any, onAction: () => void }) {
function DetailDataPengaduan({ data, onAction }: { data: any | null, onAction: () => void }) {
const [opened, { open, close }] = useDisclosure(false);
const [catModal, setCatModal] = useState<"tolak" | "terima">("tolak");
const [openedPreview, setOpenedPreview] = useState(false);

View File

@@ -104,8 +104,9 @@ const PelayananRoute = new Elysia({
// --- PELAYANAN SURAT ---
.get("/", async ({ query }) => {
const { phone } = query
.get("/", async ({ query, headers }) => {
// const { phone } = query
const phone = headers['x-phone'] || ""
const data = await prisma.pelayananAjuan.findMany({
orderBy: {
createdAt: "asc"
@@ -115,13 +116,34 @@ const PelayananRoute = new Elysia({
Warga: {
phone
}
},
select: {
noPengajuan: true,
status: true,
createdAt: true,
CategoryPelayanan: {
select: {
name: true
}
}
}
})
return data
const dataFix = data.map((item) => {
return {
noPengajuan: item.noPengajuan,
status: item.status,
category: item.CategoryPelayanan.name,
createdAt: item.createdAt.toLocaleDateString("id-ID", { day: "numeric", month: "long", year: "numeric" }),
}
})
return dataFix
}, {
query: t.Object({
phone: t.String({ minLength: 1, error: "phone harus diisi" }),
}),
// query: t.Object({
// phone: t.String({ minLength: 1, error: "phone harus diisi" }),
// }),
detail: {
summary: "List Ajuan Pelayanan Surat by Phone",
description: `tool untuk mendapatkan list ajuan pelayanan surat`,
@@ -130,17 +152,9 @@ const PelayananRoute = new Elysia({
})
.get("/detail", async ({ query }) => {
const { id } = query
const data = await prisma.pelayananAjuan.findFirst({
where: {
OR: [
{
noPengajuan: id
},
{
id: id
}
]
id: id
},
select: {
id: true,
@@ -170,6 +184,17 @@ const PelayananRoute = new Elysia({
}
})
if (!data) {
const datafix = {
pengajuan: {},
history: [],
warga: {},
syaratDokumen: [],
dataText: [],
}
return datafix
}
const dataSurat = await prisma.suratPelayanan.findFirst({
where: {
idPengajuanLayanan: data?.id,
@@ -280,15 +305,15 @@ const PelayananRoute = new Elysia({
syaratDokumen: dataSyaratFix,
dataText: dataTextFix,
}
return datafix
}, {
query: t.Object({
id: t.String({ minLength: 1, error: "id harus diisi" }),
}),
detail: {
summary: "Detail Ajuan Pelayanan Surat",
description: `tool untuk mendapatkan detail ajuan pelayanan surat`,
tags: ["mcp"]
summary: "Detail Ajuan Pelayanan Surat by ID",
description: `tool untuk mendapatkan detail ajuan pelayanan surat berdasarkan id`,
}
})
.post("/create", async ({ body, headers }) => {
@@ -481,6 +506,171 @@ const PelayananRoute = new Elysia({
tags: ["mcp"]
}
})
.post("/detail-data", async ({ body }) => {
const { nomerPengajuan } = body
const data = await prisma.pelayananAjuan.findFirst({
where: {
noPengajuan: nomerPengajuan
},
select: {
id: true,
noPengajuan: true,
status: true,
createdAt: true,
updatedAt: true,
CategoryPelayanan: {
select: {
name: true,
dataText: true,
syaratDokumen: true,
}
},
Warga: {
select: {
name: true,
phone: true,
_count: {
select: {
Pengaduan: true,
PelayananAjuan: true,
}
}
}
},
}
})
if (!data) {
return { success: false, message: "Data tidak ditemukan" }
}
const dataSurat = await prisma.suratPelayanan.findFirst({
where: {
idPengajuanLayanan: data?.id,
isActive: true
},
select: {
id: true,
idCategory: true,
}
})
const dataSyarat = await prisma.syaratDokumenPelayanan.findMany({
where: {
idPengajuanLayanan: data?.id,
isActive: true
},
select: {
id: true,
jenis: true,
value: true,
}
})
const dataText = await prisma.dataTextPelayanan.findMany({
where: {
idPengajuanLayanan: data?.id,
isActive: true
},
select: {
id: true,
value: true,
jenis: true,
}
})
const syaratDokumen = (data?.CategoryPelayanan?.syaratDokumen ?? []) as {
name: string;
desc: string;
}[];
const dataSyaratFix = dataSyarat.map((item) => {
// const desc = syaratDokumen.find((v) => v.name == item.jenis)?.desc
return {
id: item.id,
jenis: item.jenis,
value: item.value,
}
})
const dataTextFix = dataText.map((item) => {
// const desc = data?.CategoryPelayanan?.dataText.find((v) => v == item.jenis)
return {
id: item.id,
jenis: item.jenis,
value: item.value,
}
})
const dataHistory = await prisma.historyPelayanan.findMany({
where: {
idPengajuanLayanan: data?.id,
},
select: {
id: true,
deskripsi: true,
status: true,
createdAt: true,
idUser: true,
User: {
select: {
name: true,
}
}
}
})
const dataHistoryFix = dataHistory.map((item) => {
return {
id: item.id,
deskripsi: item.deskripsi,
status: item.status,
createdAt: item.createdAt,
idUser: item.idUser,
nameUser: item.User?.name,
}
})
const warga = {
name: data?.Warga?.name,
phone: data?.Warga?.phone,
pengaduan: data?.Warga?._count.Pengaduan,
pelayanan: data?.Warga?._count.PelayananAjuan,
}
const dataPengajuan = {
id: data?.id,
noPengajuan: data?.noPengajuan,
category: data?.CategoryPelayanan.name,
status: data?.status,
createdAt: data?.createdAt,
updatedAt: data?.updatedAt,
idSurat: dataSurat?.id,
}
const datafix = {
pengajuan: dataPengajuan,
history: dataHistoryFix,
warga: warga,
syaratDokumen: dataSyaratFix,
dataText: dataTextFix,
}
return datafix
}, {
body: t.Object({
nomerPengajuan: t.String({
description: "Nomor pengajuan pelayanan surat yang ingin diakses.",
examples: ["PS-101225-001", "PS-101225-002"],
error: "Nomor pengajuan harus diisi"
})
}),
detail: {
summary: "Detail Pengajuan Pelayanan Surat By Nomor Pengajuan",
description: `tool untuk mendapatkan detail pengajuan pelayanan surat berdasarkan nomor pengajuan`,
tags: ["mcp"]
}
})
.post("/update-status", async ({ body }) => {
const { id, status, keterangan, idUser, noSurat } = body
let deskripsi = ""
@@ -538,6 +728,199 @@ const PelayananRoute = new Elysia({
detail: {
summary: "Update Status Pengajuan Pelayanan Surat",
description: `tool untuk update status pengajuan pelayanan surat`,
}
})
.post("/update", async ({ body }) => {
const { nomerPengajuan, syaratDokumen, dataText } = body
let dataUpdate = []
console.log(body)
const pengajuan = await prisma.pelayananAjuan.findFirst({
where: {
noPengajuan: nomerPengajuan,
}
})
if (!pengajuan) {
console.log("data pengajuan surat tidak ditemukan")
return { success: false, message: 'data pengajuan surat tidak ditemukan' }
}
if (pengajuan.status != "ditolak" && pengajuan.status != "antrian") {
console.log("pengajuan surat tidak dapat diupdate karena status " + pengajuan.status)
return { success: false, message: 'pengajuan surat tidak dapat diupdate karena status ' + pengajuan.status }
}
if (dataText && dataText.length > 0) {
console.log("dataText")
for (const item of dataText) {
dataUpdate.push(item.jenis)
const hasil = await prisma.dataTextPelayanan.findFirst({
where: {
idPengajuanLayanan: pengajuan.id,
jenis: item.jenis,
}
})
const upd = await prisma.dataTextPelayanan.upsert({
where: {
id: hasil?.id
},
update: {
value: item.value,
},
create: {
value: item.value,
jenis: item.jenis,
idPengajuanLayanan: pengajuan.id,
idCategory: pengajuan.idCategory,
}
})
}
}
const category = await prisma.categoryPelayanan.findUnique({
where: {
id: pengajuan.idCategory,
}
})
type SyaratDokumen = {
desc: string;
name: string;
};
const syarat = category?.syaratDokumen as SyaratDokumen[] | undefined
if (syaratDokumen && syaratDokumen.length > 0) {
console.log("syaratDokumen")
for (const item of syaratDokumen) {
const pilih = syarat?.find((cat) => cat.desc == item.jenis || cat.name == item.jenis)?.name;
console.log(syarat, pilih)
dataUpdate.push(pilih)
const hasil = await prisma.syaratDokumenPelayanan.findFirst({
where: {
idPengajuanLayanan: pengajuan.id,
jenis: pilih,
}
})
console.log(hasil, item)
if (hasil && hasil.id) {
const upd = await prisma.syaratDokumenPelayanan.upsert({
where: {
id: hasil.id
},
update: {
value: item.value,
},
create: {
value: item.value,
jenis: hasil.jenis,
idPengajuanLayanan: pengajuan.id,
idCategory: pengajuan.idCategory,
}
})
} else {
return { success: false, message: 'dokumen tidak dapat diupload' }
}
}
}
const keys = dataUpdate.join(", ");
if (pengajuan.status == "ditolak") {
const updStatus = await prisma.pelayananAjuan.update({
where: {
id: pengajuan.id,
},
data: {
status: "antrian",
}
})
}
const history = await prisma.historyPelayanan.create({
data: {
idPengajuanLayanan: pengajuan.id,
deskripsi: `Pengajuan surat diupdate oleh warga (data yg diupdate: ${keys})`,
status: "antrian",
}
})
console.log("pengajuan surat sudah diperbarui")
return { success: true, message: 'pengajuan surat sudah diperbarui' }
}, {
body: t.Object({
nomerPengajuan: t.String({
error: "nomer pengajuan harus diisi",
description: "Nomer pengajuan yang ingin diupdate"
}),
dataText: t.Optional(t.Array(
t.Object({
jenis: t.String({
description: "Jenis field yang dibutuhkan oleh kategori pelayanan. Biasanya dinamis.",
examples: ["nama", "jenis kelamin", "tempat tanggal lahir", "negara", "agama", "status perkawinan", "alamat", "pekerjaan", "jenis usaha", "alamat usaha"],
error: "jenis harus diisi"
}),
value: t.String({
description: "Isi atau nilai dari jenis field terkait.",
examples: ["Budi Santoso", "Laki-laki", "Denpasar, 28 Februari 1990", "Indonesia", "Islam", "Belum menikah", "Jl. Mawar No. 10", "Karyawan Swasta", "usaha makanan", "Jl. Melati No. 21"],
error: "value harus diisi"
}),
}),
{
description: "Kumpulan data text dinamis sesuai kategori layanan.",
examples: [
[
{ jenis: "nama", value: "Budi Santoso" },
{ jenis: "jenis kelamin", value: "Laki-laki" },
{ jenis: "tempat tanggal lahir", value: "Denpasar, 28 Februari 1990" },
{ jenis: "negara", value: "Indonesia" },
{ jenis: "agama", value: "Islam" },
{ jenis: "status perkawinan", value: "Belum menikah" },
{ jenis: "alamat", value: "Jl. Mawar No. 10" },
{ jenis: "pekerjaan", value: "Karyawan Swasta" },
{ jenis: "jenis usaha", value: "usaha makanan" },
{ jenis: "alamat usaha", value: "Jl. Melati No. 21" },
]
],
}
)),
syaratDokumen: t.Optional(t.Array(
t.Object({
jenis: t.String({
description: "Jenis dokumen persyaratan yang diminta oleh kategori layanan.",
examples: ["ktp", "kk", "surat_pengantar_rt"],
error: "jenis harus diisi"
}),
value: t.String({
description: "Nama file atau identifier file dokumen yang diupload.",
examples: ["ktp_budi.png", "kk_budi.png"],
error: "value harus diisi"
}),
}),
{
description: "Kumpulan dokumen yang wajib diupload sesuai persyaratan layanan.",
examples: [
[
{ jenis: "pengantar kelian", value: "pengantar_kelurahan_budi.png" },
{ jenis: "ktp/kk", value: "kk_budi.png" },
{ jenis: "foto lokasi", value: "foto_lokasi_budi.png" }
]
],
}
)),
}),
detail: {
summary: "Update Data Pengajuan Pelayanan Surat",
description: `tool untuk update data pengajuan pelayanan surat`,
tags: ["mcp"]
}
})

View File

@@ -1,6 +1,6 @@
import Elysia, { t } from "elysia"
import type { StatusPengaduan } from "generated/prisma"
import _, { head } from "lodash"
import _ from "lodash"
import { v4 as uuidv4 } from "uuid"
import { getLastUpdated } from "../lib/get-last-updated"
import { mimeToExtension } from "../lib/mimetypeToExtension"
@@ -376,13 +376,7 @@ const PengaduanRoute = new Elysia({
const data = await prisma.pengaduan.findFirst({
where: {
OR: [
{
noPengaduan: id
}, {
id: id
}
]
id: id
},
select: {
id: true,
@@ -417,6 +411,16 @@ const PengaduanRoute = new Elysia({
}
})
if (!data) {
const datafix = {
pengaduan: {},
history: [],
warga: {},
}
return datafix
}
const dataHistory = await prisma.historyPengaduan.findMany({
where: {
idPengaduan: data?.id,
@@ -471,11 +475,11 @@ const PengaduanRoute = new Elysia({
}
return datafix
}, {
detail: {
summary: "Detail Pengaduan Warga",
description: `tool untuk mendapatkan detail pengaduan warga / history pengaduan / mengecek status pengaduan berdasarkan id atau nomer Pengaduan`,
tags: ["mcp"]
summary: "Detail Pengaduan Warga By ID",
description: `tool untuk mendapatkan detail pengaduan warga / history pengaduan / mengecek status pengaduan berdasarkan id pengaduan`,
}
})
.get("/", async ({ query, headers }) => {
@@ -595,7 +599,6 @@ const PengaduanRoute = new Elysia({
detail: {
summary: "Upload File (FormData)",
description: "Tool untuk upload file ke folder tujuan dengan memakai FormData",
// tags: ["mcp"],
consumes: ["multipart/form-data"]
},
})
@@ -639,7 +642,6 @@ const PengaduanRoute = new Elysia({
detail: {
summary: "Upload File (FormData)",
description: "Tool untuk upload file ke folder tujuan dengan memakai FormData",
// tags: ["mcp"],
consumes: ["multipart/form-data"]
},
})
@@ -681,7 +683,6 @@ const PengaduanRoute = new Elysia({
detail: {
summary: "Upload File (Base64)",
description: "Tool untuk upload file ke Seafile dalam format Base64",
// tags: ["mcp"],
consumes: ["multipart/form-data"]
},
})
@@ -884,6 +885,118 @@ const PengaduanRoute = new Elysia({
description: "Tool untuk delete file Seafile",
},
})
.post("/detail-data", async ({ body }) => {
const { nomerPengaduan } = body
const data = await prisma.pengaduan.findFirst({
where: {
noPengaduan: nomerPengaduan
},
select: {
id: true,
noPengaduan: true,
title: true,
detail: true,
location: true,
image: true,
idCategory: true,
idWarga: true,
status: true,
keterangan: true,
createdAt: true,
updatedAt: true,
CategoryPengaduan: {
select: {
name: true
}
},
Warga: {
select: {
name: true,
phone: true,
_count: {
select: {
Pengaduan: true,
PelayananAjuan: true,
}
}
}
}
}
})
if (!data) {
return { success: false, message: "Data tidak ditemukan" };
}
const dataHistory = await prisma.historyPengaduan.findMany({
where: {
idPengaduan: data?.id,
},
select: {
id: true,
deskripsi: true,
status: true,
createdAt: true,
idUser: true,
User: {
select: {
name: true,
}
}
}
})
const dataHistoryFix = dataHistory.map((item: any) => ({
..._.omit(item, ["User", "createdAt"]),
nameUser: item.User?.name,
createdAt: item.createdAt
}))
const warga = {
name: data?.Warga?.name,
phone: data?.Warga?.phone,
pengaduan: data?.Warga?._count.Pengaduan,
pelayanan: data?.Warga?._count.PelayananAjuan,
}
const dataPengaduan = {
id: data?.id,
noPengaduan: data?.noPengaduan,
title: data?.title,
detail: data?.detail,
location: data?.location,
image: data?.image,
category: data?.CategoryPengaduan.name,
status: data?.status,
keterangan: data?.keterangan,
createdAt: data?.createdAt,
updatedAt: data?.updatedAt,
}
const datafix = {
pengaduan: dataPengaduan,
history: dataHistoryFix,
warga: warga,
}
return datafix
}, {
body: t.Object({
nomerPengaduan: t.String({
description: "Nomer pengaduan yg ingin diakses",
examples: ["PGD-101225-001", "PGD-101225-002"],
error: "Nomer pengaduan harus diisi",
}),
}),
detail: {
summary: "Detail Pengaduan Warga By Nomor Pengaduan",
description: `tool untuk mendapatkan detail data pengaduan berdasarkan nomor pengaduan`,
tags: ["mcp"]
}
})
;
export default PengaduanRoute