Laravel ERP API

Single Page API Documentation

Product Requirement Document (PRD)

Overview

Proyek ini adalah API backend untuk sebuah sistem ERP internal yang mendukung manajemen penawaran (quotation), kontrak, proyek, sumber daya manusia, dan reimbursement. Aplikasi dibangun dengan Laravel dan menempatkan kontrol akses pada JWT authorization, Spatie role/permission, serta lapisan API resource untuk master data dan operasional keuangan.

Latar Belakang

  • Menstandarisasi proses komersial dari quotation hingga pembuatan proyek dan kontrak.
  • Memastikan klaim reimbursement dicatat dengan validasi anggaran dan lampiran nota.
  • Mengelola data master departemen, posisi, pegawai, dan akses pengguna secara terpusat.

Tujuan API

  • Menyediakan endpoint terautentikasi untuk CRUD master data HR dan finance.
  • Mendukung kalkulasi quotation otomatis dengan formula margin, overhead, pajak, dan risiko.
  • Men-trigger pipeline ERP otomatis ketika quotation disetujui.
  • Menangani file upload nota reimbursement dengan GCS dan anggaran budget allocation.
  • Memungkinkan FE menampilkan status quotation, link PDF, dan data terkait contract/project secara konsisten.

Objective untuk Frontend

  • FE harus bisa menampilkan daftar quotation beserta status, nilai pricing client, dan status PDF yang sudah dibuat.
  • FE harus menyediakan form create/update quotation dengan input item, perhitungan otomatis, dan validasi yang jelas.
  • FE perlu menampilkan tombol aksi untuk mengubah status quotation (sent, approved, rejected) dan refresh data setelah aksi.
  • FE wajib menampilkan link PDF / attachment setelah proses generate PDF dan mengarahkan user ke dokumen yang benar.
  • FE harus menghubungkan tampilan quotation dengan contract/project yang muncul setelah approval agar alur bisnis mudah dipahami pengguna.

Scope Sistem

  • Autentikasi JWT untuk seluruh API selain /api/login.
  • Manajemen pengguna, role, dan permission lewat Spatie.
  • CRUD Master Data: Departments, Positions, Employees.
  • Quotation engine dengan matematika margin dan pajak.
  • Contract & Project creation automation ketika quotation approved.
  • Reimbursement workflow dengan attachment dan budget validation.

Business Rules Utama

  1. Hanya user terautentikasi dengan perizinan yang sesuai boleh mengakses data operasional.
  2. Quotation yang berstatus approved memicu pembuatan kontrak, proyek, dan budget allocation.
  3. Kontrak dan posisi tidak boleh dihapus jika masih terhubung dengan project atau employee.
  4. Reimbursement hanya bisa diupdate ketika status masih pending.
  5. Mark as paid memotong saldo budget allocation sesuai total reimbursement.
  6. Upload nota reimbursement disimpan di Google Cloud Storage melalui service khusus.

System Flow & Data Journey

Bagaimana request API melintasi stack aplikasi ini dari awal sampai akhir.

Middleware & Routing
1

Authentication & Authorization

Semua endpoint selain POST /api/login dilindungi oleh middleware auth:api. Izin akses dikendalikan oleh Spatie Permission saat request diteruskan ke controller.

2

Query Helper & Pagination

Controller list endpoint menggunakan BaseController::processQuery() untuk mencari, mengurutkan, dan melakukan pagination otomatis berdasarkan kolom tabel.

3

Quotation & ERP Pipeline

Saat quotation dibuat, sistem menghitung total cost, multiplier, client price, margin bruto, pajak, overhead, risiko, dan laba bersih. Ketika status menjadi approved, backend otomatis membuat kontrak, proyek, dan alokasi budget untuk item lumpsum.

4

Reimbursement Workflow

Pengajuan reimbursement menyimpan header, banyak item, dan attachment nota ke GCS. Update hanya boleh untuk status pending. Approval final membuat tanggal pembayaran, sedangkan pay mengubah status menjadi paid dan memperbarui anggaran alokasi proyek.

