Ringkasan Utama
Project costing hanya berjalan ketika timesheet, pembelian dan pendapatan semuanya diposting ke kode proyek yang sama, sehingga profitabilitas bisa dibaca per proyek, bukan diperkirakan di akhir tahun. Bagi perusahaan jasa profesional dan konstruksi, angka itu adalah pembeda antara memberi harga pekerjaan berikutnya dengan tepat atau keliru.
Rata-rata ROI untuk implementasi ERP adalah 52% — artinya setiap dolar yang diinvestasikan menghasilkan $1,52 kembali — dengan sebagian besar perusahaan memulihkan investasi mereka dalam 16 bulan. Untuk bisnis jasa profesional dan konstruksi di Indonesia, project costing sering menjadi modul dengan ROI tercepat: mengetahui persis berapa biaya setiap proyek versus apa yang ditagih dapat mengubah jenis proyek yang tidak menguntungkan menjadi menguntungkan dalam satu kuartal.
Struktur Anggaran Proyek
Proyek memiliki satu atau lebih baris anggaran, masing-masing terkait dengan kategori biaya: Tenaga Kerja, Perjalanan, Material, Subkontraktor, Lainnya. Setiap baris anggaran memiliki jumlah yang dianggarkan dan opsional kuantitas yang dianggarkan (jam, perjalanan, unit). Modul proyek melacak aktual terhadap setiap baris anggaran saat biaya diposting.
Entri dan Persetujuan Timesheet
Staf mengirimkan timesheet mingguan melalui UI React sederhana: pilih proyek, pilih tugas, masukkan jam per hari, tambahkan deskripsi. Timesheet masuk ke manajer proyek untuk persetujuan. Setelah disetujui, jam dikalikan dengan cost rate staf (tersimpan di modul HR) untuk menghitung biaya tenaga kerja, yang diposting secara otomatis ke jurnal proyek.
Project Costing Data Flow
┌─────────────────────────────────────────────────────┐
│ COST SOURCES │
│ │
│ Timesheets Expense Claims AP Invoices │
│ (Labor) (Travel/Other) (Materials) │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ hours × cost_rate receipts vendor bills │
└──────────────────────────┬──────────────────────────┘
│ all auto-post to
▼
┌─────────────────────────────────────────────────────┐
│ journal_lines (project_id tagged) │
│ DEBIT Project WIP [cost amount] │
│ CREDIT Accrued Labor [or Expense Payable] │
└──────────────────────────┬──────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ Budget vs. Actual Dashboard │
│ │
│ Category Budget Actual Variance Status │
│ Labor 200M 165M +35M 🟢 83% │
│ Travel 15M 18M -3M 🔴 120% │
│ Materials 300M 280M +20M 🟡 93% │
│ Subcontract 50M 40M +10M 🟢 80% │
│ ───────────────────────────────────────────────── │
│ TOTAL 565M 503M +62M 89% │
└─────────────────────────────────────────────────────┘Dari pengalaman saya membangun sistem ERP dalam pekerjaan konsultasi ERP lepas saya: selalu tangkap perbedaan billable/non-billable pada setiap entri timesheet. Waktu yang dihabiskan untuk rapat internal, penulisan proposal, dan pengerjaan ulang adalah non-billable bahkan jika ada di proyek klien. Rasio jam billable vs. total jam per manajer proyek adalah salah satu metrik paling mengungkapkan — menunjukkan siapa yang efisien dan siapa yang menghabiskan waktu berlebihan untuk overhead.
Integrasi Klaim Biaya
Biaya proyek — perjalanan, akomodasi, hiburan klien — diajukan melalui klaim biaya yang terhubung ke proyek. Workflow klaim biaya mencerminkan proses AP mini: staf mengirimkan bukti (unggah foto), manajer proyek menyetujui, keuangan memverifikasi dan mengganti rugi. Klaim biaya yang disetujui diposting ke buku besar biaya proyek secara otomatis.
Beberapa Model Penagihan
Sistem yang saya bangun mendukung tiga model penagihan: Time and Materials (tagih jam aktual × tarif yang disepakati + biaya yang dapat diganti), Fixed Price (penagihan berbasis milestone terlepas dari biaya), dan Cost Plus (biaya + margin yang disepakati%). Untuk proyek T&M, sistem menghasilkan draft faktur AR dari timesheet dan biaya yang disetujui.
-- PostgreSQL: project cost tables
CREATE TABLE projects (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
code VARCHAR(20) UNIQUE NOT NULL,
name VARCHAR(200) NOT NULL,
billing_model VARCHAR(20) NOT NULL -- 'TM', 'FIXED', 'COST_PLUS'
);
CREATE TABLE project_budget_lines (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
project_id UUID NOT NULL REFERENCES projects(id),
category VARCHAR(50) NOT NULL, -- 'LABOR','TRAVEL','MATERIALS'
budgeted_amt NUMERIC(15,2) NOT NULL,
budgeted_qty NUMERIC(10,2)
);
-- NestJS: approve timesheet and post cost to ledger
@Transactional()
async approveTimesheet(timesheetId: string) {
const ts = await this.tsRepo.findOneOrFail(timesheetId, {
relations: ['employee', 'project'],
});
const costRate = await this.hrService.getCostRate(ts.employee.id);
const laborCost = ts.hours * costRate;
// Post to journal
await this.journalService.post({
description: `Labor: ${ts.employee.name} - ${ts.project.code}`,
lines: [
{ accountId: ACCOUNTS.PROJECT_WIP, projectId: ts.project.id,
debit: laborCost, credit: 0 },
{ accountId: ACCOUNTS.ACCRUED_LABOR,
debit: 0, credit: laborCost },
],
});
ts.status = 'approved';
await this.tsRepo.save(ts);
}Bagaimana Saya Mendekati Ini
Modul proyek dibangun dengan NestJS untuk API, PostgreSQL untuk data, dan React untuk frontend. Dashboard proyek menggunakan Recharts untuk menampilkan garis tren anggaran vs. aktual dari waktu ke waktu. Saya mengimplementasikan sistem lampu lalu lintas: hijau jika aktual di bawah 75% anggaran, kuning jika 75-90%, merah jika di atas 90%.
Cost rate staf (gaji / jam produktif) adalah informasi penggajian yang sensitif. Jangan tampilkan pada layar timesheet atau dalam laporan yang dapat diakses manajer proyek atau klien. Simpan cost rate di modul HR dengan RBAC yang membatasi akses hanya untuk peran Keuangan dan HR. Laporan proyek harus menampilkan total biaya proyek tanpa mengungkapkan cost rate staf individu.
Pelaporan Profitabilitas Proyek
Laporan profitabilitas menampilkan untuk setiap proyek: nilai kontrak, total biaya (tenaga kerja + langsung), laba kotor, margin laba kotor %, dan status penagihan (berapa banyak yang telah difakturkan vs. dikontrak). Untuk proyek T&M, laporan juga menampilkan realisasi — rasio jam yang ditagih terhadap jam yang timbul.
Integrasi dengan Keuangan dan Penggajian
Modul proyek berintegrasi secara bidireksional dengan modul keuangan: biaya diposting ke buku besar umum saat disetujui (debit WIP Proyek, kredit Tenaga Kerja yang Masih Harus Dibayar), dan pendapatan diposting ketika faktur dibuat. Untuk integrasi penggajian, jam timesheet berfungsi sebagai sumber untuk menghitung penggajian staf berbasis jam atau proyek.
