Tokiva-backend-Node / src /services /member.service.ts
anoderb
feat: initial commit of Tokiva POS Node backend for Hugging Face
ef874e6
Raw
History Blame Contribute Delete
5.79 kB
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;
}
}