Detailed API Flow

Detail alur request, field required, dan cara pengisian untuk workflow utama.

Request Contract

1. Login (Authentication)

Endpoint ini wajib dipanggil dulu untuk mendapatkan JWT token sebelum menggunakan endpoint lain.

  • POST /api/login
  • Required: email, password
  • Format: email valid, password string.
  • Response: access_token, token_type, expires_in, dan user profile.

2. Create User

Buat akun user baru dengan role dan department yang valid.

  • POST /api/users
  • Required: name, email, password, role, department_id
  • Tips isi: email harus unik, password minimum 8 karakter, role harus ada pada tabel roles, department_id harus merujuk ke department yang ada.

3. Create Employee

Tambahkan pegawai baru ke master data dan hubungkan ke departemen/posisi.

  • POST /api/employees
  • Required: first_name, email, salary, department_id, position_id, status
  • Status valid: permanent, contract, internship.
  • Tips isi: email harus unik, salary numeric >= 0, department_id dan position_id wajib ada di master data.

4. Create Quotation

Kirim quotation draft dengan komponen biaya untuk dihitung oleh engine.

  • POST /api/quotations
  • Required: client_name, multiplier_type, items
  • Items required: setiap item membutuhkan name, cost_type, base_price, quantity.
  • cost_type valid: prorate atau lumpsum.
  • multiplier_type valid: enterprise, b2b, umkm, custom, reverse.
  • Optional: multiplier_value, tax_percentage, overhead_percentage, risk_percentage, reverse_client_price.
  • Alur: backend hitung total_cost, client_price, gross_margin, tax, overhead, risk, dan net_profit.
  • Output tambahan: setiap item menyimpan client_unit_price dan client_total_price untuk tampilan PDF/FE.

5. Approve Quotation

Ubah status quotation agar pipeline kontrak dan proyek berjalan.

  • PATCH /api/quotations/{id}/status
  • Required: status.
  • Status valid: draft, sent, approved, rejected.
  • Jika approved: sistem otomatis membuat record contract, project, dan alokasi budget untuk item lumpsum.

6. Generate Quotation PDF

Setelah quotation siap, admin bisa mengirim data tambahan untuk membuat PDF resmi dan menyimpannya ke storage.

  • POST /api/quotations/{id}/generate-pdf
  • Optional body: quotation_date, valid_until, client_address, client_email, phone_number, notes.
  • Behavior: sistem membuat nomor quotation, menyimpan log cetak, menghasilkan PDF, mengunggah ke GCS, dan mengembalikan attachment/log.
  • Auto rule: jika quotation masih draft, status otomatis berubah ke sent.

7. Create Contract

Buat umbrella contract untuk menampung proyek-proyek terkait.

  • POST /api/contracts
  • Required: contract_number, client_name, total_contract_value.
  • Optional: start_date, end_date, contract_file, description.
  • Aturan: contract_number harus unik, end_date harus sama atau setelah start_date.

8. Create Project

Buat project baru yang terhubung ke contract.

  • POST /api/projects
  • Required: contract_id, name, status.
  • Status valid: planned, on_progress, on_hold, completed, cancelled.
  • Optional: start_date, end_date, project_budget.
  • Alur: project dibuat setelah contract ada, lalu bisa assign employee.

9. Assign Employee to Project

Tambahkan pegawai ke proyek dengan peran dan persentase alokasi.

  • POST /api/projects/{id}/assign-employee
  • Required: employee_id, role, billing_rate, allocation_percentage.
  • Aturan: allocation_percentage harus integer 1-100, billing_rate harus numeric >= 0.
  • Optional: start_date, end_date.

10. Submit Reimbursement

