Nalala Store - Dokumen Spesifikasi Skripsi

E-Commerce Tas Fashion, Paket Usaha Reseller & Logistik J&T (24 Model Basis Data)
DOKUMEN SPESIFIKASI REKAYASA PERANGKAT LUNAK DAN BASIS DATA

PERANCANGAN DAN PENGUJIAN SISTEM
E-COMMERCE NALALA STORE

Penjualan Tas Fashion Berbasis Paket Usaha Reseller (Kuota Flat 11 Pcs), Simulasi Interaktif 3D Bag Capacity Checker, dan Logistik Terpadu J&T Express

Stack: Next.js 15 (App Router, Tailwind CSS) + Express.js REST API + MySQL 8.0 (Prisma ORM 24 Model) + J&T Express API Oktober 2026

Gunakan navigasi Daftar Isi di sebelah kiri untuk berpindah bab. Seluruh diagram dilengkapi tombol "Lihat Kode Mermaid" dan "Salin Kode Mermaid" serta tabel penjelasan akademis.

BAB I - PENDAHULUAN

Bab ini menguraikan latar belakang pengembangan sistem e-commerce Nalala Store, perumusan masalah bisnis dan teknis, tujuan pengembangan, manfaat yang diharapkan, batasan masalah, dan diagram alir operasional utama (Master Flowchart).

1.1 Latar Belakang

Nalala Store merupakan bisnis perdagangan ritel dan grosir tas fashion wanita yang beroperasi secara dinamis dengan ragam koleksi produk mencakup sling bag, shoulder bag, tote bag, dan tas ransel wanita. Dalam perkembangannya, model operasional konvensional berbasis komunikasi pesan instan manual menghadapi empat kendala utama:

  1. Pendaftaran dan Pembelian Paket Usaha Reseller Tidak Terstruktur: Calon mitra grosir harus menghubungi admin secara manual melalui aplikasi pesan WhatsApp untuk menanyakan ketersediaan produk paket usaha dan melakukan negosiasi harga. Hal ini memicu antrean verifikasi yang lambat dan risiko ketidakteraturan kuota pemilihan tas.
  2. Ketidakpastian Kapasitas Muatan Tas bagi Calon Pembeli Online: Pembeli tas fashion sering mengurungkan niat transaksi karena kesulitan mengestimasi apakah tas yang diminati mampu menampung barang bawaan kerja atau kuliah harian (seperti laptop 14 inci, botol air minum 600ml, pouch kosmetik, dan mukena travel).
  3. Pengelolaan Pembayaran Transfer Multi-Rekening yang Rawan Selisih: Transaksi pelanggan yang mentransfer dana ke rekening toko (BCA, Mandiri, serta QRIS dinamis) memerlukan verifikasi mutasi bank yang ketat terhadap struk bukti bayar guna mencegah terjadinya pemalsuan bukti transfer (struk fiktif).
  4. Penghitungan Ongkos Kirim dan Penerbitan Resi Logistik Terpisah: Admin harus menghitung bobot produk dan tarif kurir secara terpisah serta menyalin nomor resi (*Air Waybill*) J&T Express secara manual ke pelanggan, sehingga rawan salah ketik dan menunda pelacakan pengiriman.

Untuk menyelesaikan kendala-kendala tersebut, dibangun platform e-commerce komprehensif dengan arsitektur modern berorientasi layanan: Next.js 15 pada sisi presentasi antarmuka, Node.js Express.js pada backend API, serta MySQL 8.0 dengan Prisma ORM melalui perancangan 24 model entitas basis data terpadu.

1.2 Rumusan Masalah

  1. Bagaimana merancang arsitektur basis data relasional (24 model) yang mampu mengakomodasi transaksi satuan, paket usaha reseller kuota flat 11 pcs, dan pelacakan riwayat voucher promosi?
  2. Bagaimana mengimplementasikan kalkulator daya tampung tas interaktif (3D Bag Capacity Checker) berbasis batas toleransi dimensi tiga dimensi (PxLxT) dan volume kubikasi liter?
  3. Bagaimana merancang keranjang belanja bersekat (Cart Sections) yang mampu mengunci komposisi paket reseller tepat 11 item tas tanpa mencampurkan kalkulasi diskon belanja reguler?
  4. Bagaimana mengintegrasikan kalkulasi tarif ekspedisi J&T Express (layanan EZ dan CARGO) berbasis bobot akumulasi gram dan penerbitan nomor resi AWB secara otomatis saat pembayaran disetujui?
  5. Bagaimana membuktikan keandalan logika persetujuan pembayaran dan pencegahan fraud melalui pengujian perangkat lunak standar White Box (Basis Path Testing) dan Black Box (Equivalence Partitioning & BVA)?

1.3 Tujuan Pengembangan

  1. Membangun platform e-commerce Nalala Store dengan dukungan penuh terhadap transaksi belanja satuan pelanggan dan skema Paket Usaha Reseller.
  2. Menyediakan fitur visualisasi Capacity Checker 3D untuk memberikan kepastian daya muat produk tas sebelum pembeli menyelesaikan pesanan.
  3. Mengintegrasikan modul logistik kurir J&T Express (layanan EZ dan CARGO) dengan perhitungan pembulatan bobot gram otomatis.
  4. Mengembangkan modul verifikasi pembayaran multi-rekening (BCA, Mandiri, QRIS) dengan panel audit admin yang terhubung langsung ke pencetakan resi AWB J&T Express.
  5. Menyusun dokumentasi rekayasa perangkat lunak standar akademik yang konsisten mulai dari pemodelan basis data (ERD, LRS, Kamus Data) hingga diagram UML dan pengujian sistem.

1.4 Manfaat Sistem

  • Bagi Toko Nalala Store: Mengotomatisasi validasi kuota grosir reseller, mempercepat verifikasi mutasi rekening koran, mencegah kehabisan stok melalui transaksi atomik, dan menerbitkan resi logistik dalam hitungan detik.
  • Bagi Pelanggan & Mitra Reseller: Mendapatkan simulasi nyata kapasitas tas sebelum membeli, transparansi biaya kirim J&T Express, serta kemudahan upload struk bukti bayar dan live tracking posisi paket.
  • Bagi Akademik: Memberikan referensi implementasi rekayasa perangkat lunak e-commerce yang utuh dengan konsistensi 24 model persisten pada ERD konseptual, LRS fisik, dan UML Class Diagram.

1.5 Batasan Masalah

  • Metode pembayaran didasarkan pada transfer manual rekening bank toko resmi (BCA, Mandiri) dan QRIS toko dengan pengunggahan bukti bayar struk dan verifikasi persetujuan admin.
  • Mitra kurir logistik yang terintegrasi secara bawaan adalah J&T Express dengan opsi layanan EZ (Reguler) dan CARGO (Grosir bobot besar ≥ 5 Kg).
  • Skema Paket Usaha Reseller berfokus pada kuota wajib tepat 11 item tas varian pilihan dengan penetapan harga flat bundle terkonfigurasi.
  • Fitur Capacity Checker 3D menguji kelayakan tampung berdasarkan perbandingan batas dimensi fisik (panjang, lebar, tinggi) dan volume liter antara tas dan master barang bawaan preset_bag_capacities.
  • Hak akses sistem terbagi atas tiga peran pengguna (RBAC): CUSTOMER (Pelanggan Umum), RESELLER (Mitra Grosir), dan ADMIN (Pengelola Toko).

1.6 Master Flowchart Operasional Layanan

Diagram alir di bawah ini menyajikan seluruh rangkaian proses operasional sistem Nalala Store dari penjelajahan katalog, simulasi muatan 3D, pemilihan paket reseller, checkout terpadu, hingga verifikasi transfer dan penyerahan paket ke ekspedisi J&T Express:

