first init
This commit is contained in:
@@ -0,0 +1,270 @@
|
||||
# POSMANT — Technical Overview
|
||||
**Point of Sale Manajemen Aset Niaga Terpadu**
|
||||
|
||||
Aplikasi POS + manajemen stok native Android, offline-first, untuk UMKM daerah terpencil.
|
||||
|
||||
---
|
||||
|
||||
## Tech Stack
|
||||
|
||||
```
|
||||
Mobile → Flutter (Android-first)
|
||||
Local DB → SQLite via Drift
|
||||
Background → WorkManager (via flutter_workmanager)
|
||||
Backend → Node.js + Fastify
|
||||
Server DB → PostgreSQL + Prisma ORM
|
||||
Bahasa → Dart (mobile) + TypeScript (backend)
|
||||
```
|
||||
|
||||
### Kenapa Flutter, bukan PWA
|
||||
|
||||
| | PWA | Flutter (dipilih) |
|
||||
|---|---|---|
|
||||
| Startup | Load browser dulu | Langsung buka |
|
||||
| Offline storage | IndexedDB — bisa dihapus sistem | SQLite — permanen |
|
||||
| Background sync | Tidak reliable | WorkManager — reliable |
|
||||
| Printer Bluetooth | Terbatas | Native, mudah |
|
||||
| Low-end device | Oke | Lebih baik |
|
||||
|
||||
> Risiko kritis PWA: Android otomatis hapus cache browser saat storage penuh. 7 hari transaksi yang belum sync bisa hilang seketika — tidak bisa ditoleransi untuk warung terpencil.
|
||||
|
||||
---
|
||||
|
||||
## Arsitektur Umum
|
||||
|
||||
```
|
||||
[Device Android] [Server] [Data Layer]
|
||||
┌──────────────────┐ ┌──────────────┐ ┌─────────────────┐
|
||||
│ Flutter App │ sync │ Fastify API │ proses │ Operational DB │
|
||||
│ - UI/UX │ ────────► │ │ ───────► │ (per warung) │
|
||||
│ - SQLite/Drift │ (silent, │ Agregasi │ │ retensi 12 bln │
|
||||
│ - WorkManager │ malam) │ per │ ├─────────────────┤
|
||||
│ │ │ kecamatan │ │ Agregat DB │
|
||||
└──────────────────┘ └──────────────┘ │ (permanen) │
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Platform
|
||||
|
||||
**Flutter — Android-first**
|
||||
|
||||
- Target device: Android kelas menengah ke bawah
|
||||
- Distribusi: APK sideload (via pengabdian masyarakat) atau Play Store
|
||||
- iOS: tidak dalam scope awal, namun codebase Flutter siap bila diperlukan
|
||||
|
||||
---
|
||||
|
||||
## Struktur Proyek
|
||||
|
||||
```
|
||||
posmant/
|
||||
├── mobile/ ← Flutter app (Android)
|
||||
│ ├── lib/
|
||||
│ │ ├── features/
|
||||
│ │ │ ├── pos/
|
||||
│ │ │ ├── stok/
|
||||
│ │ │ ├── laporan/
|
||||
│ │ │ └── sync/
|
||||
│ │ ├── core/ ← database, network, shared logic
|
||||
│ │ └── main.dart
|
||||
│ └── pubspec.yaml
|
||||
├── server/ ← Node.js + Fastify backend
|
||||
│ ├── src/
|
||||
│ │ ├── routes/
|
||||
│ │ ├── jobs/ ← agregasi & cleanup scheduler
|
||||
│ │ └── prisma/
|
||||
│ └── package.json
|
||||
└── README.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Strategi Offline-First
|
||||
|
||||
### Prinsip Dasar
|
||||
App dirancang untuk berjalan **tanpa internet sebagai kondisi default**. Koneksi internet hanya dibutuhkan untuk sync.
|
||||
|
||||
### Teknologi Offline
|
||||
| Komponen | Package | Fungsi |
|
||||
|---|---|---|
|
||||
| **SQLite** | `drift` | Database lokal permanen — menyimpan semua transaksi |
|
||||
| **WorkManager** | `flutter_workmanager` | Jadwalkan sync otomatis tengah malam |
|
||||
| **HTTP Client** | `dio` | Kirim data ke server saat online |
|
||||
| **Connectivity** | `connectivity_plus` | Deteksi status jaringan |
|
||||
|
||||
### Alur Sync
|
||||
```
|
||||
Seharian → Transaksi tersimpan di SQLite lokal
|
||||
Tengah malam → WorkManager cek koneksi → ada sinyal? sync otomatis, diam-diam
|
||||
Pagi → Semua tersinkron, pengguna tidak perlu tahu
|
||||
```
|
||||
|
||||
### Sync Window (Batas Offline)
|
||||
```
|
||||
Hari 1-4 → Normal, tidak ada notifikasi
|
||||
Hari 5 → Banner kuning: "Segera hubungkan ke internet"
|
||||
Hari 7 → Banner merah: "Harap sinkron hari ini"
|
||||
Hari 8+ → Mode read-only: hanya bisa lihat data, tidak bisa input transaksi baru
|
||||
```
|
||||
|
||||
### Conflict Resolution
|
||||
Jika dua device edit data yang sama saat offline:
|
||||
- Strategi: **last-write-wins** dengan audit log
|
||||
- Semua perubahan dicatat dengan timestamp
|
||||
|
||||
---
|
||||
|
||||
## Template Bisnis (Onboarding)
|
||||
|
||||
Saat registrasi, pengguna memilih jenis usaha. App otomatis menyiapkan data awal yang relevan.
|
||||
|
||||
| Template | Pre-fill Kategori | Satuan Default | Mode |
|
||||
|---|---|---|---|
|
||||
| Warung | Sembako, snack, minuman | pcs, sachet, kg, liter | Produk |
|
||||
| Kafe | Menu minuman, makanan ringan | gelas, porsi, cup | Produk |
|
||||
| Katering | Paket nasi box, prasmanan | porsi, paket, orang | Produk* |
|
||||
| Laundry | Cuci reguler, express, setrika | kg, pcs, paket | Produk* |
|
||||
| Umum | Kosong | pcs | Produk |
|
||||
|
||||
> *Katering dan Laundry menggunakan model produk disederhanakan di MVP. Mode order dengan status (masuk → proses → selesai) masuk fase berikutnya.
|
||||
|
||||
Template juga memperkaya data riset — setiap agregat per kecamatan diketahui distribusi jenis usahanya.
|
||||
|
||||
---
|
||||
|
||||
## Data Architecture
|
||||
|
||||
### Lapis 1 — Operational (Private per Warung)
|
||||
```
|
||||
Entitas utama:
|
||||
- Warung (nama, jenis usaha, lokasi kecamatan)
|
||||
- Produk (nama, kategori, harga, satuan, stok)
|
||||
- Transaksi (waktu, produk, jumlah, total)
|
||||
- StokOpname (penyesuaian stok manual + alasan)
|
||||
```
|
||||
- Hanya bisa diakses oleh pemilik warung sendiri
|
||||
- Disimpan di server maksimal **12 bulan**
|
||||
- Setelah 12 bulan: di-aggregate lalu raw data dihapus otomatis
|
||||
|
||||
### Lapis 2 — Research (Agregat per Kecamatan)
|
||||
```
|
||||
Contoh data agregat:
|
||||
- Total transaksi per kategori produk per kecamatan per bulan
|
||||
- Rata-rata harga jual per kategori per wilayah
|
||||
- Distribusi jenis usaha per kecamatan
|
||||
- Pola stok (kelangkaan, kelebihan) per kategori
|
||||
```
|
||||
- Tidak dapat mengidentifikasi warung atau individu manapun
|
||||
- Disimpan **permanen** — aset riset utama
|
||||
- Jadi bahan laporan, dataset, jurnal, dan produk data
|
||||
|
||||
### Alur Agregasi (Server)
|
||||
```
|
||||
Raw data masuk → disimpan di Operational DB
|
||||
Setiap malam → job agregasi → update Agregat DB per kecamatan
|
||||
Setiap bulan → cek data > 12 bulan → hapus raw (pastikan agregat sudah tersimpan)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Fitur Inti (MVP)
|
||||
|
||||
### Modul Onboarding
|
||||
- [ ] Pilih template bisnis (warung, kafe, katering, laundry, umum)
|
||||
- [ ] Data produk awal ter-pre-fill sesuai template
|
||||
- [ ] Tutorial singkat alur penggunaan
|
||||
|
||||
### Modul POS
|
||||
- [ ] Input transaksi penjualan
|
||||
- [ ] Pilih produk dari daftar
|
||||
- [ ] Hitung total otomatis
|
||||
- [ ] Struk digital (simpan di app)
|
||||
- [ ] Dukungan printer thermal Bluetooth
|
||||
|
||||
### Modul Stok
|
||||
- [ ] Daftar produk dengan stok real-time
|
||||
- [ ] Notifikasi stok menipis
|
||||
- [ ] Stok opname manual
|
||||
- [ ] Riwayat perubahan stok
|
||||
|
||||
### Modul Laporan
|
||||
- [ ] Ringkasan penjualan harian / mingguan / bulanan
|
||||
- [ ] Produk terlaris
|
||||
- [ ] Export CSV (backup darurat)
|
||||
|
||||
### Modul Sync
|
||||
- [ ] Background sync otomatis tengah malam (WorkManager)
|
||||
- [ ] Status sync terakhir
|
||||
- [ ] Warning sistem (hari ke-5, ke-7, mode read-only hari ke-8)
|
||||
- [ ] Manual sync (tombol opsional)
|
||||
|
||||
---
|
||||
|
||||
## Privasi & Keamanan
|
||||
|
||||
- Enkripsi data in-transit (HTTPS)
|
||||
- Enkripsi data at-rest di server
|
||||
- Consent eksplisit saat registrasi (penggunaan data untuk riset)
|
||||
- Hak hapus data (right to erasure) — pengguna bisa hapus akun + data
|
||||
- Data retention policy otomatis (12 bulan raw → hapus)
|
||||
- Kepatuhan UU PDP No. 27/2022
|
||||
- Ethical clearance institusi untuk jalur publikasi akademik
|
||||
|
||||
---
|
||||
|
||||
## Yang Masih Perlu Didiskusikan
|
||||
|
||||
- [ ] **User roles** — apakah ada perbedaan akses kasir vs pemilik warung?
|
||||
- [ ] **Multi-device** — satu warung bisa pakai lebih dari satu HP?
|
||||
- [ ] **Satuan lokal** — ikat, kodi, pak — bagaimana sistem satuannya?
|
||||
- [ ] **Infrastruktur** — hosting di mana? (VPS, Railway, dll.)
|
||||
- [ ] **Distribusi app** — APK sideload via pengabdian, atau Play Store?
|
||||
- [ ] **Printer struk** — model printer thermal Bluetooth yang disupport?
|
||||
- [ ] **Fitur fase 2** — mode order untuk laundry/katering, multi-outlet, dll.
|
||||
|
||||
---
|
||||
|
||||
## Deploy — Landing Page (Coolify)
|
||||
|
||||
Landing page statis di-serve via nginx dalam Docker container.
|
||||
|
||||
### File
|
||||
```
|
||||
index.html ← landing page
|
||||
Dockerfile ← build config untuk Coolify
|
||||
```
|
||||
|
||||
### Dockerfile
|
||||
```dockerfile
|
||||
FROM nginx:alpine
|
||||
COPY index.html /usr/share/nginx/html/index.html
|
||||
EXPOSE 80
|
||||
HEALTHCHECK --interval=30s --timeout=5s CMD wget -qO- http://localhost/ || exit 1
|
||||
```
|
||||
|
||||
### Langkah Deploy di Coolify
|
||||
|
||||
1. **Push repo ke GitHub/Gitlab** (pastikan `Dockerfile` dan `Posmant Landing Page.html` ikut ter-commit)
|
||||
2. **Buka Coolify** → New Resource → Application
|
||||
3. Pilih repo dan branch
|
||||
4. **Build Pack:** Dockerfile *(Coolify akan auto-detect)*
|
||||
5. **Port:** `80`
|
||||
6. Klik **Deploy**
|
||||
|
||||
### Environment
|
||||
Tidak ada environment variable yang dibutuhkan — ini halaman statis murni.
|
||||
|
||||
### Update Landing Page
|
||||
Ganti file `index.html` → push → Coolify auto-redeploy (aktifkan auto-deploy di settings).
|
||||
|
||||
---
|
||||
|
||||
## Status
|
||||
|
||||
`v0.2 — Perencanaan (stack dikonfirmasi)`
|
||||
|
||||
---
|
||||
|
||||
*README ini adalah dokumen hidup yang akan diperbarui seiring diskusi pengembangan.*
|
||||
Reference in New Issue
Block a user