Aturan Diskon Penjualan

Panduan membuat rule harga jual, diskon item, dan diskon faktur penjualan dengan rumus yang dieksekusi oleh ExpressionCalc.

Rute Menu

Umum Aturan-aturan

/form/salesdiscrules

Kapan Form Ini Dipakai

Form ini dipakai untuk membuat master aturan diskon penjualan. Aturan tidak langsung membuat transaksi; aturan akan dibaca oleh transaksi penjualan saat produk atau customer yang dipilih memiliki rule terkait.

Harga Jual Item
Mengubah harga jual baris barang berdasarkan produk, customer, salesman, satuan, jumlah, atau subtotal sementara.
Diskon Item
Memberi diskon persen atau nominal per unit di detail Sales, Sales Order, POS, Table Order, dan Shop.
Diskon Faktur
Memberi diskon persen atau nominal di level header transaksi berdasarkan gross penjualan dan ringkasan brand, supplier, factory, atau product group.
Rule ini khusus penjualan. Diskon pembayaran, reward produk, dan reward poin memakai form rule lain.

Gambaran Sistem

  1. Pengguna membuat rule di /form/salesdiscrules.
  2. Rule kategori Product dipasang di master Produk. Master Customer juga harus memiliki daftar rule agar perhitungan harga/diskon item dipanggil dari layar transaksi.
  3. Rule kategori Transaction dipasang di master Customer untuk menghitung diskon faktur.
  4. Saat transaksi berubah, frontend memanggil POST /salespriceformula untuk detail item dan POST /salesinvoiceformula untuk diskon header.
  5. Backend mengambil rumus dari tabel salesdiscrules, memasukkan variabel ke ExpressionCalc, lalu hasilnya dikirim balik ke form transaksi.
Jika beberapa rule dengan jenis yang sama aktif, nilai terakhir yang dievaluasi akan menimpa nilai sebelumnya. Buat satu rule final untuk setiap kebutuhan, atau gabungkan logika bertingkat di satu rumus.

Prasyarat Sebelum Membuat Rule

Package discount_management aktif agar field rule tampil di master Customer dan Produk.
Produk, Customer, Salesman, dan satuan produk sudah benar karena field tersebut menjadi sumber variabel rumus.
Harga jual, diskon default, dan harga berdasarkan quantity di master Units sudah diisi bila akan dipakai di rumus.
User yang menulis rumus memahami bahwa hasil rumus harus berupa angka untuk harga atau diskon.

Alur Pengisian

  1. Buka menu Umum, Aturan-aturan, lalu Aturan Diskon Penjualan.
  2. Klik Tambah untuk rule baru.
  3. Isi Kode, Deskripsi, dan Tampilan Nama.
  4. Pilih Kategori: Product untuk rule baris barang, atau Transaction untuk rule diskon faktur.
  5. Pilih Jenis: Sales Price, Percent Disc, atau Value Disc.
  6. Pakai field Variabel yang tersedia untuk menyalin nama variabel yang valid ke clipboard.
  7. Pakai field Fungsi yang tersedia bila membutuhkan fungsi seperti round atau stackeddiscount.
  8. Tulis rumus di editor Formula. Rumus harus mengembalikan satu nilai, bukan beberapa statement.
  9. Simpan rule.
  10. Pasang rule ke Produk atau Customer sesuai kategorinya, lalu uji di transaksi Sales, Sales Order, POS, Table Order, atau Shop.

Field Form

Field Wajib Penjelasan
Kode (id) Ya Kode numerik rule. Kode ini yang disimpan di JSON field salesdiscrules pada Customer atau Produk.
Deskripsi (description) Ya Nama panjang rule. Gunakan nama yang menjelaskan kondisi dan hasil rule, misalnya "Diskon grosir 12 pcs".
Nama Tampilan (displayname) Ya Nama pendek maksimal 20 karakter. Dipakai untuk tampilan ringkas.
Kategori (category) Ya Product untuk perhitungan item. Transaction untuk perhitungan diskon faktur.
Jenis (kind) Ya Sales Price menghasilkan harga jual baru. Percent Disc menghasilkan diskon persen. Value Disc menghasilkan diskon nominal.
Rumus (formula) Ya Ekspresi perhitungan yang dievaluasi oleh ExpressionCalc. Editor memakai mode JavaScript, tetapi evaluator backend memakai parser PHPExpression.
Variabel (variables) Tidak Autocomplete variabel dari vw_salesdiscrules. Saat dipilih, nilai variabel disalin ke clipboard.
Fungsi (functions) Tidak Daftar fungsi rumus. Saat dipilih, template fungsi disalin ke clipboard.
Audit (usercreate, useredit, updatetimestamp) Tidak Field audit otomatis.
Form ini tidak memiliki detail table. Semua pengaruh rule berasal dari field header rule dan rumusnya.