Kirim klaim reimbursement dengan beberapa item biaya.

  • POST /api/reimbursements
  • Required: title, items.
  • Item required: description, amount, expense_date.
  • Optional: project_id, project_budget_allocation_id, items.*.receipt_file.
  • Validasi: jika project_budget_allocation_id disertakan, total amount dibandingkan dengan sisa budget.

Quotation Flow

Alur quotation lengkap: dari input items sampai hubungan ke contract, project, dan budget allocation.

Quotation Lifecycle

1. Buat Quotation Draft

User mengirim request POST /api/quotations dengan data klien, multiplier, dan daftar item biaya.

  • Required: client_name, multiplier_type, items.
  • Item object: name, cost_type, base_price, quantity.
  • cost_type: prorate atau lumpsum.
  • multiplier_type: enterprise, b2b, umkm, custom, reverse.
  • Optional fields: multiplier_value, tax_percentage, overhead_percentage, risk_percentage, reverse_client_price.

2. Perhitungan Harga

Backend menghitung nilai penting quotation berdasarkan rules berikut:

  • Total cost: jumlah base_price * quantity semua item.
  • Client price: dihitung dari multiplier_type dan nilai penyesuaian optional.
  • Gross margin: selisih antara total cost dan client price sebelum pajak/overhead/risk.
  • Tax / overhead / risk: didukung sebagai persentase optional, ditambahkan ketika tersedia.
  • Net profit: hasil akhir setelah semua biaya tambahan.

3. Status Quotation

Quotation diawali sebagai draft, lalu bisa diubah status menjadi sent, approved, atau rejected.

  • PATCH /api/quotations/{id}/status
  • Required: status.
  • Status valid: draft, sent, approved, rejected.
  • Transisi penting: ketika status menjadi approved, sistem otomatis membuat contract, project, dan budget allocation yang terkait.

4. Hubungan Entitas

Quotation terhubung ke beberapa entitas penting bila disetujui.

  • QuotationItem: setiap item biaya disimpan di tabel quotation_items dan terhubung ke quotation.
  • QuotationGenerationLog: setiap kali file PDF dibuat, sistem menyimpan log nomor quotation, tanggal, masa berlaku, dan metadata cetak.
  • Attachment: file PDF yang telah digenerate diupload ke storage dan dihubungkan ke log cetak melalui polymorphic attachment.
  • Contract: quotation approved menghasilkan record contract baru.
  • Project: contract yang dibuat akan menjadi dasar pembuatan project.
  • ProjectBudgetAllocation: item lumpsum dapat memicu alokasi anggaran untuk pekerjaan tersebut.
  • Employee / Position: meskipun tidak langsung terhubung saat quotation dibuat, project hasil approval dapat memanfaatkan karyawan dan posisi dalam proses assignment selanjutnya.

5. Alur Berdasarkan Tipe Item

Alur backend berbeda sedikit tergantung cost_type item:

  • prorate: biaya dibagi secara prorata, biasanya dihitung per unit atau per hari.
  • lumpsum: biaya langsung ditetapkan satu kali dan sering dihubungkan ke alokasi anggaran.
  • Automation: hanya item lumpsum yang biasanya memicu alokasi budget otomatis.

6. Front-end Guidance

Petunjuk berikut akan membantu tim FE membangun UI dan request flow quotation dengan benar.

  • Form field: tampilkan input untuk client_name, multiplier_type, multiplier_value, tax_percentage, overhead_percentage, risk_percentage, dan reverse_client_price.
  • Item list: FE harus menyediakan kemampuan menambah/menghapus item, dengan input name, cost_type, base_price, dan quantity untuk setiap row.
  • Validation: periksa client-side bahwa semua required field terisi, angka valid, dan quantity minimal 1 sebelum submit.
  • Submit flow: kirim body JSON ke POST /api/quotations, lalu tampilkan hasil kalkulasi jika response sukses.
  • PDF status: pada list quotation, gunakan field is_pdf_generated dan latest_pdf_url untuk menampilkan status file yang sudah dibuat.
  • Status actions: pada tampilan detail quotation, sediakan tombol untuk mengubah status ke sent, approved, atau rejected melalui PATCH /api/quotations/{id}/status.
  • After approved: reload detail quotation untuk memastikan contract/project sudah dibuat dan tampilkan link atau status terkait contract/project tersebut.
  • After generate PDF: setelah memanggil POST /api/quotations/{id}/generate-pdf, reload data quotation untuk melihat link PDF terbaru dari response attachment/log.
  • Error handling: tangkap 422 validation errors dan tampilkan pesan field-by-field, serta tangkap 500 error jika terjadi masalah kalkulasi di server.

