Spaces:
Sleeping
Sleeping
| import prisma from '../utils/db'; | |
| import { catatAudit } from '../utils/audit'; | |
| import { moveToTrash } from '../utils/trash'; | |
| import { APIError } from '../utils/errors'; | |
| export class MemberService { | |
| static async getMembers(skip = 0, limit = 10, pencarian?: string) { | |
| const where: any = { | |
| deleted_at: null, | |
| }; | |
| if (pencarian) { | |
| where.OR = [ | |
| { nama: { contains: pencarian } }, | |
| { kode: { contains: pencarian } }, | |
| { nomor_hp: { contains: pencarian } }, | |
| ]; | |
| } | |
| return await prisma.member.findMany({ | |
| where, | |
| skip, | |
| take: limit, | |
| }); | |
| } | |
| static async getMemberById(id: number) { | |
| const member = await prisma.member.findFirst({ | |
| where: { id, deleted_at: null }, | |
| }); | |
| if (!member) { | |
| throw new APIError('Member tidak ditemukan', 404); | |
| } | |
| return member; | |
| } | |
| static async create(data: any, actorId: number, ip: string, userAgent: string) { | |
| const existingPhone = await prisma.member.findFirst({ | |
| where: { nomor_hp: data.nomor_hp }, | |
| }); | |
| const existingCode = await prisma.member.findUnique({ | |
| where: { kode: data.kode }, | |
| }); | |
| const existing = existingPhone || existingCode; | |
| if (existing) { | |
| if (existing.deleted_at === null) { | |
| const fieldType = existing.id === existingPhone?.id ? 'Nomor HP' : 'Kode'; | |
| const fieldVal = existing.id === existingPhone?.id ? data.nomor_hp : data.kode; | |
| throw new APIError(`${fieldType} member '${fieldVal}' sudah terdaftar/digunakan`, 400); | |
| } else { | |
| // Soft deleted duplicate. Reactivate and update! | |
| const restored = await prisma.member.update({ | |
| where: { id: existing.id }, | |
| data: { | |
| deleted_at: null, | |
| aktif: 1, | |
| kode: data.kode, | |
| nama: data.nama, | |
| nomor_hp: data.nomor_hp, | |
| alamat: data.alamat ?? null, | |
| limit_bon: data.limit_bon ?? 0, | |
| foto_url: data.foto_url ?? null, | |
| }, | |
| }); | |
| await catatAudit({ | |
| userId: actorId, | |
| aksi: 'restore', | |
| entitas: 'member', | |
| entitasId: restored.id, | |
| dataBaru: { kode: restored.kode, nama: restored.nama, nomor_hp: restored.nomor_hp, limit_bon: Number(restored.limit_bon) }, | |
| ipAddress: ip, | |
| userAgent, | |
| }); | |
| return restored; | |
| } | |
| } | |
| const member = await prisma.member.create({ | |
| data: { | |
| kode: data.kode, | |
| nama: data.nama, | |
| nomor_hp: data.nomor_hp, | |
| alamat: data.alamat ?? null, | |
| limit_bon: data.limit_bon ?? 0, | |
| total_bon: 0, | |
| foto_url: data.foto_url ?? null, | |
| aktif: data.aktif ?? 1, | |
| }, | |
| }); | |
| await catatAudit({ | |
| userId: actorId, | |
| aksi: 'create', | |
| entitas: 'member', | |
| entitasId: member.id, | |
| dataBaru: { kode: member.kode, nama: member.nama, nomor_hp: member.nomor_hp, limit_bon: Number(member.limit_bon) }, | |
| ipAddress: ip, | |
| userAgent, | |
| }); | |
| return member; | |
| } | |
| static async update(id: number, data: any, actorId: number, ip: string, userAgent: string) { | |
| const member = await this.getMemberById(id); | |
| const dataLama = { | |
| nama: member.nama, | |
| nomor_hp: member.nomor_hp, | |
| alamat: member.alamat, | |
| total_poin: member.total_poin, | |
| limit_bon: Number(member.limit_bon), | |
| total_bon: Number(member.total_bon), | |
| foto_url: member.foto_url, | |
| aktif: member.aktif, | |
| }; | |
| if (data.nomor_hp !== undefined) { | |
| const dup = await prisma.member.findFirst({ | |
| where: { nomor_hp: data.nomor_hp, id: { not: id } }, | |
| }); | |
| if (dup) { | |
| throw new APIError('Nomor HP tersebut sudah digunakan oleh member lain', 400); | |
| } | |
| } | |
| const updateData: any = {}; | |
| if (data.nama !== undefined) updateData.nama = data.nama; | |
| if (data.nomor_hp !== undefined) updateData.nomor_hp = data.nomor_hp; | |
| if (data.alamat !== undefined) updateData.alamat = data.alamat; | |
| if (data.total_poin !== undefined) updateData.total_poin = data.total_poin; | |
| if (data.limit_bon !== undefined) updateData.limit_bon = data.limit_bon; | |
| if (data.total_bon !== undefined) updateData.total_bon = data.total_bon; | |
| if (data.foto_url !== undefined) updateData.foto_url = data.foto_url; | |
| if (data.aktif !== undefined) updateData.aktif = data.aktif; | |
| const updated = await prisma.member.update({ | |
| where: { id }, | |
| data: updateData, | |
| }); | |
| const dataBaru = { | |
| nama: updated.nama, | |
| nomor_hp: updated.nomor_hp, | |
| alamat: updated.alamat, | |
| total_poin: updated.total_poin, | |
| limit_bon: Number(updated.limit_bon), | |
| total_bon: Number(updated.total_bon), | |
| foto_url: updated.foto_url, | |
| aktif: updated.aktif, | |
| }; | |
| await catatAudit({ | |
| userId: actorId, | |
| aksi: 'update', | |
| entitas: 'member', | |
| entitasId: updated.id, | |
| dataLama, | |
| dataBaru, | |
| ipAddress: ip, | |
| userAgent, | |
| }); | |
| return updated; | |
| } | |
| static async delete(id: number, actorId: number, ip: string, userAgent: string) { | |
| const member = await this.getMemberById(id); | |
| if (Number(member.total_bon) > 0) { | |
| throw new APIError(`Tidak dapat menghapus member. Masih memiliki tanggungan kasbon sebesar Rp ${Number(member.total_bon).toLocaleString('id-ID')}`, 400); | |
| } | |
| await moveToTrash({ | |
| instance: member, | |
| entityType: 'member', | |
| actorId, | |
| }); | |
| await catatAudit({ | |
| userId: actorId, | |
| aksi: 'delete', | |
| entitas: 'member', | |
| entitasId: member.id, | |
| dataLama: { kode: member.kode, nama: member.nama, aktif: 1 }, | |
| dataBaru: { kode: member.kode, nama: member.nama, aktif: 0 }, | |
| ipAddress: ip, | |
| userAgent, | |
| }); | |
| return true; | |
| } | |
| } | |