Master Flowchart Operasional Layanan E-Commerce & Paket Usaha Nalala Store
flowchart TD START([Pengunjung Membuka Website Nalala]) --> CHOOSE_PATH{Pilih Mode Belanja} %% JALUR 1: BELANJA SATUAN REGULER & CAPACITY CHECKER CHOOSE_PATH -->|Belanja Satuan Reguler| DETAIL_PROD["Buka Detail Produk Tas
(Foto, Deskripsi, Dimensi 3D)"] DETAIL_PROD --> OPEN_CAP{Gunakan Fitur
Capacity Checker?} OPEN_CAP -->|Ya| SELECT_PRESET["Pilih Preset Barang:
Laptop, Botol, Pouch, Buku"] SELECT_PRESET --> CALC_3D["Kalkulasi Dimensi 3D (PxLxT)
& Toleransi Volume Liter"] CALC_3D --> CHECK_FIT{Barang Muat
di Dalam Tas?} CHECK_FIT -->|Muat / Sesuai| SHOW_FIT["Tampilkan Status Hijau (FIT)
& Visualisasi 3D"] CHECK_FIT -->|Overload / Tidak Muat| SHOW_WARN["Tampilkan Status Merah (OVERLOAD)
& Peringatan Batas Dimensi"] SHOW_FIT --> ADD_CART_REG["Masukkan Produk ke Keranjang
(cart_items dengan section NULL)"] SHOW_WARN --> ADD_CART_REG OPEN_CAP -->|Tidak| ADD_CART_REG %% JALUR 2: PAKET USAHA RESELLER (KUOTA FLAT 11 PCS) CHOOSE_PATH -->|Paket Usaha Reseller| BROWSE_PAKET["Buka Halaman Paket Usaha Reseller
(Aturan Kuota Wajib 11 Pcs)"] BROWSE_PAKET --> PICK_11["Pilih Kombinasi Varian Tas
(Total Wajib Tepat 11 Pcs)"] PICK_11 --> CHECK_KUOTA{Jumlah Item
Tepat 11 Pcs?} CHECK_KUOTA -->|Kurang / Lebih| WARN_KUOTA["Validasi Gagal:
Tampilkan Sisa Kuota (n/11)"] WARN_KUOTA --> PICK_11 CHECK_KUOTA -->|Tepat 11 Pcs| ADD_CART_PAKET["Simpan ke Keranjang
(cart_sections & 11 baris cart_items)"] %% KERANJANG & CHECKOUT TERPADU ADD_CART_REG --> VIEW_CART["Buka Halaman Keranjang Belanja
(Pemisahan Section Reguler & Paket)"] ADD_CART_PAKET --> VIEW_CART VIEW_CART --> PROCEED_CHECKOUT["Lanjut ke Halaman Checkout"] PROCEED_CHECKOUT --> SELECT_ADDR["Pilih Alamat Pengiriman
(user_addresses / Destinasi J&T)"] SELECT_ADDR --> CALC_WEIGHT["Hitung Akumulasi Berat Total (gram)
& Dimensi Paket"] CALC_WEIGHT --> PICK_COURIER["Pilih Layanan J&T Express:
J&T EZ (Reguler) atau J&T CARGO (Grosir)"] PICK_COURIER --> APPLY_VOUCHER{Gunakan Voucher
Diskon / Ongkir?} APPLY_VOUCHER -->|Ya| VALIDATE_VOUCHER["Validasi Min. Spend & Kuota
(Hitung net_total = Subtotal + Ongkir - Diskon)"] APPLY_VOUCHER -->|Tidak| NET_CALC["Hitung net_total = Subtotal + Ongkir"] VALIDATE_VOUCHER --> CREATE_ORDER["Terbitkan Pesanan (Status: PENDING_PAYMENT)
Generate Order Number & Countdown 24 Jam"] NET_CALC --> CREATE_ORDER %% PEMBAYARAN & VERIFIKASI ADMIN CREATE_ORDER --> PAY_TRANSFER["Pembeli Transfer ke Rekening Toko
(BCA, Mandiri, atau QRIS Dinamis)"] PAY_TRANSFER --> UPLOAD_RECEIPT["Upload Struk Bukti Transfer
(Status: WAITING_VERIFICATION)"] UPLOAD_RECEIPT --> ADMIN_AUDIT{Admin Cek Mutasi
Rekening & Bukti Valid?} ADMIN_AUDIT -->|Tidak / Bukti Fiktif| REJECT_PAY["Admin Tolak Pembayaran & Beri Alasan
(Status Payment: REJECTED)"] REJECT_PAY --> CHECK_RETRY{Batas Reupload
Terpenuhi? (<= 3x)} CHECK_RETRY -->|Bisa Upload Ulang| UPLOAD_RECEIPT CHECK_RETRY -->|Batas Habis / Batal| CANCEL_ORDER["Admin Batalkan Pesanan
(Status: CANCELLED)"] CANCEL_ORDER --> END_FAIL([Pesanan Dibatalkan]) ADMIN_AUDIT -->|Ya / Mutasi Sesuai| APPROVE_PAY["Admin Setujui Pembayaran
(Status: VERIFIED & Order: PAID)"] APPROVE_PAY --> AUTO_AWB["Generate Resi J&T Express (AWB)
via Modul Logistik shipments"] AUTO_AWB --> PACKING["Admin Packing & Serahkan Paket ke J&T
(Status: PROCESSING -> SHIPPED)"] PACKING --> TRACK_JNT["Pelanggan Lacak Resi Real-Time
(J&T API Tracking Logs)"] TRACK_JNT --> DELIVERED["Paket Diterima Pelanggan
(Status: DELIVERED -> COMPLETED)"] DELIVERED --> END_SUCCESS([Transaksi Selesai & Sukses])
(Dapat disalin & di-render langsung di mermaid.live)

Gambar 1.1 Master Flowchart Alur Operasional Nalala Store

Tabel 1.2 Deskripsi Alur Master Flowchart Operasional Nalala Store

Fase Tahapan Alur Aktivitas & Logika Bisnis Entitas Basis Data Terkait
1 Eksplorasi & Capacity Check Pengunjung mengeksplorasi katalog tas atau membuka modal 3D Capacity Checker untuk menguji kompatibilitas barang bawaan (laptop, botol, pouch) terhadap volume dan batas dimensi fisik produk. products, product_variants, product_images, preset_bag_capacities
2 Kompilasi Paket Reseller Mitra reseller memilih tepat 11 item tas varian untuk mendapatkan harga grosir flat bundle. Sistem memvalidasi jumlah kuota secara real-time sebelum mengizinkan penambahan ke keranjang. reseller_packages, product_reseller_packages, cart_sections, cart_items
3 Keranjang & Checkout Terpadu Keranjang memisahkan item reguler dan paket reseller. Saat checkout, sistem menghitung bobot akumulasi gram, memanggil tarif J&T Express (EZ / CARGO), dan memvalidasi voucher diskon. carts, cart_sections, cart_items, user_addresses, vouchers
4 Pembayaran Transfer & Bukti Struk Pembeli mentransfer nominal net_total ke rekening resmi (BCA/Mandiri/QRIS) dan mengunggah foto struk bukti bayar sebelum tenggat waktu 24 jam berakhir. orders, payments, payment_accounts, user_voucher_usages
5 Verifikasi Mutasi & Penerbitan AWB Admin mencocokkan mutasi bank. Jika valid, sistem otomatis menerbitkan nomor AWB pengiriman J&T Express, memperbarui status menjadi PAID, dan mengirimkan notifikasi. payments, orders, shipments, notifications

BAB II - PERANCANGAN BASIS DATA

Perancangan basis data Nalala Store dikembangkan berdasarkan 24 model entitas persisten pada skema resmi schema.prisma MySQL 8.0, mencakup pengelolaan pengguna, katalog tas berdimensi 3D, paket reseller, keranjang bersekat, pesanan, pembayaran multi-rekening, dan resi logistik J&T Express.

2.1 Entity Relationship Diagram (ERD) Konseptual

Diagram di bawah ini memodelkan hubungan kardinalitas 24 entitas basis data Nalala Store menggunakan notasi Crow's Foot. Entitas PRESET_BAG_CAPACITIES dimodelkan sebagai entitas mandiri (standalone) yang menyediakan master data ukuran barang 3D untuk kalkulasi komparasi:

Entity Relationship Diagram (ERD) Basis Data Nalala Store (Notasi Crow's Foot)
erDiagram USERS ||--o{ USER_SOCIAL_ACCOUNTS : "memiliki_sosial" USERS ||--o{ USER_ADDRESSES : "memiliki_alamat" USERS ||--o{ USER_VERIFICATIONS : "memiliki_verifikasi" USERS ||--o{ USER_TOKENS : "memiliki_token" USERS ||--|| CARTS : "memiliki_keranjang" USERS ||--o{ ORDERS : "membuat" USERS ||--o{ USER_VOUCHER_USAGES : "riwayat_pemakaian" USERS ||--o{ NOTIFICATIONS : "mendapat_notifikasi" CATEGORIES ||--o{ PRODUCTS : "mengelompokkan" PRODUCTS ||--o{ PRODUCT_VARIANTS : "memiliki_varian" PRODUCTS ||--o{ PRODUCT_IMAGES : "memiliki_gambar" PRODUCTS ||--o{ PRODUCT_RESELLER_PACKAGES : "dibundel_dalam" PRODUCTS ||--o{ VOUCHER_PRODUCTS : "terhubung_ke_produk" PRODUCTS ||--o{ CART_ITEMS : "ditaruh_di" PRODUCTS ||--o{ ORDER_ITEMS : "dipesan_dalam" PRODUCT_VARIANTS ||--o{ CART_ITEMS : "varian_dipilih" PRODUCT_VARIANTS ||--o{ ORDER_ITEMS : "varian_dibeli" PRODUCT_VARIANTS ||--o{ PRODUCT_IMAGES : "gambar_varian" RESELLER_PACKAGES ||--o{ PRODUCT_RESELLER_PACKAGES : "bundle_produk" RESELLER_PACKAGES ||--o{ CART_SECTIONS : "diterapkan_pada" CARTS ||--o{ CART_SECTIONS : "membagi_section" CARTS ||--o{ CART_ITEMS : "memuat_satuan" CART_SECTIONS |o--o{ CART_ITEMS : "memuat_paket" VOUCHERS ||--o{ VOUCHER_PRODUCTS : "digunakan_pada" VOUCHERS ||--o{ USER_VOUCHER_USAGES : "dicatat_pemakaian" ORDERS ||--o{ ORDER_ITEMS : "memuat_rincian" ORDERS ||--|| PAYMENTS : "memiliki_transaksi" ORDERS ||--|| SHIPMENTS : "menghasilkan_logistik" PAYMENT_ACCOUNTS ||--o{ PAYMENTS : "menerima_ke" USERS { bigint id PK string email UK string phone_number UK string name string role boolean is_active datetime created_at } USER_SOCIAL_ACCOUNTS { bigint id PK bigint user_id FK string provider string provider_user_id } USER_ADDRESSES { bigint id PK bigint user_id FK string recipient_name string phone_number string city string postal_code boolean is_primary } USER_VERIFICATIONS { bigint id PK bigint user_id FK string type string token boolean is_used datetime expires_at } USER_TOKENS { bigint id PK bigint user_id FK string token_hash UK datetime expires_at } CATEGORIES { bigint id PK bigint parent_id FK string name string slug UK boolean is_active } PRODUCTS { bigint id PK bigint category_id FK string name string slug UK int weight_grams decimal base_price_customer decimal base_price_reseller decimal length_cm decimal width_cm decimal height_cm decimal volume_liters string reseller_package_type boolean is_active } PRODUCT_VARIANTS { bigint id PK bigint product_id FK string color_name string sku UK int stock decimal price_adjustment } PRODUCT_IMAGES { bigint id PK bigint product_id FK bigint variant_id FK string image_url boolean is_primary } PRESET_BAG_CAPACITIES { bigint id PK string name string category decimal length_cm decimal width_cm decimal height_cm decimal volume_liters boolean is_rigid } RESELLER_PACKAGES { bigint id PK string name string slug UK decimal package_price int required_quantity boolean is_active } PRODUCT_RESELLER_PACKAGES { bigint id PK bigint product_id FK bigint reseller_package_id FK } VOUCHERS { bigint id PK string code UK string title string type string discount_type decimal discount_value decimal min_spend string applicable_to int quota_total int quota_used boolean is_active } VOUCHER_PRODUCTS { bigint id PK bigint voucher_id FK bigint product_id FK } USER_VOUCHER_USAGES { bigint id PK bigint user_id FK bigint voucher_id FK datetime used_at } CARTS { bigint id PK bigint user_id FK_UK datetime updated_at } CART_SECTIONS { bigint id PK bigint cart_id FK bigint reseller_package_id FK } CART_ITEMS { bigint id PK bigint cart_id FK bigint cart_section_id FK bigint product_id FK bigint variant_id FK int quantity } ORDERS { bigint id PK string order_number UK bigint user_id FK string status decimal regular_subtotal decimal package_subtotal decimal discount_product_total decimal shipping_fee decimal net_total int total_weight_grams json shipping_address } ORDER_ITEMS { bigint id PK bigint order_id FK bigint product_id FK bigint variant_id FK string product_name string color_name string sku decimal unit_price int quantity decimal total_price } PAYMENTS { bigint id PK bigint order_id FK_UK bigint payment_account_id FK decimal amount string status string proof_image_url datetime verified_at } PAYMENT_ACCOUNTS { bigint id PK string type string provider_name string account_number string account_holder_name boolean is_active } SHIPMENTS { bigint id PK bigint order_id FK_UK string waybill_number UK string courier_name string service_type string status json tracking_logs } NOTIFICATIONS { bigint id PK bigint user_id FK string title string type boolean is_read datetime created_at }
(Dapat disalin & di-render langsung di mermaid.live)

Gambar 2.1 Entity Relationship Diagram (ERD) Basis Data Nalala Store (24 Entitas)

Tabel 2.1 Deskripsi Entitas dan Kardinalitas ERD Nalala Store

No Entitas Asal Entitas Tujuan Kardinalitas Deskripsi Hubungan Bisnis
1 users user_social_accounts 1 : N Satu akun pengguna dapat menautkan nol atau banyak akun autentikasi OAuth (Google, Apple).
2 users user_addresses 1 : N Satu pengguna dapat menyimpan banyak alamat pengiriman ekspedisi J&T Express.
3 users user_verifications 1 : N Satu pengguna dapat memiliki riwayat banyak token verifikasi OTP email/WhatsApp.
4 users user_tokens 1 : N Satu pengguna dapat login pada beberapa perangkat dengan token sesi berbeda.
5 users carts 1 : 1 Setiap pengguna memiliki tepat satu keranjang belanja persisten (One-to-One).
6 users orders 1 : N Satu pengguna dapat melakukan pemesanan transaksi belanja berkali-kali.
7 users user_voucher_usages 1 : N Pencatatan riwayat klaim voucher oleh pengguna untuk validasi batas kuota per akun.
8 users notifications 1 : N Satu pengguna dapat menerima banyak pesan pemberitahuan status dan promo.
9 categories products 1 : N Satu kategori tas fashion menaungi banyak produk tas terkait.
10 products product_variants 1 : N Satu produk tas memiliki banyak varian warna dengan SKU dan kuantitas stok terpisah.
11 products product_images 1 : N Satu produk tas memiliki banyak foto galeri untuk detail tampilan visual.
12 products product_reseller_packages 1 : N Relasi Many-to-Many antara produk dan paket usaha reseller via junction table.
13 products voucher_products 1 : N Relasi Many-to-Many antara voucher spesifik dan daftar produk yang dipromosikan.
14 products cart_items 1 : N Produk tas dapat dimasukkan sebagai item pada keranjang belanja pengguna.
15 products order_items 1 : N Produk tas tercatat sebagai rincian baris pesanan faktur pembelian.
16 product_variants cart_items 1 : N Varian warna spesifik dipilih saat menaruh tas ke dalam keranjang.
17 product_variants order_items 1 : N Varian warna dan SKU dibekukan saat pesanan checkout berhasil dibuat.
18 product_variants product_images 1 : N Foto produk opsional dapat ditautkan secara spesifik ke suatu varian warna.
19 reseller_packages product_reseller_packages 1 : N Paket usaha reseller mendefinisikan koleksi produk tas yang diizinkan untuk dibundel.
20 reseller_packages cart_sections 1 : N Paket usaha diterapkan pada sekat keranjang untuk validasi kuota 11 pcs.
21 carts cart_sections 1 : N Satu keranjang dapat memiliki banyak sekat paket usaha reseller yang sedang disusun.
22 carts cart_items 1 : N Keranjang memuat kumpulan item tas belanja satuan langsung.
23 cart_sections cart_items 0/1 : N Sekat paket usaha mengelompokkan tepat 11 baris item varian tas terpilih.
24 vouchers voucher_products 1 : N Voucher bertipe produk spesifik membatasi diskon pada produk terdaftar.
25 vouchers user_voucher_usages 1 : N Satu voucher mencatat histori klaim oleh banyak pengguna berbeda.
26 orders order_items 1 : N Satu pesanan memuat satu atau lebih baris rincian item barang yang dibeli.
27 orders payments 1 : 1 Setiap pesanan memiliki tepat satu transaksi pembayaran transfer (One-to-One).
28 orders shipments 1 : 1 Setiap pesanan terverifikasi memiliki tepat satu manifes pengiriman J&T (One-to-One).
29 payment_accounts payments 1 : N Rekening resmi toko dapat menerima transfer dari banyak transaksi pembayaran.
30 preset_bag_capacities (Standalone) - Entitas mandiri master data ukuran barang 3D (tidak berelasi langsung via FK).

2.2 Penjelasan Relasi Entitas Basis Data

Analisis keterhubungan antar entitas pada perancangan basis data Nalala Store memiliki beberapa poin arsitektural krusial:

  • Isolasi Riwayat Voucher dari Pesanan (No voucher_id FK on orders): Sesuai kaidah normalisasi dan skema resmi, tabel orders tidak memiliki foreign key langsung ke vouchers. Relasi pemakaian kupon dicatat secara independen pada tabel user_voucher_usages untuk menjaga keutuhan data faktur pesanan meskipun data promosi diubah atau dihapus.
  • Relasi One-to-One Keranjang (users ke carts): Setiap pengguna yang telah mengaktifkan akun memiliki tepat satu keranjang belanja persisten (user_id bersifat UNIQUE pada tabel carts).
  • Pemisahan Section Paket Usaha (carts ke cart_sections): Keranjang belanja dapat menampung transaksi satuan (langsung pada cart_items dengan cart_section_id = NULL) dan transaksi paket reseller (mengelompokkan tepat 11 item tas di bawah cart_sections yang terhubung ke reseller_packages).
  • Relasi One-to-One Transaksi dan Logistik: Satu pesanan (orders) menghasilkan tepat satu rekaman pembayaran transfer (payments, dengan order_id UNIQUE) dan satu manifes logistik ekspedisi (shipments, dengan order_id UNIQUE).

2.3 Aturan Transformasi ERD ke LRS

Proses pemetaan dari Entity Relationship Diagram (ERD) konseptual menjadi Logical Record Structure (LRS) fisik dilakukan mengikuti 4 kaidah formal rekayasa basis data:

Kaidah 1: Relasi One-to-One (1 : 1)

Kunci primer (PK) dari entitas induk disalin sebagai foreign key (FK) yang bersifat UNIQUE pada entitas anak. Contoh: users.id dipetakan sebagai carts.user_id (UQ); orders.id dipetakan sebagai payments.order_id (UQ) dan shipments.order_id (UQ).

Kaidah 2: Relasi One-to-Many (1 : N)

Kunci primer dari entitas pada sisi 'One' (1) disalin sebagai kolom Foreign Key (FK) pada entitas di sisi 'Many' (N). Contoh: categories.id disalin ke products.category_id; products.id disalin ke product_variants.product_id; users.id disalin ke orders.user_id.

Kaidah 3: Relasi Many-to-Many (M : N) Melalui Junction Table

Relasi jamak ke jamak dipecah menjadi dua relasi One-to-Many dengan membentuk tabel perantara (Junction / Bridge Table) yang memuat kombinasi FK dari kedua entitas induk dengan batasan UNIQUE komposit. Contoh: relasi produk tas dan paket reseller dipecah oleh product_reseller_packages; relasi voucher dan produk dipecah oleh voucher_products.

Kaidah 4: Penanganan Entitas Mandiri (Standalone)

Entitas yang tidak memiliki ketergantungan referensial ke tabel transaksi operasional tetap bertransformasi menjadi tabel mandiri dengan primary key unik untuk kebutuhan lookup sistem komparasi. Contoh: entitas preset_bag_capacities yang dibaca oleh modul Capacity Checker 3D.

2.4 Logical Record Structure (LRS) Fisik

Berikut adalah representasi LRS fisik 24 tabel basis data Nalala Store lengkap dengan tipe data MySQL, indikator kunci primer (+PK), kunci tamu (#FK), kunci unik (~UQ), serta arah relasi multiplisitas:

Logical Record Structure (LRS) Skema Fisik Basis Data Nalala Store
classDiagram direction TB class users { +BigInt id PK ~String email UQ ~String phone_number UQ +String name +String role +Boolean is_active +DateTime created_at } class user_social_accounts { +BigInt id PK #BigInt user_id FK +String provider +String provider_user_id } class user_addresses { +BigInt id PK #BigInt user_id FK +String recipient_name +String city +String postal_code +Boolean is_primary } class user_verifications { +BigInt id PK #BigInt user_id FK +String type +String token +Boolean is_used +DateTime expires_at } class user_tokens { +BigInt id PK #BigInt user_id FK ~String token_hash UQ +DateTime expires_at } class categories { +BigInt id PK #BigInt parent_id FK +String name ~String slug UQ +Boolean is_active } class products { +BigInt id PK #BigInt category_id FK +String name ~String slug UQ +Int weight_grams +Decimal base_price_customer +Decimal base_price_reseller +Decimal volume_liters +String reseller_package_type } class product_variants { +BigInt id PK #BigInt product_id FK +String color_name ~String sku UQ +Int stock +Decimal price_adjustment } class product_images { +BigInt id PK #BigInt product_id FK #BigInt variant_id FK +String image_url +Boolean is_primary } class preset_bag_capacities { +BigInt id PK +String name +String category +Decimal volume_liters +Boolean is_rigid } class reseller_packages { +BigInt id PK +String name ~String slug UQ +Decimal package_price +Int required_quantity } class product_reseller_packages { +BigInt id PK #BigInt product_id FK #BigInt reseller_package_id FK } class vouchers { +BigInt id PK ~String code UQ +String type +Decimal discount_value +Decimal min_spend +String applicable_to } class voucher_products { +BigInt id PK #BigInt voucher_id FK #BigInt product_id FK } class user_voucher_usages { +BigInt id PK #BigInt user_id FK #BigInt voucher_id FK +DateTime used_at } class carts { +BigInt id PK #BigInt user_id FK_UQ } class cart_sections { +BigInt id PK #BigInt cart_id FK #BigInt reseller_package_id FK } class cart_items { +BigInt id PK #BigInt cart_id FK #BigInt cart_section_id FK #BigInt product_id FK #BigInt variant_id FK +Int quantity } class orders { +BigInt id PK ~String order_number UQ #BigInt user_id FK +String status +Decimal net_total +Int total_weight_grams +JSON shipping_address } class order_items { +BigInt id PK #BigInt order_id FK #BigInt product_id FK #BigInt variant_id FK +String sku +Int quantity +Decimal total_price } class payments { +BigInt id PK #BigInt order_id FK_UQ #BigInt payment_account_id FK +Decimal amount +String status +String proof_image_url } class payment_accounts { +BigInt id PK +String type +String provider_name +String account_number } class shipments { +BigInt id PK #BigInt order_id FK_UQ ~String waybill_number UQ +String courier_name +String service_type +String status } class notifications { +BigInt id PK #BigInt user_id FK +String title +String type +Boolean is_read } users "1" --> "0..*" user_social_accounts : user_id users "1" --> "0..*" user_addresses : user_id users "1" --> "0..*" user_verifications : user_id users "1" --> "0..*" user_tokens : user_id users "1" --> "1" carts : user_id users "1" --> "0..*" orders : user_id users "1" --> "0..*" user_voucher_usages : user_id users "1" --> "0..*" notifications : user_id categories "1" --> "0..*" products : category_id categories "0..1" --> "0..*" categories : parent_id products "1" --> "0..*" product_variants : product_id products "1" --> "0..*" product_images : product_id products "1" --> "0..*" product_reseller_packages : product_id products "1" --> "0..*" voucher_products : product_id products "1" --> "0..*" cart_items : product_id products "1" --> "0..*" order_items : product_id product_variants "1" --> "0..*" cart_items : variant_id product_variants "1" --> "0..*" order_items : variant_id product_variants "0..1" --> "0..*" product_images : variant_id reseller_packages "1" --> "0..*" product_reseller_packages : reseller_package_id reseller_packages "1" --> "0..*" cart_sections : reseller_package_id carts "1" --> "0..*" cart_sections : cart_id carts "1" --> "0..*" cart_items : cart_id cart_sections "0..1" --> "0..*" cart_items : cart_section_id vouchers "1" --> "0..*" voucher_products : voucher_id vouchers "1" --> "0..*" user_voucher_usages : voucher_id orders "1" --> "1..*" order_items : order_id orders "1" --> "1" payments : order_id orders "1" --> "1" shipments : order_id payment_accounts "1" --> "0..*" payments : payment_account_id
(Dapat disalin & di-render langsung di mermaid.live)

Gambar 2.2 Logical Record Structure (LRS) Fisik Basis Data Nalala Store

Tabel 2.3 Matriks Relasi Foreign Key dan Integritas Referensial LRS

Tabel Anak (Child) Kolom Foreign Key Tabel Induk (Parent) Aksi On Delete Tipe Relasi LRS
user_social_accounts user_id users(id) CASCADE Identifying (1 : N)
user_addresses user_id users(id) CASCADE Identifying (1 : N)
carts user_id users(id) CASCADE One-to-One (1 : 1, Unique)
products category_id categories(id) RESTRICT Non-Identifying (1 : N)
product_variants product_id products(id) CASCADE Identifying (1 : N)
product_reseller_packages product_id, reseller_package_id products, reseller_packages CASCADE Junction M : N
orders user_id users(id) CASCADE Non-Identifying (1 : N)
order_items order_id orders(id) CASCADE Identifying (1 : N)
order_items product_id, variant_id products, product_variants RESTRICT Preserve Historical Data
payments order_id orders(id) CASCADE One-to-One (1 : 1, Unique)
payments payment_account_id payment_accounts(id) RESTRICT Non-Identifying (1 : N)
shipments order_id orders(id) CASCADE One-to-One (1 : 1, Unique)

2.5 Kamus Data Fisik (24 Tabel Basis Data MySQL)

Kamus data fisik merinci secara lengkap spesifikasi atribut kolom, tipe data MySQL, batasan integritas (PK, FK, UQ, NULLABLE, DEFAULT), dan fungsi bisnis pada seluruh 24 model persisten basis data Nalala Store:

Tabel 2.1: Spesifikasi Struktur Tabel users (Model: User)

Menyimpan entitas akun pengguna terpusat untuk seluruh peran hak akses (Customer, Reseller, dan Administrator) serta status verifikasi email dan nomor telepon.

No Nama Kolom Tipe Data MySQL Atribut / Constraint Keterangan Bisnis
1 id BIGINT UNSIGNED PK AUTO_INCREMENT, NOT NULL Kunci primer identitas unik pengguna
2 name VARCHAR(191) NOT NULL Nama lengkap akun pengguna
3 email VARCHAR(191) UQ NOT NULL Alamat surel login pengguna (unik)
4 phone_number VARCHAR(32) UQ NULLABLE Nomor WhatsApp / telepon seluler (unik)
5 password_hash VARCHAR(255) NULLABLE Hash kata sandi argon2/bcrypt (opsional jika login OAuth)
6 avatar_url VARCHAR(255) NULLABLE Tautan URL berkas gambar profil pengguna
7 role ENUM('CUSTOMER','RESELLER','ADMIN') DEFAULT 'CUSTOMER', NOT NULL Peran pengguna dalam kendali hak akses (RBAC)
8 is_active BOOLEAN DEFAULT true, NOT NULL Status keaktifan akun dalam sistem
9 email_verified_at DATETIME(3) NULLABLE Stempel waktu verifikasi alamat surel
10 phone_verified_at DATETIME(3) NULLABLE Stempel waktu verifikasi OTP nomor telepon
11 created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), NOT NULL Waktu pencatatan akun ke basis data
12 updated_at DATETIME(3) ON UPDATE CURRENT_TIMESTAMP(3), NOT NULL Waktu pembaruan rekaman terakhir

Tabel 2.2: Spesifikasi Struktur Tabel user_social_accounts (Model: UserSocialAccount)

Menyimpan tautan akun masuk pihak ketiga (OAuth 2.0 Single Sign-On) seperti Google, Apple, dan Facebook.

No Nama Kolom Tipe Data MySQL Atribut / Constraint Keterangan Bisnis
1 id BIGINT UNSIGNED PK AUTO_INCREMENT, NOT NULL Kunci primer unik rekaman OAuth
2 user_id BIGINT UNSIGNED FK → users(id) [CASCADE] NOT NULL Kunci asing referensi ke pemilik akun users
3 provider ENUM('GOOGLE','FACEBOOK','APPLE') NOT NULL Penyedia layanan identitas eksternal
4 provider_user_id VARCHAR(191) NOT NULL ID identitas unik dari penyedia pihak ketiga
5 created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), NOT NULL Waktu pertautan akun sosial
6 updated_at DATETIME(3) ON UPDATE CURRENT_TIMESTAMP(3), NOT NULL Waktu pembaruan sinkronisasi akun sosial

Tabel 2.3: Spesifikasi Struktur Tabel user_addresses (Model: UserAddress)

Buku alamat tujuan ekspedisi pengiriman pelanggan dan reseller yang terhubung dengan API destinasi kurir J&T Express.

No Nama Kolom Tipe Data MySQL Atribut / Constraint Keterangan Bisnis
1 id BIGINT UNSIGNED PK AUTO_INCREMENT, NOT NULL Kunci primer identitas alamat
2 user_id BIGINT UNSIGNED FK → users(id) [CASCADE] NOT NULL Kunci asing referensi pemilik alamat
3 label VARCHAR(64) NOT NULL Label penanda alamat (e.g. Rumah, Toko, Kantor)
4 recipient_name VARCHAR(128) NOT NULL Nama lengkap penerima paket
5 phone_number VARCHAR(32) NOT NULL Nomor telepon penerima paket
6 province VARCHAR(128) NOT NULL Nama provinsi tujuan
7 city VARCHAR(128) NOT NULL Nama kota atau kabupaten tujuan
8 district VARCHAR(128) NOT NULL Kecamatan tujuan destinasi pengiriman
9 subdistrict VARCHAR(128) NULLABLE Kelurahan atau desa tujuan
10 postal_code VARCHAR(10) NOT NULL Kode pos wilayah pengiriman
11 full_address TEXT NOT NULL Rincian nama jalan, RT/RW, nomor rumah
12 benchmark VARCHAR(255) NULLABLE Patokan lokasi fisik kurir J&T
13 latitude DECIMAL(10,8) NULLABLE Titik koordinat lintang untuk pemetaan
14 longitude DECIMAL(11,8) NULLABLE Titik koordinat bujur untuk pemetaan
15 is_primary BOOLEAN DEFAULT false, NOT NULL Status penanda alamat utama saat checkout
16 created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), NOT NULL Waktu pembuatan alamat
17 updated_at DATETIME(3) ON UPDATE CURRENT_TIMESTAMP(3), NOT NULL Waktu pembaruan alamat terakhir

Tabel 2.4: Spesifikasi Struktur Tabel user_verifications (Model: UserVerification)

Penyimpanan kode token OTP verifikasi registrasi akun, verifikasi WhatsApp, dan token tautan reset password.

No Nama Kolom Tipe Data MySQL Atribut / Constraint Keterangan Bisnis
1 id BIGINT UNSIGNED PK AUTO_INCREMENT, NOT NULL Kunci primer rekaman verifikasi
2 user_id BIGINT UNSIGNED FK → users(id) [CASCADE] NOT NULL Kunci asing referensi pengguna terkait
3 type ENUM('EMAIL_VERIFICATION','PHONE_OTP','PASSWORD_RESET') NOT NULL Kategori tujuan verifikasi keamanan
4 token VARCHAR(128) NOT NULL Kode token acak numerik 6-digit atau hash string
5 expires_at DATETIME(3) NOT NULL Waktu batas kedaluwarsa masa aktif token
6 is_used BOOLEAN DEFAULT false, NOT NULL Bendera penanda apakah token telah digunakan
7 created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), NOT NULL Stempel waktu penerbitan kode OTP

Tabel 2.5: Spesifikasi Struktur Tabel user_tokens (Model: UserToken)

Pengelolaan sesi login pengguna multi-perangkat via Refresh Token berbasis hash SHA-256.

No Nama Kolom Tipe Data MySQL Atribut / Constraint Keterangan Bisnis
1 id BIGINT UNSIGNED PK AUTO_INCREMENT, NOT NULL Kunci primer sesi token
2 user_id BIGINT UNSIGNED FK → users(id) [CASCADE] NOT NULL Kunci asing pengguna terotentikasi
3 token_hash VARCHAR(255) UQ NOT NULL Hash aman dari refresh token perangkat
4 device_name VARCHAR(128) NULLABLE User-Agent atau nama perangkat pengguna
5 ip_address VARCHAR(45) NULLABLE Alamat IP saat login terdeteksi
6 expires_at DATETIME(3) NOT NULL Waktu batas kedaluwarsa sesi token
7 created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), NOT NULL Waktu penerbitan sesi login

Tabel 2.6: Spesifikasi Struktur Tabel categories (Model: Category)

Hierarki kategori katalog produk tas fashion (Sling Bag, Tote Bag, Ransel, Shoulder Bag) dengan relasi self-referencing parent_id.

No Nama Kolom Tipe Data MySQL Atribut / Constraint Keterangan Bisnis
1 id BIGINT UNSIGNED PK AUTO_INCREMENT, NOT NULL Kunci primer kategori produk
2 parent_id BIGINT UNSIGNED FK → categories(id) [SET NULL] NULLABLE Kunci asing self-reference induk sub-kategori
3 name VARCHAR(128) NOT NULL Nama kategori produk tas
4 slug VARCHAR(191) UQ NOT NULL Pengenal URL ramah SEO (unik)
5 description TEXT NULLABLE Deskripsi ringkas karakteristik kategori
6 image_url VARCHAR(255) NULLABLE Ikon atau gambar banner kategori
7 is_active BOOLEAN DEFAULT true, NOT NULL Status visibilitas kategori di katalog publik
8 created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), NOT NULL Waktu pembuatan kategori
9 updated_at DATETIME(3) ON UPDATE CURRENT_TIMESTAMP(3), NOT NULL Waktu pembaruan kategori

Tabel 2.7: Spesifikasi Struktur Tabel products (Model: Product)

Katalog utama produk tas fashion wanita yang memuat spesifikasi fisik 3D (PxLxT & volume) untuk modul Capacity Checker serta penetapan harga eceran dan reseller.

No Nama Kolom Tipe Data MySQL Atribut / Constraint Keterangan Bisnis
1 id BIGINT UNSIGNED PK AUTO_INCREMENT, NOT NULL Kunci primer identitas produk tas
2 category_id BIGINT UNSIGNED FK → categories(id) [RESTRICT] NOT NULL Kunci asing kategori produk tas
3 name VARCHAR(191) NOT NULL Nama komersial produk tas fashion
4 slug VARCHAR(191) UQ NOT NULL Pengenal URL unik produk
5 description TEXT NOT NULL Ringkasan spesifikasi singkat produk
6 full_description LONGTEXT NULLABLE Rincian naratif mendalam dan petunjuk perawatan
7 material VARCHAR(128) NULLABLE Bahan tas (e.g. Kulit Sintetis PU, Kanvas Tebal)
8 weight_grams INT UNSIGNED NOT NULL Bobot fisik tas dalam satuan gram (dasar hitung J&T)
9 base_price_customer DECIMAL(12,2) NOT NULL Harga jual normal eceran ke pembeli reguler
10 discount_price_customer DECIMAL(12,2) NULLABLE Harga promo diskon eceran (jika ada)
11 base_price_reseller DECIMAL(12,2) NOT NULL Harga grosir khusus mitra reseller per satuan
12 length_cm DECIMAL(6,2) NOT NULL Dimensi panjang fisik tas dalam centimeter
13 width_cm DECIMAL(6,2) NOT NULL Dimensi lebar fisik tas dalam centimeter
14 height_cm DECIMAL(6,2) NOT NULL Dimensi tinggi fisik tas dalam centimeter
15 volume_liters DECIMAL(6,2) NOT NULL Volume kapasitas muat efektif tas (Liter)
16 max_laptop_size DECIMAL(4,1) NULLABLE Ukuran laptop maksimal yang muat (Inci)
17 reseller_package_type ENUM('NONE','PAKET_11_PCS','ALL_PACKAGES') DEFAULT 'NONE', NOT NULL Kelayakan produk masuk ke skema Paket Usaha Reseller
18 is_active BOOLEAN DEFAULT true, NOT NULL Status ketersediaan produk di toko
19 created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), NOT NULL Waktu pendaftaran produk
20 updated_at DATETIME(3) ON UPDATE CURRENT_TIMESTAMP(3), NOT NULL Waktu peremajaan data produk

Tabel 2.8: Spesifikasi Struktur Tabel product_variants (Model: ProductVariant)

Varian warna fisik produk tas, persediaan stok unit tersendiri, SKU unik, dan penyesuaian harga khusus.

No Nama Kolom Tipe Data MySQL Atribut / Constraint Keterangan Bisnis
1 id BIGINT UNSIGNED PK AUTO_INCREMENT, NOT NULL Kunci primer varian produk
2 product_id BIGINT UNSIGNED FK → products(id) [CASCADE] NOT NULL Kunci asing referensi produk induk
3 color_name VARCHAR(64) NOT NULL Nama warna varian (e.g. Hitam Obsidian, Sage Green)
4 image_url VARCHAR(255) NULLABLE Foto spesifik produk warna terkait
5 sku VARCHAR(64) UQ NOT NULL Stock Keeping Unit unik untuk inventori gudang
6 stock INT DEFAULT 0, NOT NULL Kuantitas stok fisik tersedia siap jual
7 price_adjustment DECIMAL(10,2) DEFAULT 0.00, NOT NULL Diferensiasi harga tambahan dari base price
8 created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), NOT NULL Waktu pembuatan varian
9 updated_at DATETIME(3) ON UPDATE CURRENT_TIMESTAMP(3), NOT NULL Waktu penyesuaian stok atau varian

Tabel 2.9: Spesifikasi Struktur Tabel product_images (Model: ProductImage)

Galeri foto produk tas multi-sudut dan foto spesifik yang tertaut ke varian warna tertentu.

No Nama Kolom Tipe Data MySQL Atribut / Constraint Keterangan Bisnis
1 id BIGINT UNSIGNED PK AUTO_INCREMENT, NOT NULL Kunci primer rekaman foto
2 product_id BIGINT UNSIGNED FK → products(id) [CASCADE] NOT NULL Kunci asing produk induk
3 variant_id BIGINT UNSIGNED FK → product_variants(id) [SET NULL] NULLABLE Kunci asing varian warna spesifik (opsional)
4 image_url VARCHAR(255) NOT NULL URL penyimpanan berkas gambar di CDN/Server
5 is_primary BOOLEAN DEFAULT false, NOT NULL Penanda foto sampul utama pada kartu produk
6 sort_order INT DEFAULT 0, NOT NULL Urutan tampilan foto di galeri slider
7 created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), NOT NULL Waktu unggah foto produk

Tabel 2.10: Spesifikasi Struktur Tabel preset_bag_capacities (Model: PresetBagCapacity)

Tabel master data barang bawaan harian (Laptop 14 Inci, Botol Minum 600ml, Pouch Kosmetik) untuk kalkulasi simulasi 3D Capacity Checker (Entitas Standalone).

No Nama Kolom Tipe Data MySQL Atribut / Constraint Keterangan Bisnis
1 id BIGINT UNSIGNED PK AUTO_INCREMENT, NOT NULL Kunci primer master preset barang
2 name VARCHAR(128) NOT NULL Nama barang simulasi (e.g. Laptop 14 Inci, Payung Lipat)
3 category VARCHAR(64) NOT NULL Kategori utilitas barang (Elektronik, Harian, Ibadah)
4 icon_url VARCHAR(255) NULLABLE Ikon representasi grafis barang simulasi
5 length_cm DECIMAL(6,2) NOT NULL Panjang fisik barang dalam centimeter
6 width_cm DECIMAL(6,2) NOT NULL Lebar fisik barang dalam centimeter
7 height_cm DECIMAL(6,2) NOT NULL Tinggi fisik barang dalam centimeter
8 volume_liters DECIMAL(6,2) NOT NULL Volume pemakaian ruang barang (Liter)
9 is_rigid BOOLEAN DEFAULT false, NOT NULL Penanda sifat kaku (tidak bisa ditekuk seperti laptop)
10 created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), NOT NULL Waktu pencatatan data preset

Tabel 2.11: Spesifikasi Struktur Tabel reseller_packages (Model: ResellerPackage)

Master paket usaha reseller (Paket Starter 11 Pcs) dengan penetapan harga grosir flat bundle dan aturan kuota wajib 11 item.

No Nama Kolom Tipe Data MySQL Atribut / Constraint Keterangan Bisnis
1 id BIGINT UNSIGNED PK AUTO_INCREMENT, NOT NULL Kunci primer paket usaha reseller
2 name VARCHAR(128) NOT NULL Nama paket dagang (e.g. Paket Usaha Cuan 11 Pcs)
3 slug VARCHAR(191) UQ NOT NULL Slug URL unik halaman paket
4 description TEXT NULLABLE Penjelasan keuntungan bisnis dan materi promosi
5 package_price DECIMAL(12,2) NOT NULL Harga flat satu paket total untuk 11 pcs tas
6 required_quantity INT DEFAULT 11, NOT NULL Batas kuota wajib pemilihan item tas (11 item)
7 is_active BOOLEAN DEFAULT true, NOT NULL Status penawaran paket aktif atau nonaktif
8 created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), NOT NULL Waktu pembuatan paket usaha
9 updated_at DATETIME(3) ON UPDATE CURRENT_TIMESTAMP(3), NOT NULL Waktu pembaruan paket usaha

Tabel 2.12: Spesifikasi Struktur Tabel product_reseller_packages (Model: ProductResellerPackage)

Tabel perantara (Junction Table) yang menghubungkan produk tas yang memenuhi syarat untuk dipilih dalam paket usaha reseller tertentu.

No Nama Kolom Tipe Data MySQL Atribut / Constraint Keterangan Bisnis
1 id BIGINT UNSIGNED PK AUTO_INCREMENT, NOT NULL Kunci primer junction paket produk
2 product_id BIGINT UNSIGNED FK → products(id) [CASCADE] NOT NULL Kunci asing produk yang dapat dipilih
3 reseller_package_id BIGINT UNSIGNED FK → reseller_packages(id) [CASCADE] NOT NULL Kunci asing paket reseller tujuan
4 created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), NOT NULL Waktu pendaftaran pertautan produk

Tabel 2.13: Spesifikasi Struktur Tabel vouchers (Model: Voucher)

Manajemen kupon promosi dan voucher potongan harga (produk atau subsidi ongkir J&T) dengan validasi kuota dan masa berlaku.

No Nama Kolom Tipe Data MySQL Atribut / Constraint Keterangan Bisnis
1 id BIGINT UNSIGNED PK AUTO_INCREMENT, NOT NULL Kunci primer identitas voucher
2 code VARCHAR(64) UQ NOT NULL Kode kupon unik yang diinput pengguna saat checkout
3 title VARCHAR(128) NOT NULL Judul kampanye promosi voucher
4 description TEXT NULLABLE Syarat dan ketentuan pemakaian voucher
5 type ENUM('PRODUCT_DISCOUNT','SHIPPING_DISCOUNT') NOT NULL Sasaran potongan (diskon produk atau subsidi ongkos kirim)
6 discount_type ENUM('PERCENTAGE','FIXED_AMOUNT') NOT NULL Metode kalkulasi potongan (persen atau nominal rupiah)
7 discount_value DECIMAL(10,2) NOT NULL Besaran nilai diskon (% atau nominal Rupiah)
8 max_discount_amount DECIMAL(10,2) NULLABLE Batas plafon diskon maksimal jika persentase
9 min_spend DECIMAL(12,2) DEFAULT 0.00, NOT NULL Batas minimum pembelanjaan untuk aktivasi kupon
10 applicable_to ENUM('ALL_ITEMS','REGULAR_ONLY','SPECIFIC_PRODUCTS') NOT NULL Cakupan item yang berhak mendapat diskon
11 target_role ENUM('ALL','CUSTOMER','RESELLER') DEFAULT 'ALL', NULLABLE Target kelompok peran pengguna yang berhak klaim
12 quota_total INT UNSIGNED NOT NULL Alokasi kuota penggunaan maksimal seluruh pengguna
13 quota_used INT UNSIGNED DEFAULT 0, NOT NULL Jumlah akumulasi kuota yang telah terpakai
14 quota_per_user INT UNSIGNED DEFAULT 1, NOT NULL Batas frekuensi klaim kupon per akun pengguna
15 start_date DATETIME(3) NOT NULL Awal waktu voucher dapat digunakan
16 end_date DATETIME(3) NOT NULL Batas akhir waktu pemakaian voucher
17 is_active BOOLEAN DEFAULT true, NOT NULL Status aktivasi operasional voucher
18 created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), NOT NULL Waktu pembuatan kupon promosi
19 updated_at DATETIME(3) ON UPDATE CURRENT_TIMESTAMP(3), NOT NULL Waktu pembaruan data kupon

Tabel 2.14: Spesifikasi Struktur Tabel voucher_products (Model: VoucherProduct)

Tabel perantara (Junction Table) untuk mengikat voucher bertipe SPECIFIC_PRODUCTS ke daftar produk tas tertentu.

No Nama Kolom Tipe Data MySQL Atribut / Constraint Keterangan Bisnis
1 id BIGINT UNSIGNED PK AUTO_INCREMENT, NOT NULL Kunci primer pertautan voucher-produk
2 voucher_id BIGINT UNSIGNED FK → vouchers(id) [CASCADE] NOT NULL Kunci asing referensi voucher promosi
3 product_id BIGINT UNSIGNED FK → products(id) [CASCADE] NOT NULL Kunci asing produk tas yang dipromosikan
4 created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), NOT NULL Waktu pengikatan produk ke voucher

Tabel 2.15: Spesifikasi Struktur Tabel user_voucher_usages (Model: UserVoucherUsage)

Pencatatan riwayat pemakaian voucher oleh masing-masing akun pengguna guna menegakkan aturan pembatasan quota_per_user secara konsisten.

No Nama Kolom Tipe Data MySQL Atribut / Constraint Keterangan Bisnis
1 id BIGINT UNSIGNED PK AUTO_INCREMENT, NOT NULL Kunci primer rekaman riwayat penggunaan
2 user_id BIGINT UNSIGNED FK → users(id) [CASCADE] NOT NULL Kunci asing pengguna pemakai kupon
3 voucher_id BIGINT UNSIGNED FK → vouchers(id) [CASCADE] NOT NULL Kunci asing kupon voucher yang diklaim
4 used_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), NOT NULL Waktu transaksi saat voucher divalidasi dan digunakan

Tabel 2.16: Spesifikasi Struktur Tabel carts (Model: Cart)

Wadah keranjang belanja persisten pengguna yang berelasi One-to-One (1:1) terhadap entitas users.

No Nama Kolom Tipe Data MySQL Atribut / Constraint Keterangan Bisnis
1 id BIGINT UNSIGNED PK AUTO_INCREMENT, NOT NULL Kunci primer keranjang belanja
2 user_id BIGINT UNSIGNED FK → users(id) [CASCADE] UQ NOT NULL Kunci asing referensi pemilik akun (relasi 1:1)
3 created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), NOT NULL Waktu inisialisasi keranjang belanja
4 updated_at DATETIME(3) ON UPDATE CURRENT_TIMESTAMP(3), NOT NULL Waktu peremajaan isi keranjang

Tabel 2.17: Spesifikasi Struktur Tabel cart_sections (Model: CartSection)

Pengelompokan (sekat) dalam keranjang belanja khusus untuk mengisolasi 11 pcs item tas yang dibundel dalam satu Paket Usaha Reseller.

No Nama Kolom Tipe Data MySQL Atribut / Constraint Keterangan Bisnis
1 id BIGINT UNSIGNED PK AUTO_INCREMENT, NOT NULL Kunci primer section paket belanja
2 cart_id BIGINT UNSIGNED FK → carts(id) [CASCADE] NOT NULL Kunci asing keranjang induk tempat section berada
3 reseller_package_id BIGINT UNSIGNED FK → reseller_packages(id) [CASCADE] NOT NULL Kunci asing aturan paket reseller yang diterapkan
4 created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), NOT NULL Waktu pembuatan section paket
5 updated_at DATETIME(3) ON UPDATE CURRENT_TIMESTAMP(3), NOT NULL Waktu peremajaan komposisi section

Tabel 2.18: Spesifikasi Struktur Tabel cart_items (Model: CartItem)

Rincian produk varian tas di dalam keranjang, baik sebagai belanja satuan reguler (cart_section_id = NULL) maupun sebagai komponen paket usaha (terikat cart_section_id).

No Nama Kolom Tipe Data MySQL Atribut / Constraint Keterangan Bisnis
1 id BIGINT UNSIGNED PK AUTO_INCREMENT, NOT NULL Kunci primer baris item keranjang
2 cart_id BIGINT UNSIGNED FK → carts(id) [CASCADE] NOT NULL Kunci asing keranjang belanja tempat item disimpan
3 cart_section_id BIGINT UNSIGNED FK → cart_sections(id) [CASCADE] NULLABLE Kunci asing section paket usaha (NULL jika belanja reguler)
4 product_id BIGINT UNSIGNED FK → products(id) [CASCADE] NOT NULL Kunci asing produk tas yang dipilih
5 variant_id BIGINT UNSIGNED FK → product_variants(id) [CASCADE] NOT NULL Kunci asing varian warna spesifik
6 quantity INT UNSIGNED DEFAULT 1, NOT NULL Kuantitas unit yang dimasukkan ke keranjang
7 created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), NOT NULL Waktu penambahan item ke keranjang
8 updated_at DATETIME(3) ON UPDATE CURRENT_TIMESTAMP(3), NOT NULL Waktu pengubahan jumlah item

Tabel 2.19: Spesifikasi Struktur Tabel orders (Model: Order)

Master pesanan transaksi komersial. PENTING: Sesuai skema resmi, tabel orders TIDAK memiliki kolom FK voucher_id; jejak kupon tercatat terpisah pada user_voucher_usages.

No Nama Kolom Tipe Data MySQL Atribut / Constraint Keterangan Bisnis
1 id BIGINT UNSIGNED PK AUTO_INCREMENT, NOT NULL Kunci primer pesanan belanja
2 order_number VARCHAR(64) UQ NOT NULL Nomor faktur unik (e.g. NL-ORD-202610-0012)
3 user_id BIGINT UNSIGNED FK → users(id) [CASCADE] NOT NULL Kunci asing pengguna pembeli
4 status ENUM('PENDING_PAYMENT','WAITING_VERIFICATION','PAID','PROCESSING','SHIPPED','DELIVERED','COMPLETED','CANCELLED') DEFAULT 'PENDING_PAYMENT', NOT NULL Status siklus hidup pesanan pesanan
5 regular_subtotal DECIMAL(12,2) DEFAULT 0.00, NOT NULL Akumulasi subtotal barang belanja reguler eceran
6 package_subtotal DECIMAL(12,2) DEFAULT 0.00, NOT NULL Akumulasi subtotal paket usaha reseller (harga flat bundle)
7 discount_product_total DECIMAL(12,2) DEFAULT 0.00, NOT NULL Total potongan diskon produk dari kupon voucher
8 shipping_fee DECIMAL(12,2) NOT NULL Biaya ekspedisi pengiriman J&T Express sebelum diskon
9 discount_shipping_total DECIMAL(12,2) DEFAULT 0.00, NOT NULL Total subsidi potongan ongkos kirim dari kupon voucher
10 net_total DECIMAL(12,2) NOT NULL Nilai bersih pelunasan transfer yang wajib dibayar
11 total_weight_grams INT UNSIGNED NOT NULL Total bobot akumulasi seluruh varian pesanan (gram)
12 shipping_address JSON NOT NULL Snapshot alamat tujuan lengkap saat checkout dibekukan
13 expires_at DATETIME(3) NOT NULL Batas akhir tenggat pembayaran (24 jam)
14 created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), NOT NULL Waktu pesanan diterbitkan
15 updated_at DATETIME(3) ON UPDATE CURRENT_TIMESTAMP(3), NOT NULL Waktu pembaruan status pesanan

Tabel 2.20: Spesifikasi Struktur Tabel order_items (Model: OrderItem)

Baris rincian produk tas yang dibeli dalam pesanan dengan pembekuan harga dan nama varian saat transaksi terjadi (immutable snapshot).

No Nama Kolom Tipe Data MySQL Atribut / Constraint Keterangan Bisnis
1 id BIGINT UNSIGNED PK AUTO_INCREMENT, NOT NULL Kunci primer baris rincian pesanan
2 order_id BIGINT UNSIGNED FK → orders(id) [CASCADE] NOT NULL Kunci asing pesanan induk
3 product_id BIGINT UNSIGNED FK → products(id) [RESTRICT] NOT NULL Kunci asing produk tas
4 variant_id BIGINT UNSIGNED FK → product_variants(id) [RESTRICT] NOT NULL Kunci asing varian warna yang dibeli
5 package_name VARCHAR(128) NULLABLE Nama paket usaha jika item merupakan bagian dari bundle
6 product_name VARCHAR(191) NOT NULL Snapshot nama produk saat pesanan diproses
7 color_name VARCHAR(64) NOT NULL Snapshot warna varian saat transaksi
8 sku VARCHAR(64) NOT NULL Snapshot SKU barang gudang
9 unit_price DECIMAL(12,2) NOT NULL Harga satuan efektif yang dibayar
10 quantity INT UNSIGNED NOT NULL Jumlah unit tas yang dibeli
11 weight_grams INT UNSIGNED NOT NULL Bobot per item dalam satuan gram
12 total_price DECIMAL(12,2) NOT NULL Total harga baris item (unit_price x quantity)
13 created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), NOT NULL Waktu pencatatan rincian item pesanan

Tabel 2.21: Spesifikasi Struktur Tabel payments (Model: Payment)

Pengelolaan data transaksi transfer manual multi-rekening toko (BCA, Mandiri, QRIS), bukti bayar struk, dan audit verifikasi admin.

No Nama Kolom Tipe Data MySQL Atribut / Constraint Keterangan Bisnis
1 id BIGINT UNSIGNED PK AUTO_INCREMENT, NOT NULL Kunci primer transaksi pembayaran
2 order_id BIGINT UNSIGNED FK → orders(id) [CASCADE] UQ NOT NULL Kunci asing pesanan terhubung (relasi 1:1)
3 payment_account_id BIGINT UNSIGNED FK → payment_accounts(id) [RESTRICT] NOT NULL Kunci asing rekening tujuan transfer resmi toko
4 amount DECIMAL(12,2) NOT NULL Nominal dana yang wajib atau telah ditransfer
5 status ENUM('WAITING_PAYMENT','WAITING_VERIFICATION','VERIFIED','REJECTED') DEFAULT 'WAITING_PAYMENT', NOT NULL Status verifikasi audit pembayaran
6 proof_image_url VARCHAR(255) NULLABLE Tautan berkas gambar struk bukti transfer yang diunggah
7 sender_bank_name VARCHAR(64) NULLABLE Nama bank asal pengirim yang dicantumkan pembeli
8 sender_account_name VARCHAR(128) NULLABLE Nama pemilik rekening bank asal pengirim
9 transfer_date DATETIME(3) NULLABLE Tanggal dan waktu transfer dilakukan oleh pembeli
10 rejection_reason TEXT NULLABLE Catatan alasan penolakan verifikasi oleh admin
11 approve_reason TEXT NULLABLE Catatan tambahan saat pembayaran disetujui
12 approve_image_url VARCHAR(255) NULLABLE Bukti tangkapan layar mutasi bank yang diunggah admin
13 reupload_attempts INT DEFAULT 0, NOT NULL Jumlah frekuensi pembeli mengunggah ulang struk bayar
14 verified_at DATETIME(3) NULLABLE Waktu admin melakukan verifikasi pembayaran
15 verified_by BIGINT UNSIGNED NULLABLE ID admin yang memvalidasi transaksi mutasi
16 created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), NOT NULL Waktu inisialisasi tagihan pembayaran
17 updated_at DATETIME(3) ON UPDATE CURRENT_TIMESTAMP(3), NOT NULL Waktu pembaruan status verifikasi

Tabel 2.22: Spesifikasi Struktur Tabel payment_accounts (Model: PaymentAccount)

Daftar rekening bank resmi dan kanal QRIS toko Nalala Store untuk menerima pembayaran transfer dari pelanggan.

No Nama Kolom Tipe Data MySQL Atribut / Constraint Keterangan Bisnis
1 id BIGINT UNSIGNED PK AUTO_INCREMENT, NOT NULL Kunci primer rekening tujuan
2 type ENUM('BANK_TRANSFER','QRIS','E_WALLET') NOT NULL Tipe kanal penerimaan transaksi dana
3 provider_name VARCHAR(64) NOT NULL Nama lembaga bank / penyedia (BCA, Mandiri, QRIS)
4 account_number VARCHAR(64) NOT NULL Nomor rekening bank atau ID QRIS penerima
5 account_holder_name VARCHAR(128) NOT NULL Nama pemilik rekening resmi (e.g. Nalala Official Store)
6 logo_url VARCHAR(255) NULLABLE Ikon logo resmi bank penerima
7 qr_image_url VARCHAR(255) NULLABLE Berkas citra QR Code QRIS dinamis/statis
8 is_active BOOLEAN DEFAULT true, NOT NULL Status rekening dapat dipilih saat checkout
9 created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), NOT NULL Waktu pendaftaran rekening toko
10 updated_at DATETIME(3) ON UPDATE CURRENT_TIMESTAMP(3), NOT NULL Waktu pembaruan informasi rekening

Tabel 2.23: Spesifikasi Struktur Tabel shipments (Model: Shipment)

Pengelolaan manifes pengiriman logistik ekspedisi J&T Express (layanan EZ dan CARGO), nomor resi AWB, dan rekaman pelacakan transit real-time.

No Nama Kolom Tipe Data MySQL Atribut / Constraint Keterangan Bisnis
1 id BIGINT UNSIGNED PK AUTO_INCREMENT, NOT NULL Kunci primer data pengiriman
2 order_id BIGINT UNSIGNED FK → orders(id) [CASCADE] UQ NOT NULL Kunci asing pesanan yang dikirim (relasi 1:1)
3 waybill_number VARCHAR(64) UQ NOT NULL Nomor Resi / AWB resmi dari J&T Express
4 courier_name VARCHAR(64) DEFAULT 'J&T Express', NOT NULL Nama mitra kurir logistik pengiriman
5 service_type ENUM('EZ','CARGO') NOT NULL Pilihan layanan ekspedisi (EZ Reguler atau CARGO Grosir)
6 status ENUM('MANIFESTED','ON_TRANSIT','DELIVERED','RETURNED') DEFAULT 'MANIFESTED', NOT NULL Status posisi fisik logistik paket
7 tracking_logs JSON NOT NULL Histori checkpoint posisi paket dari webhook/API kurir
8 shipped_at DATETIME(3) NULLABLE Waktu paket diserahkan ke drop point J&T
9 delivered_at DATETIME(3) NULLABLE Waktu paket diterima di alamat pelanggan
10 created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), NOT NULL Waktu penerbitan manifes pengiriman
11 updated_at DATETIME(3) ON UPDATE CURRENT_TIMESTAMP(3), NOT NULL Waktu pembaruan status logistik kurir

Tabel 2.24: Spesifikasi Struktur Tabel notifications (Model: Notification)

Layanan notifikasi internal sistem kepada pengguna terkait progres verifikasi pesanan, nomor resi pengiriman J&T, serta pesan siaran promosi.

No Nama Kolom Tipe Data MySQL Atribut / Constraint Keterangan Bisnis
1 id BIGINT UNSIGNED PK AUTO_INCREMENT, NOT NULL Kunci primer pesan notifikasi
2 user_id BIGINT UNSIGNED FK → users(id) [CASCADE] NULLABLE Kunci asing penerima notifikasi (NULL jika broadcast)
3 target_audience ENUM('ALL','CUSTOMER_ONLY','RESELLER_ONLY') NULLABLE Sasaran kelompok pengguna untuk pesan broadcast
4 title VARCHAR(191) NOT NULL Judul ringkas pemberitahuan sistem
5 message TEXT NOT NULL Isi lengkap teks pesan notifikasi
6 type VARCHAR(64) NOT NULL Tipe kategori pesan (ORDER, PAYMENT, PROMO, SYSTEM)
7 is_read BOOLEAN DEFAULT false, NOT NULL Status apakah notifikasi telah dibaca pengguna
8 created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3), NOT NULL Waktu pengiriman pemberitahuan

BAB III - PERANCANGAN SISTEM (UML)

Perancangan sistem perangkat lunak Nalala Store dimodelkan secara komprehensif menggunakan Unified Modeling Language (UML) yang mencakup Use Case Diagram, Activity Diagram, Sequence Diagram, dan Comprehensive Domain Class Diagram.

3.1 Use Case Diagram

Sistem Nalala Store melibatkan tiga aktor utama dengan batasan wewenang berbasis peran (Role-Based Access Control): Customer (Pembeli Ritel), Reseller (Mitra Grosir Paket Usaha), dan Admin (Pengelola Operasional Toko). Hubungan aktor dengan 12 use case disajikan pada Gambar 3.1:

Use Case Diagram Sistem E-Commerce Nalala Store (3 Aktor & 12 Use Case)
flowchart LR subgraph Aktor Sistem Cust[Customer / Pembeli Reguler] Reseller[Mitra Reseller] Admin[Administrator Toko] end subgraph Nalala Store E-Commerce Subsystem UC1([UC-01 Registrasi & Verifikasi OTP]) UC2([UC-02 Login Multi-Role & Profil]) UC3([UC-03 Eksplorasi Katalog & Capacity Checker 3D]) UC4([UC-04 Pemilihan Paket Usaha Reseller 11 Pcs]) UC5([UC-05 Manajemen Keranjang & Section Paket]) UC6([UC-06 Klaim & Validasi Voucher Diskon]) UC7([UC-07 Checkout Pesanan & Hitung Ongkir J&T]) UC8([UC-08 Pembayaran Transfer & Upload Bukti]) UC9([UC-09 Lacak Pengiriman Resi J&T Real-Time]) UC10([UC-10 Verifikasi Pembayaran & Approval Mutasi]) UC11([UC-11 Kelola Produk, Varian & Paket Usaha]) UC12([UC-12 Dispatch Pengiriman & Penerbitan AWB J&T]) end Cust --> UC1 Cust --> UC2 Cust --> UC3 Cust --> UC5 Cust --> UC6 Cust --> UC7 Cust --> UC8 Cust --> UC9 Reseller --> UC1 Reseller --> UC2 Reseller --> UC3 Reseller --> UC4 Reseller --> UC5 Reseller --> UC6 Reseller --> UC7 Reseller --> UC8 Reseller --> UC9 Admin --> UC2 Admin --> UC10 Admin --> UC11 Admin --> UC12
(Dapat disalin & di-render langsung di mermaid.live)

Gambar 3.1 Use Case Diagram Sistem E-Commerce Nalala Store

Tabel 3.1 Spesifikasi Use Case Inti Sistem Nalala Store

ID UC Nama Use Case Aktor Kondisi Awal (Precondition) Hasil Akhir (Postcondition)
UC-03 Capacity Checker 3D Customer, Reseller Pengguna membuka halaman detail produk tas. Sistem menampilkan visual 3D dan status kelayakan tampung barang (FIT atau OVERLOAD).
UC-04 Paket Usaha Reseller Reseller Pengguna login dengan peran Reseller dan membuka katalog paket. Sistem memvalidasi tepat 11 item tas dan menyimpan ke cart_sections dengan harga paket flat.
UC-07 Checkout & J&T Ongkir Customer, Reseller Keranjang berisi item dan pengguna memiliki alamat tujuan. Sistem menghitung tarif J&T (EZ/CARGO) berdasarkan bobot gram dan menghasilkan orders.
UC-10 Verifikasi Pembayaran Admin Pembeli telah mengunggah bukti bayar (status: WAITING_VERIFICATION). Admin menyetujui mutasi rekening, sistem mengupdate status ke PAID, dan menerbitkan AWB J&T.

3.2 Spesifikasi Use Case Inti

Tabel 3.1 pada sub-bab sebelumnya menyajikan rincian skenario operasional use case inti, kondisi prasyarat (precondition), alur transaksi normal, serta kondisi akhir sistem (postcondition).

3.3 Activity Diagram Registrasi Akun dan Verifikasi OTP

Activity diagram pada Gambar 3.2 memodelkan alur registrasi pengguna baru, pembuatan token verifikasi acak 6 digit, pengiriman melalui pesan instan WhatsApp/Email, hingga validasi masa aktif token 5 menit sebelum aktivasi akun:

Activity Diagram Registrasi Akun dan Verifikasi OTP WhatsApp/Email
flowchart TD START([Mulai]) --> INPUT_REG[Pengguna Mengisi Form Registrasi: Nama, Email, No. WA, Password] INPUT_REG --> SUBMIT_REG[Kirim Data ke Server] SUBMIT_REG --> VAL_INPUT{Format Data Valid & Email Belum Terdaftar?} VAL_INPUT -->|Tidak| SHOW_ERR[Tampilkan Pesan Validasi Error] SHOW_ERR --> INPUT_REG VAL_INPUT -->|Ya| SAVE_USER[Simpan Akun ke users: is_active = false] SAVE_USER --> GEN_OTP[Generate 6-Digit OTP & Simpan ke user_verifications] GEN_OTP --> SEND_OTP[Kirim OTP via WhatsApp / Email Gateway] SEND_OTP --> SHOW_OTP_PAGE[Buka Halaman Input Verifikasi OTP & Countdown 5 Menit] SHOW_OTP_PAGE --> INPUT_OTP[Pengguna Memasukkan 6-Digit Kode OTP] INPUT_OTP --> CHECK_OTP{Kode OTP Cocok & Belum Kedaluwarsa?} CHECK_OTP -->|Tidak Cocok / Expired| WARN_OTP[Tampilkan Error OTP & Sisa Percobaan] WARN_OTP --> SHOW_OTP_PAGE CHECK_OTP -->|Valid| UPDATE_VERIF[Update user_verifications: is_used = true] UPDATE_VERIF --> ACTIVATE_USER[Update users: is_active = true, verified_at = NOW] ACTIVATE_USER --> AUTO_LOGIN[Generate JWT Auth Token & Inisialisasi Keranjang carts] AUTO_LOGIN --> REDIRECT_HOME[Arahkan ke Beranda / Dashboard Pembeli] REDIRECT_HOME --> FINISH([Selesai])
(Dapat disalin & di-render langsung di mermaid.live)

Gambar 3.2 Activity Diagram Registrasi dan Verifikasi OTP

Tabel 3.2 Deskripsi Alur Aktivitas Registrasi dan OTP

Alur memodelkan interaksi antara calon pengguna dan subsistem autentikasi Nalala Store, memastikan setiap pendaftar tervalidasi melalui saluran komunikasi nomor telepon WhatsApp atau surel sebelum akun diaktifkan.

3.4 Activity Diagram Simulasi Daya Muat Tas (3D Capacity Checker)

Activity diagram pada Gambar 3.3 memodelkan proses pemilihan objek barang bawaan harian, kalkulasi dimensi batas tiga dimensi (PxLxT) dan kubikasi volume liter, serta penentuan indikator kelayakan muat tas:

Activity Diagram Simulasi Daya Muat Tas (3D Capacity Checker)
flowchart TD START([Mulai]) --> OPEN_PROD[Pengguna Membuka Halaman Detail Produk Tas] OPEN_PROD --> FETCH_SPEC[Sistem Memuat Spesifikasi Fisik: PxLxT, Volume Liter, & Laptop Max] FETCH_SPEC --> CLICK_CAP[Pengguna Mengklik Tombol 'Uji Kapasitas Muat 3D'] CLICK_CAP --> LOAD_PRESETS[Sistem Mengambil Master Data preset_bag_capacities] LOAD_PRESETS --> SELECT_ITEMS[Pengguna Memilih Barang Bawaan: Laptop, Botol Minum, Mukena, Pouch] SELECT_ITEMS --> CALC_ENGINE[Engine Menghitung Total Volume Barang & Dimensi Maksimal PxLxT] CALC_ENGINE --> EVALUATE{Volume Barang <= Volume Tas & Dimensi Muat?} EVALUATE -->|Ya / Fit Sempurna| RENDER_GREEN[Render Kontainer Tas 3D Hijau & Label 'Muat Sempurna'] EVALUATE -->|Melebihi Kapasitas| RENDER_RED[Render Kontainer Tas 3D Merah & Peringatan Dimensi Overload] RENDER_GREEN --> USER_DECISION{Pengguna Puas & Ingin Membeli?} RENDER_RED --> USER_DECISION USER_DECISION -->|Ubah Pilihan Barang| SELECT_ITEMS USER_DECISION -->|Beli Produk| ADD_TO_CART[Simpan Produk & Varian ke cart_items] ADD_TO_CART --> FINISH([Selesai])
(Dapat disalin & di-render langsung di mermaid.live)

Gambar 3.3 Activity Diagram Simulasi Capacity Checker 3D

Tabel 3.3 Deskripsi Alur Aktivitas Simulasi 3D Capacity Checker

Alur memodelkan kalkulasi matematis evaluasi dimensi tiga dimensi (Panjang, Lebar, Tinggi) dan toleransi volume kubik liter antara produk tas fashion dengan objek preset barang bawaan harian.

3.5 Activity Diagram Checkout Belanja & Pembayaran Multi-Rekening

Activity diagram pada Gambar 3.4 memodelkan alur checkout keranjang belanja, penegakan kuota wajib 11 pcs paket reseller, penghitungan tarif kurir J&T Express (EZ / CARGO), hingga pengunggahan struk bukti bayar transfer:

Activity Diagram Checkout Belanja & Pembayaran Transfer Multi-Rekening
flowchart TD START([Mulai]) --> OPEN_CART[Pengguna Membuka Keranjang Belanja] OPEN_CART --> CHECK_SECTIONS{Keranjang Memuat Paket Reseller?} CHECK_SECTIONS -->|Ya| VALIDATE_11{Item di Section Tepat 11 Pcs?} VALIDATE_11 -->|Belum Tepat| WARN_SECTION[Tampilkan Peringatan Kuota Paket Belum Genap 11] WARN_SECTION --> OPEN_CART VALIDATE_11 -->|Tepat 11 Pcs| CLICK_CHECKOUT[Klik Tombol Checkout Pesanan] CHECK_SECTIONS -->|Tidak / Reguler Saja| CLICK_CHECKOUT CLICK_CHECKOUT --> LOAD_CHECKOUT[Sistem Menampilkan Form Checkout: Alamat & Layanan J&T] LOAD_CHECKOUT --> PICK_ADDRESS[Pengguna Memilih Alamat Pengiriman dari user_addresses] PICK_ADDRESS --> CALC_JNT_FEE[Sistem Menghitung Total Bobot Gram & Tarif J&T EZ/CARGO] CALC_JNT_FEE --> INPUT_VOUCHER{Input Kupon Diskon / Subsidi Ongkir?} INPUT_VOUCHER -->|Ya| CHECK_VOUCHER{Kode Valid, Min Spend Cukup, Kuota Ada?} CHECK_VOUCHER -->|Tidak| ERR_VOUCHER[Tampilkan Error Voucher Tidak Berlaku] ERR_VOUCHER --> INPUT_VOUCHER CHECK_VOUCHER -->|Valid| APPLY_DISCOUNT[Kurangi Total Bayar Sesuai Nilai Diskon] INPUT_VOUCHER -->|Tidak| SUM_TOTAL[Kalkulasi net_total = Subtotal + Ongkir - Diskon] APPLY_DISCOUNT --> SUM_TOTAL SUM_TOTAL --> CREATE_ORDER_DB[Sistem Terbitkan orders & payments (Status: PENDING_PAYMENT)] CREATE_ORDER_DB --> SELECT_PAYMENT[Pengguna Memilih Rekening Transfer: BCA / Mandiri / QRIS] SELECT_PAYMENT --> SHOW_PAY_INFO[Tampilkan Nomor Rekening, Jumlah Transfer, & Timer 24 Jam] SHOW_PAY_INFO --> USER_TRANSFERS[Pengguna Melakukan Transfer Dana ke Rekening Toko] USER_TRANSFERS --> UPLOAD_PROOF[Pengguna Mengunggah Foto Bukti Struk Pembayaran] UPLOAD_PROOF --> UPDATE_WAITING[Update Status: WAITING_VERIFICATION & Notifikasi ke Admin] UPDATE_WAITING --> FINISH([Menunggu Verifikasi Admin])
(Dapat disalin & di-render langsung di mermaid.live)

Gambar 3.4 Activity Diagram Checkout Belanja & Pembayaran Multi-Rekening

Tabel 3.4 Deskripsi Alur Aktivitas Checkout & Pembayaran

Alur memodelkan transisi keranjang belanja menuju pesanan terikat (binding order), penegakan kuota paket 11 pcs, kalkulasi ongkos kirim logistik J&T, serta pengunggahan bukti pembayaran transfer.

3.6 Activity Diagram Verifikasi Pembayaran & Penerbitan Resi J&T

Activity diagram pada Gambar 3.5 memodelkan pemeriksaan mutasi rekening oleh admin, penanganan penolakan struk fiktif berulang, serta pemanggilan API logistik kurir J&T Express untuk auto-generate nomor resi AWB saat transaksi disetujui:

Activity Diagram Verifikasi Bukti Transfer & Penerbitan Resi AWB J&T
flowchart TD START([Mulai]) --> ADMIN_LOGIN[Admin Membuka Dashboard Kelola Transaksi] ADMIN_LOGIN --> VIEW_PENDING[Admin Memfilter Transaksi Berstatus: WAITING_VERIFICATION] VIEW_PENDING --> OPEN_DETAIL[Buka Detail Pembayaran: Struk Bukti Bayar & Nominal net_total] OPEN_DETAIL --> CHECK_MUTASI[Admin Membuka Rekening Koran Internet Banking / QRIS Mutasi] CHECK_MUTASI --> AUDIT_DECISION{Bukti Struk & Mutasi Bank Sesuai?} AUDIT_DECISION -->|Tidak Valid / Fiktif| INPUT_REASON[Admin Mengisi Alasan Penolakan di Form] INPUT_REASON --> SUBMIT_REJECT[Eksekusi Tolak Pembayaran] SUBMIT_REJECT --> DB_REJECT[Update payments: REJECTED & Increment reupload_attempts] DB_REJECT --> NOTIF_BUYER[Kirim Notifikasi Penolakan ke Pembeli via In-App / WA] NOTIF_BUYER --> BUYER_CHECK{Percobaan Upload <= 3x?} BUYER_CHECK -->|Bisa Re-Upload| BUYER_REUPLOAD[Pembeli Mengunggah Ulang Bukti Transfer Baru] BUYER_REUPLOAD --> VIEW_PENDING BUYER_CHECK -->|Batas Habis / Dibatalkan| DB_CANCEL[Update orders: CANCELLED & Kembalikan Stok] DB_CANCEL --> FINISH_CANCEL([Pesanan Batal]) AUDIT_DECISION -->|Valid & Dana Masuk| APPROVE_PAY[Admin Menyetujui Pembayaran] APPROVE_PAY --> DB_APPROVE[Update payments: VERIFIED & Update orders: PAID] DB_APPROVE --> CALL_JNT_API[Sistem Memanggil API J&T Express: Generate Air Waybill] CALL_JNT_API --> SAVE_SHIPMENT[Simpan ke shipments: waybill_number, courier_name, status MANIFESTED] SAVE_SHIPMENT --> PRINT_LABEL[Admin Mencetak Label Pengiriman & Tempel ke Paket] PRINT_LABEL --> HANDOVER_COURIER[Paket Diserahkan ke Kurir J&T Express: Status SHIPPED] HANDOVER_COURIER --> NOTIF_SUCCESS[Kirim Notifikasi Resi & Tautan Live Tracking ke Pembeli] NOTIF_SUCCESS --> FINISH_SUCCESS([Pengiriman Berjalan])
(Dapat disalin & di-render langsung di mermaid.live)

Gambar 3.5 Activity Diagram Verifikasi Pembayaran & Penerbitan Resi Logistik

Tabel 3.5 Deskripsi Alur Aktivitas Verifikasi Pembayaran & Logistik

Alur memodelkan proses verifikasi pembayaran transfer oleh administrator, pencegahan fraud bukti bayar fiktif, serta integrasi otomatis penerbitan resi kurir J&T Express saat transaksi terverifikasi.

3.7 Sequence Diagram Alur Sistem

Empat Sequence Diagram di bawah ini memodelkan pertukaran pesan dinamis antar komponen UI, Controller, Service Layer, dan Prisma ORM Database:

3.7.1 Sequence Diagram Registrasi dan Verifikasi OTP

Sequence Diagram Registrasi Pengguna dan Verifikasi OTP
sequenceDiagram autonumber actor User as Calon Pengguna participant View as Web Client UI participant AuthCtrl as AuthController participant OTPService as VerificationService participant DB as Prisma (MySQL) participant WA as Gateway WA / Email User->>View: Isi nama, email, no_telp, password View->>AuthCtrl: POST /api/auth/register (payload) AuthCtrl->>DB: findUnique({ where: { email } }) DB-->>AuthCtrl: null (email tersedia) AuthCtrl->>DB: users.create({ data: { is_active: false } }) DB-->>AuthCtrl: userRecord AuthCtrl->>OTPService: generateOTP(userRecord.id) OTPService->>DB: user_verifications.create({ token, expires_at }) DB-->>OTPService: verifRecord OTPService->>WA: sendOTPMessage(phone_number, token) WA-->>OTPService: Delivery Status: Sent AuthCtrl-->>View: 201 Created (Redirect ke Verifikasi OTP) User->>View: Input 6-Digit Kode OTP View->>AuthCtrl: POST /api/auth/verify-otp { user_id, token } AuthCtrl->>DB: findFirst(user_verifications valid & belum dipakai) DB-->>AuthCtrl: verifMatch AuthCtrl->>DB: $transaction([activateUser, markVerifUsed, createCart]) DB-->>AuthCtrl: Transaction Committed AuthCtrl-->>View: 200 OK { token: JWT, user: profile } View-->>User: Tampilkan Dashboard Akun Aktif
(Dapat disalin & di-render langsung di mermaid.live)

Gambar 3.6 Sequence Diagram Registrasi dan Verifikasi OTP

3.7.2 Sequence Diagram Simulasi Capacity Checker 3D

Sequence Diagram Simulasi Daya Tampung Tas (Capacity Inspector)
sequenceDiagram autonumber actor User as Calon Pembeli participant UI as ProductDetailPage UI participant ProdCtrl as ProductController participant CapEngine as CapacityEngine3D participant DB as Prisma (MySQL) User->>UI: Buka Halaman Detail Produk Tas UI->>ProdCtrl: GET /api/products/:slug ProdCtrl->>DB: products.findUnique({ include: { variants, images } }) DB-->>ProdCtrl: productData (PxLxT: 32x12x25cm, Volume: 9.6L) ProdCtrl-->>UI: 200 OK (Render Spesifikasi Produk) User->>UI: Klik 'Uji Kapasitas Muat 3D' UI->>ProdCtrl: GET /api/preset-capacities ProdCtrl->>DB: preset_bag_capacities.findMany() DB-->>ProdCtrl: listPresets (Laptop 14", Botol 600ml, Pouch) ProdCtrl-->>UI: 200 OK (Tampilkan Pilihan Objek) User->>UI: Centang Laptop 14" & Botol Minum 600ml UI->>CapEngine: evaluateFit(productDimensions, selectedItems) Note over CapEngine: Hitung Vol Item = 4.2L <= 9.6L
Uji Dimensi PxLxT & Sifat Kaku (Rigid) CapEngine-->>UI: Result: { isFit: true, percentUsed: 43.75%, status: 'FIT' } UI-->>User: Render Visualisasi 3D Hijau & Label 'Muat Sempurna' User->>UI: Klik 'Masukkan Keranjang' UI->>ProdCtrl: POST /api/cart/items { product_id, variant_id } ProdCtrl->>DB: cart_items.upsert() DB-->>ProdCtrl: cartItemRecord ProdCtrl-->>UI: 201 Added to Cart
(Dapat disalin & di-render langsung di mermaid.live)

Gambar 3.7 Sequence Diagram Simulasi Capacity Checker 3D

3.7.3 Sequence Diagram Checkout Pesanan dan Kalkulasi Logistik

Sequence Diagram Checkout Pesanan dan Kalkulasi Ongkir J&T
sequenceDiagram autonumber actor Buyer as Pembeli (Customer / Reseller) participant View as CheckoutView UI participant OrderCtrl as OrderController participant JntService as JntLogisticsService participant VoucherService as VoucherService participant DB as Prisma (MySQL) Buyer->>View: Pilih Alamat Kirim & Layanan J&T (EZ / CARGO) View->>OrderCtrl: POST /api/shipping/calculate-rate { address_id, cart_id, courier: 'J&T' } OrderCtrl->>DB: Hitung total_weight_grams dari seluruh cart_items DB-->>OrderCtrl: Total Bobot = 2.450 gram (Dibulatkan ke 3 Kg) OrderCtrl->>JntService: queryTariff(originDistrict, destDistrict, weight: 3kg, service: 'EZ') JntService-->>OrderCtrl: Tariff Response: Rp 36.000,- OrderCtrl-->>View: 200 OK { shipping_fee: 36000 } Buyer->>View: Input Kupon Diskon 'NALALAHEMAT' View->>VoucherService: validateVoucher(code, subtotal, user_id) VoucherService->>DB: vouchers.findUnique({ where: { code } }) DB-->>VoucherService: voucherData VoucherService-->>View: 200 OK { discount_product: 20000, net_total: subtotal + 36000 - 20000 } Buyer->>View: Klik 'Buat Pesanan & Bayar' View->>OrderCtrl: POST /api/orders/create (payload checkout) OrderCtrl->>DB: $transaction([orders.create, order_items.createMany, payments.create, clearCart]) DB-->>OrderCtrl: Order #NL-202610-008 Diterbitkan OrderCtrl-->>View: 201 Created { order_number, net_total, expires_at } View-->>Buyer: Tampilkan Rekening Transfer Toko & Instruksi Upload Bukti
(Dapat disalin & di-render langsung di mermaid.live)

Gambar 3.8 Sequence Diagram Checkout dan Kalkulasi Logistik

3.7.4 Sequence Diagram Verifikasi Pembayaran Admin & Penerbitan AWB

Sequence Diagram Verifikasi Pembayaran Admin & Auto-Generate Resi J&T
sequenceDiagram autonumber actor Admin as Administrator Toko participant AdminUI as AdminDashboard UI participant PayCtrl as PaymentVerificationController participant JntAPI as J&T Express Logistics API participant DB as Prisma (MySQL) participant NotifHub as NotificationGateway Admin->>AdminUI: Buka Daftar Pembayaran Menunggu Verifikasi AdminUI->>PayCtrl: GET /api/admin/payments?status=WAITING_VERIFICATION PayCtrl->>DB: payments.findMany({ include: { order, payment_account } }) DB-->>PayCtrl: listWaitingPayments PayCtrl-->>AdminUI: 200 OK (Render Tabel & Bukti Struk) Admin->>AdminUI: Cek Mutasi Bank & Klik 'Setujui Pembayaran' AdminUI->>PayCtrl: POST /api/admin/payments/:id/verify { action: 'APPROVE', admin_id } PayCtrl->>DB: orders.findUnique({ where: { id: order_id } }) DB-->>PayCtrl: orderRecord PayCtrl->>JntAPI: requestAWB(senderAddress, orderRecord.shipping_address, weight, service) JntAPI-->>PayCtrl: 200 Success { waybill_number: 'JT8829102910' } PayCtrl->>DB: $transaction([payments.update(VERIFIED), orders.update(PAID), shipments.create(JT8829102910)]) DB-->>PayCtrl: Transaction Committed PayCtrl->>NotifHub: dispatchNotification(order.user_id, 'Pembayaran Lunas & Resi Terbit: JT8829102910') NotifHub-->>PayCtrl: Notification Queued PayCtrl-->>AdminUI: 200 OK { message: 'Pembayaran Diverifikasi & Resi Berhasil Diterbitkan' } AdminUI-->>Admin: Tampilkan Tombol Cetak Label Pengiriman J&T
(Dapat disalin & di-render langsung di mermaid.live)

Gambar 3.9 Sequence Diagram Verifikasi Pembayaran & Penerbitan AWB

3.8 Comprehensive Domain Class Diagram (24 Kelas)

Class diagram pada Gambar 3.10 menyajikan 24 kelas domain bisnis perangkat lunak yang selaras secara presisi dengan 24 model tabel basis data, lengkap dengan atribut, tipe data, serta operasi/metode pada service layer:

Comprehensive Domain Class Diagram Sistem Nalala Store (24 Entitas)
classDiagram direction TB class User { +BigInt id +String name +String email +String phone_number +String password_hash +Role role +Boolean is_active +register() +login() +verifyOTP() } class UserAddress { +BigInt id +BigInt user_id +String label +String recipient_name +String city +String postal_code +Boolean is_primary +setPrimary() } class UserVerification { +BigInt id +BigInt user_id +VerificationType type +String token +Boolean is_used +DateTime expires_at +isExpired() Boolean } class UserToken { +BigInt id +BigInt user_id +String token_hash +DateTime expires_at +revoke() } class Category { +BigInt id +BigInt parent_id +String name +String slug +Boolean is_active +getSubCategories() } class Product { +BigInt id +BigInt category_id +String name +String slug +Int weight_grams +Decimal base_price_customer +Decimal base_price_reseller +Decimal length_cm +Decimal width_cm +Decimal height_cm +Decimal volume_liters +getEffectivePrice(role) Decimal } class ProductVariant { +BigInt id +BigInt product_id +String color_name +String sku +Int stock +Decimal price_adjustment +deductStock(qty) } class ProductImage { +BigInt id +BigInt product_id +BigInt variant_id +String image_url +Boolean is_primary } class PresetBagCapacity { +BigInt id +String name +String category +Decimal length_cm +Decimal width_cm +Decimal height_cm +Decimal volume_liters +Boolean is_rigid } class ResellerPackage { +BigInt id +String name +String slug +Decimal package_price +Int required_quantity +Boolean is_active +validateQuota(count) Boolean } class ProductResellerPackage { +BigInt id +BigInt product_id +BigInt reseller_package_id } class Voucher { +BigInt id +String code +VoucherType type +DiscountType discount_type +Decimal discount_value +Decimal min_spend +Int quota_total +Int quota_used +calculateDiscount(amount) Decimal } class VoucherProduct { +BigInt id +BigInt voucher_id +BigInt product_id } class UserVoucherUsage { +BigInt id +BigInt user_id +BigInt voucher_id +DateTime used_at } class Cart { +BigInt id +BigInt user_id +calculateTotal() Decimal +clear() } class CartSection { +BigInt id +BigInt cart_id +BigInt reseller_package_id +isQuotaFulfilled() Boolean } class CartItem { +BigInt id +BigInt cart_id +BigInt cart_section_id +BigInt product_id +BigInt variant_id +Int quantity +getSubtotal() Decimal } class Order { +BigInt id +String order_number +BigInt user_id +OrderStatus status +Decimal net_total +Int total_weight_grams +JSON shipping_address +cancel() +markPaid() } class OrderItem { +BigInt id +BigInt order_id +BigInt product_id +BigInt variant_id +String sku +Decimal unit_price +Int quantity +Decimal total_price } class Payment { +BigInt id +BigInt order_id +BigInt payment_account_id +Decimal amount +PaymentStatus status +String proof_image_url +approve(adminId) +reject(reason) } class PaymentAccount { +BigInt id +AccountType type +String provider_name +String account_number +String account_holder_name +Boolean is_active } class Shipment { +BigInt id +BigInt order_id +String waybill_number +String courier_name +ServiceType service_type +ShipmentStatus status +JSON tracking_logs +updateTracking() } class Notification { +BigInt id +BigInt user_id +String title +String message +Boolean is_read +markAsRead() } User "1" --> "0..*" UserAddress User "1" --> "0..*" UserVerification User "1" --> "0..*" UserToken User "1" --> "1" Cart User "1" --> "0..*" Order User "1" --> "0..*" UserVoucherUsage User "1" --> "0..*" Notification Category "1" --> "0..*" Product Product "1" --> "0..*" ProductVariant Product "1" --> "0..*" ProductImage Product "1" --> "0..*" ProductResellerPackage Product "1" --> "0..*" VoucherProduct ResellerPackage "1" --> "0..*" ProductResellerPackage ResellerPackage "1" --> "0..*" CartSection Cart "1" --> "0..*" CartSection Cart "1" --> "0..*" CartItem CartSection "0..1" --> "0..*" CartItem Voucher "1" --> "0..*" VoucherProduct Voucher "1" --> "0..*" UserVoucherUsage Order "1" --> "1..*" OrderItem Order "1" --> "1" Payment Order "1" --> "1" Shipment PaymentAccount "1" --> "0..*" Payment
(Dapat disalin & di-render langsung di mermaid.live)

Gambar 3.10 Domain Class Diagram Sistem Nalala Store (24 Entitas)

BAB IV - PERANCANGAN ANTARMUKA (USER INTERFACE)

Perancangan antarmuka sistem e-commerce Nalala Store dirancang menggunakan tata letak responsif ramah seluler dan desktop. Berikut adalah representasi 7 layar wireframe berbasis ASCII yang memetakan alur transaksi dari penelusuran produk hingga audit verifikasi pesanan:

4.1 UI-01 - Beranda & Katalog Produk Tas Fashion (Navigasi & Filter)

Antarmuka utama pengunjung untuk mengeksplorasi koleksi tas fashion wanita, pencarian berdasarkan kategori (Sling Bag, Tote Bag, Ransel, Shoulder Bag), serta filter harga dan status stok.

+----------------------------------------------------------------------------------------------------+
|  [LOGO NALALA STORE]     [Cari Tas Fashion...]         (Katalog) (Paket Reseller) (Keranjang: 2) [Login]   |
+----------------------------------------------------------------------------------------------------+
|                                                                                                    |
|  +==================================== HERO BANNER PROMO =======================================+  |
|  |  KOLEKSI TAS WANITA TERKINI & PAKET USAHA RESELLER SPESIAL                                    |  |
|  |  Mulai Bisnis Grosir Tas dengan Paket Cuan 11 Pcs Flat Rp 750.000,- | Gratis Ongkir J&T       |  |
|  |  [ Belanja Sekarang ]    [ Gabung Mitra Reseller ]                                            |  |
|  +===============================================================================================+  |
|                                                                                                    |
|  KATEGORI:  [Semua]  [Sling Bag]  [Shoulder Bag]  [Tote Bag]  [Ransel Wanita]  [Tas Kerja Laptop]  |
|  ------------------------------------------------------------------------------------------------  |
|  FILTER: [Harga: Semua v] [Bahan: Kulit PU v] [Warna: Hitam v]           Urutkan: [Terpopuler v]   |
|                                                                                                    |
|  +---------------------+   +---------------------+   +---------------------+   +-----------------+ |
|  | [ FOTO PRODUK ]     |   | [ FOTO PRODUK ]     |   | [ FOTO PRODUK ]     |   | [ FOTO PRODUK ] | |
|  | NALALA AURA SLING   |   | NALALA CLARA TOTE   |   | NALALA URBAN BACKPK |   | NALALA SOFIA SHL| |
|  | P:24 L:8 T:16 cm    |   | P:34 L:12 T:28 cm   |   | P:30 L:14 T:40 cm   |   | P:26 L:9 T:18 cm| |
|  | Vol: 3.1 Liter      |   | Vol: 11.4 Liter     |   | Vol: 16.8 Liter     |   | Vol: 4.2 Liter  | |
|  | Rp 129.000,-        |   | Rp 189.000,-        |   | Rp 249.000,-        |   | Rp 145.000,-    | |
|  | [Uji Muatan 3D]     |   | [Uji Muatan 3D]     |   | [Uji Muatan 3D]     |   | [Uji Muatan 3D] | |
|  | [ + Keranjang ]     |   | [ + Keranjang ]     |   | [ + Keranjang ]     |   | [ + Keranjang ] | |
|  +---------------------+   +---------------------+   +---------------------+   +-----------------+ |
|                                                                                                    |
|                                        << [1]  [2]  [3]  [4] >>                                    |
+----------------------------------------------------------------------------------------------------+

4.2 UI-02 - Detail Produk & Modal Simulasi 3D Capacity Checker

Halaman spesifikasi detail produk yang terintegrasi dengan modal simulasi interaktif 3D Capacity Checker untuk memvisualisasikan daya muat barang bawaan harian pembeli sebelum transaksi.

+----------------------------------------------------------------------------------------------------+
|  [ < Kembali ke Katalog ]                                          Nalala Store / Tote Bag / Clara |
+----------------------------------------------------------------------------------------------------+
|  [ GALERI FOTO PRODUK ]           |  NALALA CLARA PREMIUM TOTE BAG (KULIT PU WATERPROOF)           |
|                                   |  SKU: NL-CLR-BLK-01 | Kategori: Tote Bag | Terjual: 142 Pcs    |
|  +-----------------------------+  |  Harga Eceran: Rp 189.000,-  (Harga Reseller: Rp 145.000,-)    |
|  |                             |  |  -------------------------------------------------------------  |
|  |      [ FOTO UTAMA 1 ]       |  |  PILIH VARIAN WARNA:                                            |
|  |                             |  |  (x) Hitam Obsidian   ( ) Mocca Latte   ( ) Sage Green          |
|  +-----------------------------+  |  Stok Tersedia: 38 Pcs                                          |
|  [Thumb 1] [Thumb 2] [Thumb 3]    |  -------------------------------------------------------------  |
|                                   |  DIMENSI FISIK & KAPASITAS KUBIKASI:                            |
|                                   |  Panjang: 34 cm | Lebar: 12 cm | Tinggi: 28 cm | Vol: 11.4 Liter|
|                                   |  Berat Fisik: 650 gram | Maksimal Laptop: 14.0 Inci             |
|                                   |  -------------------------------------------------------------  |
|                                   |  [!] RAGU BARANG BAWAAN ANDA MUAT?                              |
|                                   |  [ >>> KLIK DI SINI: UJI KAPASITAS MUAT 3D <<< ]                |
|                                   |  -------------------------------------------------------------  |
|                                   |  Jumlah: [-] [ 1 ] [+]        [ + Masukkan Keranjang ] [Beli]   |
+-----------------------------------+----------------------------------------------------------------+
|  +============================= MODAL 3D CAPACITY CHECKER =======================================+  |
|  |  SIMULASI DAYA MUAT TAS: NALALA CLARA TOTE (Kapasitas Maksimal: 11.4 Liter)                   |  |
|  |  -------------------------------------------------------------------------------------------  |
|  |  PILIH BARANG BAWAAN HARIAN ANDA:          |  VISUALISASI KONTAINER 3D (TOLERANSI RUANG):     |  |
|  |  [x] Laptop 14 Inci  (P:32 L:22 T:2 cm)    |  +--------------------------------------------+  |
|  |  [x] Botol Minum 600ml (D:7 T:23 cm)       |  |  +--------------------------------------+  |  |
|  |  [x] Pouch Make-Up (P:18 L:8 T:12 cm)      |  |  |  [LAPTOP 14"]    [BOTOL]   [POUCH]   |  |  |
|  |  [ ] Mukena Travel Pouch                   |  |  |  Total Terpakai: 5.4 Liter (47.3%)   |  |  |
|  |  [ ] Buku Agenda A5                        |  |  +--------------------------------------+  |  |
|  |  [ ] Payung Lipat Otomatis                 |  |  STATUS DAYA MUAT:  [ OKE: SEMUA MUAT (FIT) ]  |  |
|  |                                            |  +--------------------------------------------+  |  |
|  |  [ Reset Pilihan ]                         |  [ Tutup Modal ]  [ Tetap Masukkan Keranjang ]    |  |
|  +===============================================================================================+  |
+----------------------------------------------------------------------------------------------------+

4.3 UI-03 - Katalog Pemilihan Paket Usaha Reseller (Kompilasi Kuota Wajib 11 Pcs)

Antarmuka pemesanan grosir khusus mitra reseller untuk memilih kombinasi 11 pcs tas pilihan dari daftar produk yang diizinkan dengan penegakan validasi kuota flat otomatis.

+----------------------------------------------------------------------------------------------------+
|  [LOGO NALALA STORE]           PORTAL MITRA RESELLER: PAKET USAHA 11 PCS               [Saldo/Akun] |
+----------------------------------------------------------------------------------------------------+
|  +================================== ATURAN PAKET USAHA ========================================+  |
|  |  PAKET USAHA CUAN 11 PCS - HARGA FLAT BUNDLE: Rp 750.000,- (Harga Rata-rata Rp 68.180/pcs)   |  |
|  |  Syarat: Anda WAJIB memilih tepat 11 item tas dari katalog produk di bawah ini.               |  |
|  |  STATUS SELEKSI SAAT INI: [ 8 / 11 PCS TERPILIH ]  -----> [ BUTUH 3 PCS LAGI UNTUK LANJUT ]  |  |
|  +==============================================================================================+  |
|                                                                                                    |
|  KATALOG PRODUK PAKET USAHA TERSEDIA:                                                              |
|  +-----------------------+  +-----------------------+  +-----------------------+  +--------------+ |
|  | NALALA AURA SLING     |  | NALALA SOFIA SHOULDER |  | NALALA DIANA TOTE     |  | NALALA MINI  | |
|  | Varian: Hitam         |  | Varian: Mocca         |  | Varian: Cream         |  | Varian: Sage | |
|  | Stok: 24 | Terpilih: 3|  | Stok: 15 | Terpilih: 2|  | Stok: 30 | Terpilih: 3|  | Stok: 10     | |
|  | [-] [ 3 ] [+]         |  | [-] [ 2 ] [+]         |  | [-] [ 3 ] [+]         |  | [-] [ 0 ] [+] | |
|  +-----------------------+  +-----------------------+  +-----------------------+  +--------------+ |
|                                                                                                    |
|  RINGKASAN KOMPOSISI PAKET ANDA:                                                                   |
|  1. Nalala Aura Sling (Hitam) x 3 Pcs                                                              |
|  2. Nalala Sofia Shoulder (Mocca) x 2 Pcs                                                          |
|  3. Nalala Diana Tote (Cream) x 3 Pcs                                                              |
|  TOTAL SAAT INI: 8 Pcs (Kurang 3 Pcs) | Total Bobot Estimasi: 5.200 gram (J&T CARGO Disarankan)   |
|                                                                                                    |
|  [ Batal / Kosongkan ]                     [ Masukkan Paket ke Keranjang (Terkunci: Belum 11) ]   |
+----------------------------------------------------------------------------------------------------+

4.4 UI-04 - Keranjang Belanja (Pemisahan Section Reguler vs Paket Usaha)

Antarmuka keranjang belanja yang mengelompokkan barang eceran satuan dan paket grosir reseller secara terpisah agar perhitungan diskon dan kuota paket tidak tercampur.

+----------------------------------------------------------------------------------------------------+
|  [LOGO NALALA]                     KERANJANG BELANJA ANDA                             [Lanjut Belanja]     |
+----------------------------------------------------------------------------------------------------+
|  SECTION 1: BELANJA REGULER (ECERAN SATUAN)                                                        |
|  +---+---------------------------------+---------------+------------+---------------+----------+   |
|  | v | Produk & Varian                 | Harga Satuan  | Kuantitas  | Total Harga   | Aksi     |   |
|  +---+---------------------------------+---------------+------------+---------------+----------+   |
|  | [x| Nalala Clara Tote - Hitam       | Rp 189.000,-  | [-] 1 [+]  | Rp 189.000,-  | [Hapus]  |   |
|  +---+---------------------------------+---------------+------------+---------------+----------+   |
|  Subtotal Belanja Reguler: Rp 189.000,- (Bobot: 650 gram)                                          |
|                                                                                                    |
|  SECTION 2: PAKET USAHA RESELLER #1 (KUOTA 11 PCS VALID - LENGKAP)                                |
|  +=============================================================================================+   |
|  | Paket Usaha Cuan 11 Pcs (Harga Flat Bundle Terkunci)            Harga Paket: Rp 750.000,-   |   |
|  | - 3x Nalala Aura Sling (Hitam)                                                              |   |
|  | - 3x Nalala Sofia Shoulder (Mocca)                                                          |   |
|  | - 5x Nalala Diana Tote (Cream)                                                              |   |
|  | Status Kuota: [ 11 / 11 PCS TEPAT - VALID ]                     [Edit Item Paket] [Hapus]   |   |
|  +=============================================================================================+   |
|  Subtotal Paket Usaha #1: Rp 750.000,- (Bobot: 6.800 gram)                                         |
|  ------------------------------------------------------------------------------------------------  |
|  RINGKASAN BELANJA:                                                                                |
|  Total Item: 12 Pcs (1 Reguler + 11 Paket Reseller) | Total Bobot: 7.450 gram (7.5 Kg)            |
|  Akumulasi Subtotal: Rp 939.000,-                                                                  |
|                                                                                                    |
|  [ Lanjut ke Form Checkout & Ekspedisi J&T Express >> ]                                            |
+----------------------------------------------------------------------------------------------------+

4.5 UI-05 - Form Checkout Pesanan & Kalkulasi Ongkir J&T Express

Halaman konfirmasi checkout dengan pemilihan alamat pengiriman, kalkulasi bobot gabungan, pemilihan jenis layanan kurir J&T Express (EZ / CARGO), dan penukaran kupon voucher.

+----------------------------------------------------------------------------------------------------+
|  [LOGO NALALA]                   CHECKOUT PESANAN & PENGIRIMAN J&T EXPRESS                         |
+----------------------------------------------------------------------------------------------------+
|  1. ALAMAT PENGIRIMAN:                                   |  RINGKASAN PEMBAYARAN:                  |
|  [v] Siti Rahmawati (Rumah Utama)                        |  Subtotal Produk Reguler : Rp 189.000   |
|      Jl. Melati No. 45 RT 02/05, Kebayoran Baru,         |  Subtotal Paket Usaha    : Rp 750.000   |
|      Kota Jakarta Selatan, DKI Jakarta 12150             |  Ongkos Kirim J&T CARGO  : Rp  45.000   |
|      No. Telp: 0812-9876-5432                            |  Diskon Voucher (HEMAT)  : -Rp 25.000   |
|  [ + Pilih Alamat Lain ]  [ + Tambah Alamat Baru ]       |  ------------------------------------   |
|                                                          |  TOTAL TAGIHAN (NET)     : Rp 959.000   |
|  ------------------------------------------------------- |                                         |
|  2. METODE PENGIRIMAN (KURIR J&T EXPRESS):               |  KUPON PROMO / VOUCHER:                 |
|  Total Bobot Pesanan: 7.450 gram (Dibulatkan ke 8 Kg)    |  +------------------------------------+ |
|                                                          |  | KODE: [ NALALAHEMAT      ] [Klaim] | |
|  ( ) J&T EZ (Reguler Estimasi 2-3 Hari)                  |  +------------------------------------+ |
|      Tarif: Rp 12.000 / Kg x 8 Kg = Rp 96.000,-          |  [V] Diskon Rp 25.000,- Berhasil Pasang!|
|                                                          |                                         |
|  (x) J&T CARGO (Grosir Khusus Bobot >= 5 Kg - Disarankan)|  Tenggat Pembayaran: 24 Jam             |
|      Tarif Flat Grosir = Rp 45.000,- (Hemat Rp 51.000)   |                                         |
|                                                          |  [ >>> LANJUTKAN KE PEMBAYARAN <<< ]    |
|  Catatan Kurir: "Tolong titip di pos satpam bila kosong" |                                         |
+----------------------------------------------------------+-----------------------------------------+

4.6 UI-06 - Pembayaran Transfer Multi-Rekening & Form Unggah Struk Bukti Bayar

Antarmuka penyelesaian transaksi yang menampilkan nomor rekening resmi toko (BCA, Mandiri, QRIS), batas waktu pembayaran 24 jam, serta formulir pengunggahan foto struk bukti transfer.

+----------------------------------------------------------------------------------------------------+
|  [LOGO NALALA]                   PORTAL PEMBAYARAN & UPLOAD BUKTI TRANSFER                         |
+----------------------------------------------------------------------------------------------------+
|  NOMOR FAKTUR PESANAN: #NL-ORD-202610-0089                  STATUS: [ MENUNGGU PEMBAYARAN ]        |
|  Sisa Waktu Pembayaran: [ 23 Jam 48 Menit 12 Detik ] (Batas: 15 Okt 2026, 14:30 WIB)              |
|  ------------------------------------------------------------------------------------------------  |
|  TOTAL YANG WAJIB DITRANSFER:                                                                      |
|  +==============================================================================================+  |
|  |   Rp 959.000,-   [ Salin Jumlah ]  (Harap transfer tepat hingga digit terakhir)              |  |
|  +==============================================================================================+  |
|                                                                                                    |
|  PILIH KANAL REKENING PEMBAYARAN TUJUAN:                                                           |
|  (x) BANK CENTRAL ASIA (BCA)     ( ) BANK MANDIRI               ( ) QRIS NALALA STORE DINAMIS      |
|      No. Rek: 8820-1928-11           No. Rek: 137-00-1928-111       [ Tampilkan Kode QR ]          |
|      A.N: NALALA STORE OFFICIAL      A.N: NALALA STORE OFFICIAL     Mendukung BCA, GoPay, OVO, dll |
|      [ Salin No Rekening ]           [ Salin No Rekening ]                                         |
|  ------------------------------------------------------------------------------------------------  |
|  FORMULIR UNGGAH BUKTI STRUK TRANSFER:                                                             |
|  Nama Bank Pengirim   : [ Bank BCA                              ]                                  |
|  Nama Pemilik Rekening: [ Siti Rahmawati                        ]                                  |
|  Waktu Transfer       : [ 14/10/2026 15:45 WIB                  ]                                  |
|  Unggah Foto Bukti    : [ Browse... ] struk_transfer_bca_959rb.jpg (Maksimal 5MB, format JPG/PNG) |
|                                                                                                    |
|  [ X Batalkan Pesanan ]                               [ >>> KIRIM BUKTI PEMBAYARAN <<< ]          |
+----------------------------------------------------------------------------------------------------+

4.7 UI-07 - Dashboard Admin Verifikasi Mutasi Rekening & Penerbitan Resi J&T

Panel kontrol administrator toko untuk memverifikasi keabsahan bukti struk bayar terhadap mutasi rekening koran bank, menyetujui transaksi, serta menerbitkan resi otomatis AWB J&T.

+----------------------------------------------------------------------------------------------------+
|  NALALA ADMIN CONSOLE         [Pesanan]  [Verifikasi Bayar (3)]  [Produk]  [Resi J&T]   (Admin Nalala v)   |
+----------------------------------------------------------------------------------------------------+
|  AUDIT VERIFIKASI PEMBAYARAN (STATUS: WAITING_VERIFICATION)                                        |
|  ------------------------------------------------------------------------------------------------  |
|  DAFTAR ANTRIAN:                                                                                   |
|  1. #NL-ORD-202610-0089 | Pembeli: Siti Rahmawati | Net: Rp 959.000,- | BCA | [AUDIT SEKARANG]     |
|  2. #NL-ORD-202610-0088 | Pembeli: Dewi Sartika   | Net: Rp 750.000,- | QRIS| [AUDIT SEKARANG]     |
|  ------------------------------------------------------------------------------------------------  |
|  DETAIL TRANSAKSI TERPILIH: #NL-ORD-202610-0089                                                   |
|  +-----------------------------------+---------------------------------------------------------+  |
|  | PRATINJAU BUKTI STRUK TRANSFER:   | DATA VERIFIKASI TRANSAKSI:                              |  |
|  | +-------------------------------+ | Order ID     : #NL-ORD-202610-0089                      |  |
|  | | [ CITRA STRUK TRANSFER BCA ]  | | Pembeli      : Siti Rahmawati (CUSTOMER)                |  |
|  | | Nilai Tercetak: Rp 959.000,-  | | Tagihan Net  : Rp 959.000,-                             |  |
|  | | Pengirim: Siti Rahmawati      | | Bank Tujuan  : BCA (8820-1928-11 A.N Nalala Official)   |  |
|  | | Tanggal : 14/10/2026 15:45    | | Ekspedisi    : J&T CARGO (Bobot: 7.5 Kg)                |  |
|  | +-------------------------------+ | Percobaan Ke : 1 dari 3x batas re-upload                |  |
|  | [ Perbesar Gambar Bukti Struk ] | ------------------------------------------------------- |  |
|  |                                   | KEPUTUSAN VERIFIKASI ADMIN:                             |  |
|  | Catatan Penolakan (Jika Fiktif):  | [v] Mutasi Internet Banking Sesuai (Dana Telah Masuk)   |  |
|  | [                               ] |                                                         |  |
|  | [ X TOLAK PEMBAYARAN ]            | [ >>> SETUJUI PEMBAYARAN & TERBITKAN RESI J&T <<< ]     |  |
|  +-----------------------------------+---------------------------------------------------------+  |
|  * Saat disetujui: Sistem otomatis memanggil API J&T, menghasilkan Nomor Resi (AWB), mengubah      |  |
|    status pesanan menjadi PAID, dan mengirim notifikasi WhatsApp resi ke nomor pelanggan.         |  |
+----------------------------------------------------------------------------------------------------+

BAB V - PENGUJIAN SISTEM

Pengujian sistem dilakukan secara komprehensif melalui dua pendekatan: pengujian struktural internal (White Box Testing) dengan metode Basis Path Testing pada fungsi inti verifikasi pembayaran, serta pengujian fungsionalitas eksternal (Black Box Testing) dengan metode Equivalence Partitioning dan Boundary Value Analysis.

5.1 White Box Testing - Fungsi verifyPayment()

Fungsi verifyPayment() pada service layer merupakan titik kritis integritas finansial dan logistik sistem yang bertugas memvalidasi bukti struk pembayaran, memeriksa kecukupan nominal transfer terhadap nilai net_total, mengeksekusi penolakan atau persetujuan, serta menerbitkan resi AWB J&T Express.

5.1.1 Pseudocode Logika Fungsi verifyPayment()

async function verifyPayment(orderId, adminId, action, rejectionReason) {
  // [Node 1] Inisialisasi proses verifikasi audit pembayaran
  const payment = await prisma.payments.findUnique({
    where: { order_id: orderId },
    include: { order: true }
  });

  // [Node 2] Predikat 1: Apakah entitas pembayaran ditemukan?
  if (!payment) {
    // [Node 11] Lempar exception error data tidak ditemukan
    throw new Error("ERR_PAYMENT_NOT_FOUND");
  }

  // [Node 3] Predikat 2: Apakah status pembayaran sedang menunggu audit?
  if (payment.status !== 'WAITING_VERIFICATION') {
    // [Node 11] Lempar exception status tidak valid untuk diverifikasi
    throw new Error("ERR_INVALID_PAYMENT_STATUS");
  }

  // [Node 4] Predikat 3: Apakah aksi admin adalah PENOLAKAN (REJECT)?
  if (action === 'REJECT') {
    // [Node 5] Eksekusi penolakan transaksi dalam atomic transaction
    await prisma.$transaction([
      prisma.payments.update({
        where: { id: payment.id },
        data: {
          status: 'REJECTED',
          rejection_reason: rejectionReason,
          reupload_attempts: { increment: 1 }
        }
      }),
      prisma.orders.update({
        where: { id: orderId },
        data: { status: 'PENDING_PAYMENT' }
      }),
      prisma.notifications.create({
        data: {
          user_id: payment.order.user_id,
          title: 'Pembayaran Ditolak',
          message: 'Bukti transfer tidak sesuai: ' + rejectionReason,
          type: 'PAYMENT_REJECTED'
        }
      })
    ]);
    // [Node 6] Selesai: Kembalikan respons penolakan sukses
    return { success: false, status: 'REJECTED' };
  }

  // [Node 7] Aksi APPROVE: Ambil entitas order terkait untuk evaluasi nominal
  const order = await prisma.orders.findUnique({ where: { id: orderId } });

  // [Node 8] Predikat 4: Apakah nominal transfer mencukupi net_total order?
  if (payment.amount < order.net_total) {
    // [Node 11] Lempar exception nominal transfer kurang dari tagihan
    throw new Error("ERR_AMOUNT_INSUFFICIENT");
  }

  // [Node 9] Terbitkan nomor resi J&T Express dan setujui transaksi
  const generatedAwb = await jntLogisticsService.generateAWB(order);
  await prisma.$transaction([
    prisma.payments.update({
      where: { id: payment.id },
      data: {
        status: 'VERIFIED',
        verified_at: new Date(),
        verified_by: adminId
      }
    }),
    prisma.orders.update({
      where: { id: orderId },
      data: { status: 'PAID' }
    }),
    prisma.shipments.create({
      data: {
        order_id: orderId,
        waybill_number: generatedAwb,
        courier_name: 'J&T Express',
        service_type: order.shipping_service,
        status: 'MANIFESTED',
        tracking_logs: JSON.stringify([{
          timestamp: new Date(),
          status: 'MANIFESTED',
          note: 'Resi dicetak, paket menunggu pickup kurir J&T'
        }])
      }
    }),
    prisma.notifications.create({
      data: {
        user_id: order.user_id,
        title: 'Pembayaran Diterima & Resi Terbit',
        message: 'Pesanan Anda telah dibayar. Nomor Resi J&T: ' + generatedAwb,
        type: 'PAYMENT_VERIFIED'
      }
    })
  ]);

  // [Node 10] Selesai: Kembalikan respons approval dan nomor resi AWB J&T
  return { success: true, status: 'VERIFIED', waybill: generatedAwb };
}

5.1.2 Graf Alir (Flow Graph)

Graf alir pada Gambar 5.1 memetakan aliran kendali eksekusi fungsi verifyPayment() ke dalam 11 node dan 14 edge:

Graf Alir (Flow Graph) Logika verifyPayment() - White Box Testing
flowchart TD 1([Node 1: Start verifyPayment]) --> 2{Node 2: payment == null?} 2 -->|Ya / True| 11([Node 11: Throw PAYMENT_NOT_FOUND]) 2 -->|Tidak / False| 3{Node 3: status != WAITING_VERIFICATION?} 3 -->|Ya / True| 11 3 -->|Tidak / False| 4{Node 4: action == REJECT?} 4 -->|Ya / True| 5[Node 5: Execute DB Reject & Notify] 5 --> 6([Node 6: Return REJECTED]) 4 -->|Tidak / False: APPROVE| 7[Node 7: Fetch Order by orderId] 7 --> 8{Node 8: amount < net_total?} 8 -->|Ya / True| 11 8 -->|Tidak / False| 9[Node 9: Generate J&T AWB & DB Commit] 9 --> 10([Node 10: Return VERIFIED with Waybill])
(Dapat disalin & di-render langsung di mermaid.live)

Gambar 5.1 Graf Alir (Flow Graph) Pengujian White Box Fungsi verifyPayment()

5.1.3 Perhitungan Kompleksitas Siklomatis (Cyclomatic Complexity)

Kompleksitas siklomatis dihitung menggunakan tiga formula matematis dasar pengujian perangkat lunak:

  1. Formula Predikat Keputusan (P + 1):
    Jumlah node predikat (node percabangan keputusan) bernilai 4 (Node 2, Node 3, Node 4, dan Node 8).
    V(G) = P + 1 = 4 + 1 = 5
  2. Formula Edge dan Node (E - N + 2):
    Jumlah sisi aliran kendali (Edges) E = 14, dan jumlah simpul pernyataan (Nodes) N = 11.
    V(G) = E - N + 2 = 14 - 11 + 2 = 5
  3. Formula Region Terisolasi (R):
    Jumlah area tertutup dan tidak tertutup pada graf bidang datar berjumlah 5 region.
    V(G) = R = 5

Berdasarkan perhitungan di atas, diperoleh V(G) = 5, yang berarti terdapat tepat 5 jalur independen (Basis Paths) yang wajib diuji untuk menjamin 100% statement and branch coverage.

5.1.4 Tabel Kasus Uji Basis Path Testing

Jalur Rute Node Aliran Skenario & Data Uji Hasil yang Diharapkan Status
Path 1 1 → 2 (True) → 11 Input: orderId = 99999 (Non-existent), action = APPROVE
Order ID tidak memiliki catatan pembayaran pada basis data (Payment Not Found).
Throw Exception: ERR_PAYMENT_NOT_FOUND PASS
Path 2 1 → 2 (False) → 3 (True) → 11 Input: orderId = 101, payment.status = PAID, action = APPROVE
Status pembayaran bukan WAITING_VERIFICATION (misal: sudah VERIFIED atau PENDING_PAYMENT).
Throw Exception: ERR_INVALID_PAYMENT_STATUS PASS
Path 3 1 → 2 (False) → 3 (False) → 4 (True) → 5 → 6 Input: orderId = 102, status = WAITING_VERIFICATION, action = 'REJECT', reason = 'Bukti mutasi fiktif'
Admin menolak bukti struk pembayaran (REJECT) karena fiktif, buram, atau nama pengirim berbeda.
Payment status REJECTED, reupload_attempts bertambah 1, order kembali PENDING_PAYMENT, notifikasi dikirim. PASS
Path 4 1 → 2 (False) → 3 (False) → 4 (False) → 7 → 8 (True) → 11 Input: orderId = 103, net_total = Rp 959.000, payment.amount = Rp 500.000, action = APPROVE
Admin memilih APPROVE namun nominal transfer yang diinput/tercatat kurang dari net_total pesanan.
Throw Exception: ERR_AMOUNT_INSUFFICIENT PASS
Path 5 1 → 2 (False) → 3 (False) → 4 (False) → 7 → 8 (False) → 9 → 10 Input: orderId = 104, net_total = Rp 959.000, payment.amount = Rp 959.000, action = APPROVE
Aksi APPROVE sukses: nominal transfer sesuai, status diubah ke VERIFIED/PAID, resi J&T terbit otomatis.
Payment VERIFIED, Order PAID, Record Shipment dibuat dengan AWB J&T, Notifikasi terkirim, return waybill. PASS

5.2 Black Box Testing (16 Skenario Fungsional)

Pengujian fungsionalitas sistem dilakukan terhadap 16 skenario operasional menggunakan teknik Equivalence Partitioning (EP) untuk memvalidasi partisi data valid/invalid, serta Boundary Value Analysis (BVA) untuk menguji batas kritis kuota 11 pcs paket reseller, batas waktu 5 menit OTP, dan pembulatan bobot gram ekspedisi J&T Express:

ID Fitur Sistem Metode Skenario & Data Uji Hasil yang Diharapkan Hasil
BB-01 Registrasi Akun Baru Equivalence Partitioning Pengisian form registrasi dengan nama valid, format email benar, dan kata sandi ≥ 8 karakter.
Name: 'Siti Rahma', Email: 'siti@example.com', Password: 'Password123!'
Akun tersimpan di users dengan status is_active = false, sistem mengirim 6-digit OTP ke email. PASS
BB-02 Registrasi Akun Duplikat Equivalence Partitioning Pengisian form pendaftaran menggunakan alamat email yang sudah terdaftar di sistem.
Email: 'siti@example.com' (Sudah ada di DB)
Sistem menolak dengan HTTP 409 Conflict dan pesan 'Email sudah terdaftar'. PASS
BB-03 Verifikasi Token OTP Boundary Value Analysis Penginputan kode token OTP pada detik ke-299 (sebelum 5 menit kedaluwarsa).
Token: 849201, Waktu kirim: 04:59 lalu
OTP valid, user_verifications diupdate is_used = true, akun users diaktifkan (is_active = true). PASS
BB-04 Verifikasi Token OTP Expired Boundary Value Analysis Penginputan kode token OTP pada detik ke-301 (melebihi batas 5 menit kedaluwarsa).
Token: 849201, Waktu kirim: 05:01 lalu
Sistem menolak verifikasi dengan status 400 Bad Request: 'Kode OTP telah kedaluwarsa'. PASS
BB-05 Capacity Checker 3D (Fit) Equivalence Partitioning Memilih produk tas tote (11.4 L) dan memasukkan barang bawaan dengan total volume 5.4 L.
Item: Laptop 14 Inci + Botol 600ml + Pouch (Total: 5.4 Liter)
Visualisasi 3D menampilkan kontainer tas berwarna hijau dengan status 'FIT / Muat Sempurna'. PASS
BB-06 Capacity Checker 3D (Overload) Boundary Value Analysis Memilih tas sling kecil (3.1 L) dan memasukkan laptop 15.6 inci yang panjang fisiknya melebihi tas.
Tas P:24cm, Laptop P:36cm (Selisih +12cm)
Visualisasi 3D menampilkan kontainer merah dengan peringatan 'OVERLOAD: Dimensi melebihi kapasitas fisik tas'. PASS
BB-07 Keranjang Belanja Satuan Equivalence Partitioning Menambahkan varian produk tas reguler dengan stok tersedia ke keranjang belanja.
Product ID: 12, Variant ID: 34, Qty: 2 Pcs, Stok: 10 Pcs
Item tersimpan di cart_items dengan cart_section_id = NULL dan subtotal terhitung otomatis. PASS
BB-08 Paket Reseller: Kuota Kurang (10 Pcs) Boundary Value Analysis Reseller mencoba menambahkan paket usaha ke keranjang dengan hanya memilih 10 pcs tas (BVA batas bawah).
Total varian terpilih = 10 Pcs (Target = 11 Pcs)
Tombol checkout terkunci, sistem menampilkan pesan error 'Kuota paket belum terpenuhi (10/11 Pcs)'. PASS
BB-09 Paket Reseller: Kuota Tepat (11 Pcs) Boundary Value Analysis Reseller memilih tepat 11 item tas varian pada paket usaha reseller (BVA nominal tepat).
Total varian terpilih = 11 Pcs (Target = 11 Pcs)
Validasi sukses, data tersimpan di cart_sections dan 11 baris cart_items dengan harga flat Rp 750.000,-. PASS
BB-10 Paket Reseller: Kuota Lebih (12 Pcs) Boundary Value Analysis Reseller mencoba memilih item ke-12 saat kuota paket sudah terisi 11 pcs (BVA batas atas).
Mencoba klik tambah pada item ke-12
Sistem menolak penambahan dan menampilkan notifikasi 'Batas maksimal paket usaha 11 pcs telah tercapai'. PASS
BB-11 Voucher Min Spend Tidak Terpenuhi Boundary Value Analysis Memasukkan kupon voucher dengan syarat min_spend Rp 200.000 saat subtotal keranjang Rp 199.000.
Voucher min_spend: Rp 200.000, Subtotal: Rp 199.000
Sistem menolak penerapan diskon: 'Total belanja belum memenuhi minimum belanja kupon (Kurang Rp 1.000)'. PASS
BB-12 Voucher Min Spend Terpenuhi Boundary Value Analysis Memasukkan kupon voucher diskon dengan subtotal keranjang tepat Rp 200.000 (BVA batas minimum).
Voucher min_spend: Rp 200.000, Subtotal: Rp 200.000, Diskon: Rp 20.000
Voucher berhasil diaplikasikan, net_total berkurang Rp 20.000, kuota_used bertambah 1. PASS
BB-13 Pembulatan Bobot Ongkir J&T Boundary Value Analysis Kalkulasi tarif pengiriman dengan bobot total pesanan 1.300 gram (toleransi J&T: > 1.200 gram dibulatkan ke 2 Kg).
Bobot: 1.300 gram, Layanan: J&T EZ (Tarif Rp 12.000/Kg)
Sistem membulatkan bobot hitung menjadi 2 Kg, ongkos kirim tercatat Rp 24.000,-. PASS
BB-14 Unggah Bukti Struk Ukuran Besar Boundary Value Analysis Pembeli mengunggah berkas citra bukti transfer struk bank dengan ukuran file 5.2 MB (batas maksimal 5 MB).
File: struk_pembayaran.jpg (5.2 MB)
Sistem menolak unggahan dengan status 413 Payload Too Large: 'Ukuran file bukti bayar maksimal 5 MB'. PASS
BB-15 Penolakan Pembayaran oleh Admin Equivalence Partitioning Admin menolak struk bukti transfer fiktif/tidak terbaca dan mengisi alasan penolakan.
Action: REJECT, Reason: 'Nominal transfer tidak sesuai struk'
Status pembayaran berubah menjadi REJECTED, pembeli menerima notifikasi dan dapat mengunggah struk baru. PASS
BB-16 Approval Bayar & Resi Otomatis Equivalence Partitioning Admin menyetujui bukti bayar yang telah diverifikasi sesuai mutasi rekening koran.
Action: APPROVE, Admin ID: 1, Order ID: 89
Status pembayaran VERIFIED, order PAID, record shipments terbuat dengan nomor resi J&T AWB valid. PASS

BAB VI - ARSITEKTUR & PENUTUP

Bab penutup ini menyajikan arsitektur multi-tier sistem terdistribusi Nalala Store, rekomendasi pemilihan teknologi, kesimpulan hasil perancangan dan pengujian, serta saran untuk pengembangan di masa mendatang.

6.1 Arsitektur Sistem 4-Tier Terdistribusi

Sistem Nalala Store dirancang menggunakan arsitektur 4-Tier (Presentation Tier, Web/API Gateway Tier, Business Logic Tier, dan Persistence & External Services Tier) untuk menjamin skalabilitas tinggi dan pemisahan tanggung jawab komputasi secara modular:

Diagram Arsitektur Multi-Tier Sistem Nalala Store
flowchart TB subgraph TIER1[TIER 1: CLIENT PRESENTATION TIER] direction LR P1[Web Browser Modern
Desktop & Mobile Responsive] P2[Next.js 15 Client Components
Tailwind CSS & Canvas 3D] P3[State Management
Zustand & React Hooks] end subgraph TIER2[TIER 2: WEB & API GATEWAY TIER] direction LR G1[Reverse Proxy & Nginx
SSL Termination] G2[Express.js REST API Server
Node.js Runtime] G3[Security Middleware
JWT Auth, CORS, Helmet, Rate Limit] end subgraph TIER3[TIER 3: BUSINESS LOGIC & SERVICE TIER] direction TB subgraph SERVICES[Core Engine Microservices] S1[Cart & Reseller Package Validator
Aturan Flat Kuota 11 Pcs] S2[3D Capacity Checker Engine
PxLxT & Kubikasi Liter Calculator] S3[J&T Logistics Calculation Engine
Rounding Berat & Tarif EZ/CARGO] S4[Payment Verification & Audit Hub
Multi-Bank & QRIS Mutasi Checker] S5[Notification & Webhook Dispatcher
Socket.IO & WhatsApp Provider] end end subgraph TIER4[TIER 4: PERSISTENCE & EXTERNAL SERVICES] direction LR D1[(MySQL 8.0 Database
Prisma ORM 24 Model)] D2[Object Cloud Storage
Foto Produk & Bukti Bayar] D3[J&T Express API Gateway
Tarif, AWB & Live Tracking] D4[WhatsApp Business API
OTP & Notifikasi Transaksi] end TIER1 -->|HTTPS / JSON REST API| TIER2 TIER2 -->|Controller Invocation| TIER3 TIER3 -->|Prisma Client Queries| D1 TIER3 -->|Upload S3 Compatible| D2 TIER3 -->|Logistics API Integration| D3 TIER3 -->|Messaging Integration| D4
(Dapat disalin & di-render langsung di mermaid.live)

Gambar 6.1 Arsitektur 4-Tier Terdistribusi Nalala Store

Tabel 6.1 Deskripsi Layer Arsitektur Multi-Tier Sistem Nalala Store

Tier / Lapisan Teknologi Implementasi Peran dan Tanggung Jawab Komputasi
Tier 1: Client Presentation Next.js 15, React 19, Tailwind CSS, Three.js / Canvas 3D Menyediakan antarmuka responsif ramah seluler, rendering visualizer kotak 3D kapasitas tas, serta pengalaman belanja interaktif.
Tier 2: Web & API Gateway Node.js Express.js, Nginx, JWT, CORS, Helmet, Multer Mengelola routing HTTP/REST, terminasi SSL, validasi payload, otentikasi peran pengguna (RBAC), dan penanganan upload file struk bukti bayar.
Tier 3: Business Logic Service TypeScript Domain Services, Prisma Transactions Menjalankan logika bisnis inti: kuota 11 pcs reseller, evaluasi dimensi muatan tas, tarif ongkir J&T, validasi voucher, dan approval pembayaran.
Tier 4: Persistence & External MySQL 8.0, Cloud Object Storage, J&T API, WhatsApp API Penyimpanan data relasional terintegrasi 24 model, berkas citra bukti transfer, serta pertukaran data ekspedisi resi dan notifikasi pesan instan.

6.2 Rekomendasi Teknologi Sistem

Tabel di bawah ini menguraikan daftar pustaka dan perangkat lunak terpilih yang direkomendasikan untuk deployment sistem pada lingkungan produksi:

Komponen Sistem Teknologi Terpilih Alasan Pemilihan Teknis & Keunggulan Bisnis
Frontend Framework Next.js 15 (React 19, App Router) Mendukung Server-Side Rendering (SSR) untuk pengindeksan SEO katalog produk tas fashion dan rendering komponen interaktif client yang cepat.
Styling & Desain Tailwind CSS Framework utility-first yang mempercepat pembangunan tampilan antarmuka responsif tanpa beban CSS berlebih pada perangkat seluler pembeli.
Backend API Runtime Node.js Express.js (TypeScript) Arsitektur non-blocking I/O dengan dukungan TypeScript menjamin keamanan pengetikan (type-safety) data transaksi dan kemudahan integrasi API pihak ketiga.
Database & ORM MySQL 8.0 & Prisma ORM Prisma ORM menyediakan migrasi skema deklaratif, generator tipe TypeScript otomatis, dan transaksi atomik ACID untuk mencegah race-condition pada pengurangan stok.
Visualizer 3D HTML5 Canvas & Three.js Menghasilkan simulasi grafis kotak wadah tas tiga dimensi dan model objek barang bawaan harian dengan performa rendering GPU yang ringan di browser.
Integrasi Logistik J&T Express Logistics REST API Menyediakan endpoint kalkulasi tarif real-time (EZ / CARGO), auto-generate nomor resi AWB pengiriman, dan checkpoint pelacakan posisi paket.
Penyimpanan Berkas Cloud Object Storage (S3-Compatible) Menampung berkas citra foto produk resolusi tinggi dan struk bukti transfer pembayaran secara aman dengan URL bertanda tangan (Signed URLs).

6.3 Kesimpulan

  1. Perancangan basis data dengan 24 model persisten berhasil mengakomodasi kebutuhan bisnis komprehensif Nalala Store, mulai dari transaksi ritel, paket usaha reseller 11 pcs bersekat, riwayat voucher promosi, audit pembayaran transfer, hingga logistik kurir J&T Express.
  2. Fitur 3D Bag Capacity Checker berhasil memecahkan kendala ketidakpastian kapasitas pembeli tas wanita secara daring melalui evaluasi matematis kubikasi volume liter dan toleransi dimensi tiga dimensi (panjang, lebar, dan tinggi).
  3. Model keranjang belanja bersekat (cart_sections) berhasil menegakkan aturan kuota flat 11 pcs secara konsisten dan mengisolasi kalkulasi harga grosir dari belanja reguler eceran.
  4. Pengujian White Box Testing pada fungsi verifyPayment() membuktikan bahwa seluruh 5 jalur independen (Basis Paths) dieksekusi dengan hasil 100% PASS (V(G)=5), membuktikan ketahanan logika persetujuan pembayaran dan pencegahan fraud bukti bayar.
  5. Pengujian Black Box Testing pada 16 skenario membuktikan bahwa seluruh fungsionalitas sistem berjalan sesuai spesifikasi kebutuhan pengguna (100% PASS).

6.4 Saran Pengembangan

  1. Otomatisasi Mutasi Bank via Webhook / Aggregator: Di masa mendatang, proses verifikasi pembayaran transfer manual dapat diintegrasikan dengan Payment Gateway otomatis (seperti Midtrans atau Xendit) untuk menghilangkan proses audit manual oleh admin.
  2. Augmented Reality (AR) Try-On: Mengembangkan fitur penampil tas menggunakan WebAR pada kamera ponsel cerdas agar pembeli dapat melihat proporsi tas saat dikenakan di tubuh secara nyata.
  3. Integrasi Multi-Kurir Ekspedisi: Menambahkan pilihan kurir logistik lain seperti SiCepat, JNE, dan Paxel untuk memperluas jangkauan layanan logistik pengiriman ke seluruh pelosok Nusantara.