User Persona

Finance Controller

Memvalidasi quotation, mengapprove reimbursement, dan menandai pembayaran.

Project Manager

Mengelola proyek, penugasan employee, dan menjaga budget allocation tetap akurat.

HR / System Admin

Menangani data pegawai, department, posisi, dan kontrol akses user serta role.

User Stories

As a Finance Controller

I want to approve quotation drafts so that the system can auto-generate contract and project records.

  • Quotation status update to approved triggers contract + project creation.
  • Create budget allocation records for lumpsum items.

As an HR Admin

I want to maintain employees, departments, and positions so that master data remains accurate and linked to operations.

  • Employee records include department, position, salary, status, and contract dates.
  • Departments and positions cannot be removed while still referenced by employees.

As an Employee

I want to submit reimbursement claims with receipt uploads so that finance can track expense approval and payment.

  • Uploaded receipt files are stored through Google Cloud Storage service.
  • Claim updates are only allowed while status is still pending.

Acceptance Criteria

Authentication

Only POST /api/login is public. All other endpoints require valid JWT bearer token.

Role-Based Access

Permission middleware validates access per module, e.g. cms:quotation:view, cms:reimburse:update.

ERP Pipeline

Approved quotation automatically creates contract, project, and budget allocation records.

Reimbursement Validity

Budget allocation is checked before reimbursement approval and total paid claims reduce the available budget.

Data Model Summary

Core Entities

  • users: nama, email, password, department_id, roles/permissions via Spatie.
  • departments: unit bisnis untuk employee dan user.
  • positions: jabatan employee dan hubungan master data.
  • employees: data pegawai, salary, status, contract dates, department, position.
  • quotations: kalkulasi harga proyek, multiplier, status.
  • quotation_items: komponen biaya prorate/lumpsum dari quotation.
  • contracts: umbrella contract yang bisa memiliki banyak projects.
  • projects: terkait contract, optional quotation, assigned employees via pivot.
  • project_budget_allocations: kategori alokasi anggaran, allocated/used amount.
  • reimbursements: klaim employee dengan status workflow dan disbursement date.
  • reimbursement_items: detail expense line dan attachment polymorphic.
  • attachments: polymorphic file metadata untuk receipts.

Relasi Kunci

  • User belongsTo Department.
  • Employee belongsTo Department dan Position.
  • Project belongsTo Contract; belongsToMany Employee.
  • Quotation hasMany QuotationItem; belongsTo Contract.
  • Reimbursement hasMany ReimbursementItem; optional belongsTo Project dan Budget Allocation.
  • Attachment menggunakan relasi polymorphic untuk ReimbursementItem.

API Endpoint Directory

Ringkasan endpoint yang tersedia dalam konfigurasi routes/api.php.