Pemasangan Rule ke Master Data

Di master Produk, field Sales Disc mengambil pilihan dari salesdiscrules dengan category=0. Rule kategori Product dipakai oleh SalesPriceFormula.

Di layar transaksi, rumus item dipanggil bila produk yang dipilih memiliki rule dan customer yang dipilih juga memiliki daftar rule diskon penjualan. Implementasi backend saat ini mengevaluasi daftar rule dari Produk untuk perhitungan item.

Di master Customer, field Sales Disc dapat menyimpan rule diskon penjualan. Rule kategori Transaction dipakai oleh SalesInvoiceFormula untuk diskon faktur.

Jika Customer tidak memiliki rule, sistem tidak memanggil rumus diskon faktur dan memakai input diskon manual yang ada di transaksi.

Field rule juga ada di Customer Group dan Product Group. Saat data customer atau produk memakai group tertentu, group dapat menjadi sumber default rule sesuai proses master data yang ada di aplikasi.

Cara Rumus Bekerja di Backend

Kategori Product

Endpoint POST /salespriceformula menerima customer, salesman, product, unit, detail, dan salestotal. Backend mengambil rule dari product.salesdiscrules. Hasil rule dikirim sebagai salesprice, percentdisc, atau valuedisc.

Jenis Efek di transaksi Catatan
Sales Price Menimpa harga jual item. Hasil 0 berarti harga menjadi 0 di Shop/POS baru. Di form legacy, hasil kosong atau 0 tidak menimpa harga.
Percent Disc Menimpa persen diskon item, lalu nominal diskon dihitung dari persen x harga x qty. Gunakan angka persen, misalnya 5 untuk 5 persen.
Value Disc Menimpa nominal diskon per unit, lalu dikalikan quantity transaksi. Jangan kembalikan total diskon satu baris kecuali memang ingin dikalikan lagi dengan quantity.

Kategori Transaction

Endpoint POST /salesinvoiceformula membaca rule dari customer.salesdiscrules. Backend hanya memakai rule kategori Transaction dengan jenis Percent Disc atau Value Disc.

Jenis Efek di transaksi Catatan
Sales Price Tidak dipakai untuk kategori Transaction. Gunakan jenis ini hanya untuk kategori Product.
Percent Disc Menimpa persen diskon faktur, lalu nominal diskon dihitung dari persen x salesgross. Hasil 5 berarti diskon faktur 5 persen.
Value Disc Menimpa nominal diskon faktur. Jika value disc dikembalikan, persen diskon dihitung ulang dari value disc / salesgross.

Variabel yang Tersedia

Daftar variabel diambil dari view vw_salesdiscrules. Nama variabel mengikuti nama kolom database, sehingga contoh di bawah adalah pola utama; pilihan lengkap dapat dicari lewat field Variabel yang tersedia di form.

Kategori Product
  • product.[kolom], misalnya product.productgroup
  • customer.[kolom], misalnya customer.pricelevel
  • salesman.[kolom], misalnya salesman.id
  • unit.[kolom], misalnya unit.salesprice1, unit.salesdisc
  • detail.[kolom], misalnya detail.salesqty, detail.price
  • salestotal, subtotal transaksi saat ini
Kategori Transaction
  • customer.[kolom], misalnya customer.customergroup
  • salesman.[kolom], misalnya salesman.id
  • sales.[kolom], misalnya sales.division
  • salesgross, total sebelum diskon faktur
  • brandsummary["BRAND01"], total net amount untuk brand tertentu
  • suppliersummary["S001"], total net amount untuk supplier tertentu
  • factorysummary["F001"], total net amount untuk factory tertentu
  • productgroupsummary["PG001"], total net amount untuk product group tertentu
