Skip to main content
BlogERP

Project Costing dan Pelacakan Waktu di ERP Kustom: Anggaran, Timesheet, dan Profitabilitas

Cara membangun modul project costing dengan pelacakan waktu, alokasi biaya, pemantauan anggaran, dan pelaporan profitabilitas di ERP kustom menggunakan NestJS dan PostgreSQL.

Matthews Wong

Software Engineer

Juni 202510 menit baca
ERP

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.

FAQ

Pertanyaan Umum

Jawaban singkat untuk pertanyaan yang paling sering diajukan pembaca tentang topik ini.

Mengapa alur persetujuan timesheet langsung memposting biaya tenaga kerja ke jurnal proyek?

Setelah manajer proyek menyetujui timesheet, sistem mengalikan jam yang disetujui dengan cost rate masing-masing staf yang tersimpan di modul HR, lalu mempostingnya secara otomatis sebagai debit ke akun biaya proyek. Otomatisasi ini menghilangkan perhitungan manual yang rawan kesalahan — yaitu berapa jam yang dihabiskan dan berapa biayanya — yang selama ini menjadi masalah umum di perusahaan jasa profesional. Tidak diperlukan entri data terpisah karena biaya langsung mengalir dari persetujuan ke buku besar.

Bagaimana sistem pemantauan anggaran lampu lalu lintas bekerja?

Dashboard proyek menampilkan indikator lampu lalu lintas berdasarkan seberapa banyak anggaran yang telah terpakai: hijau jika aktual di bawah 75% anggaran, kuning jika 75–90%, dan merah jika di atas 90%. Tampilan visual ini memungkinkan manajer proyek melihat sekilas proyek mana yang cenderung melebihi anggaran tanpa harus membaca angka secara detail. Dashboard diperbarui setiap 15 menit melalui refetchInterval dari React Query.

Apa saja tiga model penagihan yang didukung, dan bagaimana pengaruhnya terhadap pembuatan faktur?

Sistem mendukung Time and Materials (T&M), Fixed Price, dan Cost Plus. Untuk proyek T&M, draft faktur AR dibuat secara otomatis dari timesheet dan klaim biaya yang telah disetujui. Proyek Fixed Price memicu faktur berdasarkan milestone proyek, sedangkan faktur Cost Plus dihitung sebagai total biaya dikalikan satu ditambah persentase margin yang disepakati. Model penagihan ditetapkan saat proyek dibuat dan menentukan logika pembuatan faktur yang dijalankan.

Mengapa cost rate staf harus disembunyikan dari manajer proyek dan klien?

Cost rate staf berasal dari data gaji dan merupakan informasi penggajian yang sensitif. Menampilkannya di layar timesheet atau laporan proyek akan mengungkapkan detail kompensasi individu kepada pihak yang tidak berhak mengaksesnya. Sistem menyimpan cost rate di modul HR dengan RBAC yang membatasi visibilitas hanya untuk peran Keuangan dan HR, serta laporan proyek hanya menampilkan total biaya proyek tanpa merinci rate individu. Permission khusus cost_rate_visible ditambahkan untuk menegakkan batasan ini.

Bagaimana perbedaan billable vs. non-billable membantu manajemen mengidentifikasi inefisiensi?

Setiap entri timesheet mencatat apakah waktu tersebut billable atau non-billable, meskipun dikerjakan dalam proyek klien. Waktu yang dihabiskan untuk rapat internal, penulisan proposal, dan pengerjaan ulang dihitung sebagai non-billable. Rasio jam billable terhadap total jam per manajer proyek adalah salah satu metrik paling mengungkapkan dalam sistem — menunjukkan siapa yang efisien dan siapa yang menghabiskan waktu berlebihan untuk overhead, dan klien selalu terkejut saat pertama kali melihat data tingkat billability mereka yang sebenarnya.