GET POST PUT/PATCH DELETE
Method Path Function Purpose
POST /api/login AuthController@login Authenticate user and issue JWT token.
POST /api/logout AuthController@logout Invalidate JWT token and sign out.
GET /api/users UserManagementController@index List users with roles and department.
POST /api/users UserManagementController@store Create user with department and role.
DELETE /api/users/{id} UserManagementController@destroy Remove user account.
GET /api/roles UserManagementController@getRoles Retrieve role list with permissions.
GET /api/permissions UserManagementController@getPermissions List grouped permission names for UI.
POST /api/roles UserManagementController@storeRole Create role and assign existing permissions.
GET /api/quotations QuotationController@index List quotations with item count, PDF generation status, and latest PDF URL.
POST /api/quotations QuotationController@store Create quotation draft with auto pricing engine and per-item client pricing.
GET /api/quotations/{id} QuotationController@show Get quotation detail with items and related contract/project data.
PUT /api/quotations/{id} QuotationController@update Edit quotation and recalc financial fields.
DELETE /api/quotations/{id} QuotationController@destroy Delete quotation and related items.
PATCH /api/quotations/{id}/status QuotationController@updateStatus Change quotation status and trigger ERP automation.
POST /api/quotations/{id}/generate-pdf QuotationController@generatePdf Generate quotation PDF, upload to GCS, and store print metadata.
GET /api/departments DepartmentController@index List department master data.
POST /api/departments DepartmentController@store Create a department record.
GET /api/departments/{id} DepartmentController@show Get single department detail.
PUT /api/departments/{id} DepartmentController@update Update department information.
DELETE /api/departments/{id} DepartmentController@destroy Delete department if no active employees.
GET /api/positions PositionController@index List positions.
POST /api/positions PositionController@store Create a new position.
GET /api/positions/{id} PositionController@show Show position and its employees.
PUT /api/positions/{id} PositionController@update Update position title.
DELETE /api/positions/{id} PositionController@destroy Delete position only if unused.
GET /api/employees EmployeeController@index List employees with department and position.
POST /api/employees EmployeeController@store Add new employee.
GET /api/employees/{id} EmployeeController@show Employee detail with relations.
PUT /api/employees/{id} EmployeeController@update Update employee profile and status.
DELETE /api/employees/{id} EmployeeController@destroy Remove employee record.
GET /api/contracts ContractController@index List umbrella contracts.
POST /api/contracts ContractController@store Create contract metadata.
GET /api/contracts/{id} ContractController@show Fetch contract detail with projects.
PUT /api/contracts/{id} ContractController@update Update contract fields.
DELETE /api/contracts/{id} ContractController@destroy Delete contract if no related projects exist.
GET /api/projects ProjectController@index List projects with budget analysis.
POST /api/projects ProjectController@store Create a project record.
GET /api/projects/{id} ProjectController@show Get project details and profit analysis.
PUT /api/projects/{id} ProjectController@update Update project metadata.
DELETE /api/projects/{id} ProjectController@destroy Delete a project record.
POST /api/projects/{id}/assign-employee ProjectController@assignEmployee Assign employee to a project with billing and allocation.
GET /api/reimbursements ReimbursementController@index List reimbursements with relations.
POST /api/reimbursements ReimbursementController@store Submit reimbursement with file upload support.
GET /api/reimbursements/{id} ReimbursementController@show Retrieve reimbursement detail and attachments.
POST /api/reimbursements/{id} ReimbursementController@update Update reimbursement using multipart/form-data.
DELETE /api/reimbursements/{id} ReimbursementController@destroy Delete reimbursement and associated GCS attachments.
PATCH /api/reimbursements/{id}/approve-final ReimbursementController@approveFinal Approve reimbursement and schedule disbursement date.
PATCH /api/reimbursements/{id}/pay ReimbursementController@markAsPaid Mark reimbursement as paid and deduct allocation.

Implementation Notes

Routing

Endpoint routing didefinisikan di routes/api.php, sementara route web default hanya mengarahkan ke halaman ini.

Respons JSON Standar

Semua response melampirkan struktur success/code/message/result, serta pagination payload jika koleksi paginasi dikembalikan.

Media & File Storage

Reimbursement attachment menggunakan GoogleCloudStorageService untuk upload file dan menyimpan metadata di tabel attachments.

Pipeline Otomatis

Flow otomatis saat quotation approved memastikan data operasional ERP terhubung dan meminimalkan pekerjaan manual.