View autocomplete menampilkan pola detail.[kolom] untuk kategori Transaction, tetapi implementasi SalesInvoiceFormula saat ini tidak memasukkan variabel detail ke evaluator. Untuk rule faktur, gunakan salesgross atau summary array.

Fungsi dan Sintaks Rumus

ExpressionCalc memakai parser PHPExpression. Rumus ditulis sebagai ekspresi tunggal dan dapat memakai operator aritmatika, perbandingan, logika, ternary, akses properti dengan titik, serta akses array dengan bracket.

Kebutuhan Sintaks
Aritmatika +, -, *, /, %, **
Perbandingan ==, !=, ===, !==, >, >=, <, <=
Logika &&, ||, !
Kondisi kondisi ? nilai_jika_benar : nilai_jika_salah
Properti customer.customergroup, unit.salesprice1, detail.salesqty
Array summary brandsummary["BRAND01"], suppliersummary["S001"]
String "GROSIR" atau 'GROSIR'
Fungsi Angka
round, floor, ceil, abs, is_infinite, is_nan, is_finite
Fungsi Teks dan Array
trim, ltrim, rtrim, str_replace, implode, join, explode, isset
Waktu Saat Ini
currentday, currentmonth, currentyear, currenthour, currentminute, currentsecond
Diskon Bertingkat
stackeddiscount(30, 40, 50) menghitung diskon susun, bukan penjumlahan 30 + 40 + 50.

Contoh Rumus

Gunakan Kategori Product dan Jenis Sales Price.

detail.salesqty >= 12 ? unit.salesdiscprice1 : unit.salesprice1

Jika quantity minimal 12, harga memakai salesdiscprice1; selain itu memakai harga jual level 1.

Gunakan Kategori Product dan Jenis Percent Disc.

customer.customergroup == "GROSIR" ? stackeddiscount(unit.salesdisc, 5) : unit.salesdisc

Jika customer termasuk group GROSIR, diskon default satuan digabung dengan diskon tambahan 5 persen secara bertingkat.

Gunakan Kategori Product dan Jenis Value Disc.

detail.salesqty >= 10 ? 2500 : 0

Hasil 2500 adalah diskon per unit. Jika pengguna membeli 10 unit, nilai diskon baris menjadi 25.000.

Gunakan Kategori Transaction dan Jenis Percent Disc.

salesgross >= 1000000 ? 2 : 0

Jika gross penjualan minimal 1.000.000, sistem memberi diskon faktur 2 persen.

Gunakan Kategori Transaction dan Jenis Value Disc.

brandsummary["BRAND01"] >= 500000 ? 25000 : 0

Jika total net amount barang dari brand BRAND01 minimal 500.000, sistem memberi diskon faktur 25.000.

Gunakan kategori dan jenis sesuai kebutuhan promo.

currentmonth == 12 ? 3 : 0

Rumus ini mengembalikan 3 pada bulan Desember. Jika jenisnya Percent Disc, artinya diskon 3 persen.

Checklist Uji Coba

Masalah Umum

Periksa apakah rule kategori Product sudah dipasang di Produk, Customer memiliki daftar Sales Disc rule, dan transaksi memakai produk serta customer yang sama. Perhitungan item mengambil rumus dari product.salesdiscrules.

Pastikan rule kategori Transaction dipasang di Customer dan jenisnya Percent Disc atau Value Disc. Jenis Sales Price tidak dipakai oleh perhitungan diskon faktur.

Untuk kategori Product dan jenis Value Disc, rumus harus mengembalikan diskon per unit. Sistem akan mengalikan hasil rumus dengan quantity baris.

Gunakan nama variabel dari autocomplete. Untuk summary array, gunakan bracket dan tanda kutip seperti brandsummary["BRAND01"]. Untuk rule faktur, hindari detail.[kolom] karena variabel detail belum dimasukkan ke evaluator invoice.

Backend mengevaluasi rule satu per satu dan menyimpan hasil ke variabel salesprice, percentdisc, atau valuedisc. Jika beberapa rule memakai jenis yang sama, hasil rule terakhir akan menjadi hasil akhir.