Skip to content

Reporting (Crystal Reports)

Reporting is a first-class, large part of the system: 101 .rpt report layouts ship in the Inventory project alone. All reports are rendered with Crystal Reports for .NET.

How reporting is wired

Each report is three co-located artifacts plus a shared print dialog:

flowchart LR
    subgraph Family["A report family folder (e.g. Laporan/LPP/)"]
        RPT["Xxx.rpt<br/>(Crystal layout)"]
        CLS["Xxx.vb<br/>(auto-generated ReportClass)"]
        VW["frmLapXxx.vb<br/>(viewer/launcher form)"]
    end
    DATA["Data feed<br/>(SQL builder OR temp table)"] --> RPT
    VW -->|"ReportSource = new Xxx()"| CRV["CrystalReportViewer"]
    VW -->|"push ParameterFields"| RPT
    CRV --> PRINT["frmCetakForm.vb<br/>(shared print dialog → PrintToPrinter)"]
    style Family fill:#ede7f6,stroke:#673ab7
Artifact Role
Xxx.rpt The Crystal layout file.
Xxx.vb Auto-generated class — Inherits ReportClass, exposes ResourceName, layout sections, and Parameter_* fields (e.g. Parameter_UserId, Parameter_KodeCabang, Parameter_Kategori). A CachedXxx companion implements ICachedReport.
frmLapXxx.vb Per-family viewer form; news up the report class, binds it to a CrystalReportViewer, and pushes parameters.
frmCetakForm.vb Shared print dialog — resolves paper size and calls PrintToPrinter(...) (F8 = print, Esc = close).
FrmWait.vb Shared wait spinner during generation.

Uses CrystalDecisions.CrystalReports.Engine / .Shared / .ReportSource.

Two ways data reaches a report

flowchart TD
    subgraph A["① SQL-builder classes"]
        SB["FrameWork.SmartSoft.Laporan/*.vb<br/>build SQL by StringBuilder"]
    end
    subgraph B["② Temp-table staging"]
        TB["Class/ProsesLaporanPenjualan.vb<br/>DELETE + repopulate tbTemp_LapPenjualan"]
    end
    SB --> RPT[".rpt reads the result set"]
    TB --> RPT
    style A fill:#e3f2fd,stroke:#1976d2
    style B fill:#fff3e0,stroke:#f57c00
  1. SQL-builder classes — in FrameWork.SmartSoft.Laporan/, report SQL is concatenated with StringBuilder and exposed via write-only properties (KodeCabang, TglAwal/ TglAkhir, Div/Dept/Kat, GroupByCabang):
    • LaporanPurchaseOrder — PO reports (DetailPOperNoBukti, RekapPOperNoBukti, RekapPOperDivDeptKat, RekapPOperTanggal).
    • PenjualanMarginProfitLaporanMarginMinus (sales below cost, honouring TipeHPP = last cost vs average cost).
  2. Temp-table stagingClass/ProsesLaporanPenjualan.vb is the canonical builder: DetailPenjualanPerBarang() clears and repopulates tbTemp_LapPenjualan (keyed USERID+LAPID) from tbTr_Penjualan_H/_D joined to master tables, driving a progress bar; the .rpt then reads that temp table.

Typed datasets back the reports: DataSet1.xsd (shared), plus DataSetTransaksi.xsd, DataSetTemporary.xsd, and Form/Transaksi/Kasir/dsDetail.xsd.

Report data sources

Reports are read-only over the transaction tables — there are no report-specific tables except temp staging. This diagram maps the main report families to the tables they read (so a wrong number leads you straight to the upstream table):

flowchart LR
    subgraph Src["Source tables"]
        PJ[("tbTr_Penjualan_H/_D")]
        PO[("tbTr_PurchaseOrder_H/_D")]
        BO[("tbTr_BackOffice_H/_D")]
        ST[("tbMaster_Stock")]
        OP[("tbTr_StockOpname_H/_D")]
        BR[("tbMaster_Barang")]
    end
    subgraph Rep["Report families"]
        R1["LPP / Margin<br/>(sales analysis)"]
        R2["Pembelian / PO"]
        R3["Bukti<br/>(transaction proofs)"]
        R4["Stock / KartuStock"]
        R5["StockOpname"]
        R6["Barang"]
    end
    PJ --> R1
    BR --> R1
    PO --> R2
    BO --> R3
    ST --> R4
    OP --> R5
    BR --> R6
    R1 -.stages via.-> TMP[("tbTemp_LapPenjualan")]
    style Src fill:#e0f2f1,stroke:#00897b
    style TMP fill:#fff3e0,stroke:#fb8c00

Report families

Report families are organised by folder under INVENTORY/Form/Laporan/ — the folder name is the family.

Family Representative reports
Barang (item master) Barang, BarangExpired, BarangPerSupplier, BarangPhoto
Stock KartuStock (stock card), StockBarang, StockOut
StockOpname (physical count) LHSO / ReLHSO / CheckerLHSO, LKSO, CHKSO, NBH
Pembelian (purchase) BuktiPembelian, BuktiTerimaPembelian
PermintaanBarang / PO BuktiPurchaseOrder(+Image/TanpaHarga), BuktiUsulanOrder, ListPurchaseOrder
SalesOrder BuktiPB, FormDO, FormInvoice, FormPengambilanBarang, FormSuratJalan
SuratJalan (delivery note) SuratJalan, FormSJS, FormInvoiceMutasi, FormPindahGudang
LPP (product/sales-purchase analysis) AnalisaProduk, LPPByDivisi/KodeBarang/Supplier
HargaJual (price change) PerubahanHargaJual, InstruksiCetakBarcode/PriceTag
Hutang (payables) TandaTerimaTukarFaktur
PemusnahanBarang (disposal) BeritaAcaraPemusnahan, ListPemusnahanBarang
PinjamanBarang / TitipBarang DetailPinjamanBarang; FormTitipBarang, FormAmbilBarang
Voucher BuktiPenerimaanVoucher
Bukti (transaction proofs — largest) BuktiBarangHilang, BuktiMPP, BuktiMutasiGudang, BuktiPemakaianSendiri, BuktiRePacking, BuktiReturBarang, RekapResetKasir, TandaTerimaService, …
eMail MarginMinusPerBarang (emailed)

Additional .rpt live outside this tree, e.g. Form/Utility/PriceTag/ and Form/Utility/Complain/Laporan/.

Reports read, they don't post

Reports are read-only views over the same tables the transactions write. A "report is wrong" bug is almost always upstream — a posting or a stock recompute — not the .rpt. Reproduce the underlying query first (the SQL-builder class or the temp-table populate) before touching the layout.