# Blueprint pyPOS-First Menuju POS Gateway Plugin Architecture

Tanggal: 2026-04-09  
Status: Blueprint implementasi (belum eksekusi coding gateway)

## 1. Latar Belakang

ERP perlu menangani banyak POS (pyPOS, RaptorPOS, dan lainnya) tanpa membuat endpoint terpisah per vendor di core ERP.  
Pendekatan yang disarankan adalah membangun satu pintu masuk integrasi, lalu setiap POS di-handle sebagai plugin connector.

## 2. Tujuan Utama

1. Menjadikan integrasi POS masuk lewat satu gateway yang seragam.
2. Menempatkan jalur pyPOS di tempat yang benar sebagai connector pertama.
3. Menjaga backward compatibility endpoint lama selama masa transisi.
4. Memudahkan onboarding POS baru tanpa mengubah logic ERP core.

## 3. Prinsip Arsitektur

1. ERP core hanya menerima format canonical, tidak tahu format vendor POS.
2. Endpoint lama tetap aktif sebagai facade, lalu forward ke service gateway.
3. Setiap vendor POS diisolasi dalam connector plugin.
4. Semua operasi kritikal memakai `idempotency_key`, `trace_id`, dan audit log.
5. Proses berat dilakukan async worker/CLI, bukan sinkron penuh di controller.

## 4. Target Arsitektur 1 Pintu

## 4.1 Komponen

1. `PosGatewayApi` sebagai ingress tunggal eksternal.
2. `LegacyFacade` (controller lama) sebagai compatibility adapter ke gateway service.
3. `ConnectorResolver` untuk memilih plugin berdasarkan provider + tenant/device.
4. `ConnectorPlugin` (pyPOS, raptor, dst) untuk validasi dan mapping payload vendor.
5. `CanonicalIngestService` untuk simpan inbox, claim idempotency, enqueue proses.
6. `IngestWorker` untuk proses bisnis lanjutan ke modul ERP transaksi/settlement/sync.
7. `StatusService` untuk cek status by `trace_id`/`idempotency_key`.

## 4.2 Aliran Data Ringkas

1. Request masuk ke gateway (atau endpoint lama facade).
2. Auth + signature/JWT diverifikasi.
3. Connector dipilih (`provider_code`).
4. Payload vendor diubah ke canonical envelope.
5. Inbox + idempotency registry ditulis atomik.
6. Worker memproses ke tabel ERP existing.
7. Client cek status lewat endpoint status gateway.

## 5. Canonical Contract (V1)

Semua connector harus menghasilkan envelope berikut:

```json
{
  "tenant_id": "SBG01",
  "branch_id": 12,
  "device_id": "118933446257318",
  "provider_code": "pypos",
  "event_type": "sales_batch",
  "trace_id": "trc_20260409_abc123",
  "idempotency_key": "sha256(...)",
  "sent_at": "2026-04-09 10:00:00",
  "payload_codec": "xz",
  "payload_version": "v1",
  "payload": {}
}
```

`event_type` awal yang wajib disiapkan:

1. `sales_batch`
2. `compile_status_query`
3. `settlement_push`
4. `sync_pull`
5. `promo_quota_check`
6. `preorder_get`
7. `preorder_use`

## 6. Struktur Folder yang Disarankan (CI3 / PHP 5.6)

```text
application/modules/pos_gateway/
  controllers/
    PosGatewayApi.php
    PosGatewayStatus.php
  libraries/
    ConnectorInterface.php
    ConnectorResolver.php
    connectors/
      PyPosConnector.php
      RaptorPosConnector.php
  models/
    MdlPosGatewayInbox.php
    MdlPosGatewayRegistry.php
    MdlPosGatewayBinding.php
  services/
    CanonicalIngestService.php
    PosEventDispatchService.php
    PosSettlementService.php
    PosSyncService.php
    PosPromoService.php
```

Catatan:

1. Nama class tetap PascalCase.
2. Hindari fitur PHP 7+.
3. Logic bisnis tetap di service/model, controller tetap tipis.

## 7. Peta Migrasi Endpoint Lama -> Gateway Event

| Endpoint Lama | Event Canonical | Connector Awal | Status Migrasi |
|---|---|---|---|
| `/eusvc/NonRest/setUploadStream` | `sales_batch` | `PyPosConnector` | facade dahulu |
| `/eusvc/NonRest/setUploadStream__GLG` | `sales_batch` | `PyPosConnector` | sumber utama pyPOS v2 |
| `/eusvc/NonRest/getUploadCompileStatus` | `compile_status_query` | `PyPosConnector` | expose via status service |
| `/penjualan/ActivityReportApi/settlement` | `settlement_push` | `PyPosConnector` | route ke settlement service |
| `/eusvc/DataSync/serverSync` | `sync_pull` | `PyPosConnector` | route bertahap |
| `/eusvc/ProDiskon/checkFreeProdukQuota` | `promo_quota_check` | `PyPosConnector` | pisah read-only |
| `/eusvc/NonRest/get_preorder` | `preorder_get` | `PyPosConnector` | route bertahap |
| `/eusvc/NonRest/use_preorder` | `preorder_use` | `PyPosConnector` | tambah lock atomik |

## 8. pyPOS-First Refactor Scope (P0-P1)

## 8.1 P0 (wajib dulu)

1. Aktifkan policy auth konsisten untuk endpoint kritikal pyPOS.
2. Jadikan jalur upload idempotent sebagai default pyPOS.
3. Matikan side-effect pada endpoint yang semantik-nya `check`.
4. Batasi endpoint CLI batch agar tidak callable dari web.
5. Tambahkan korelasi log `trace_id + idempotency_key + machine_id`.

## 8.2 P1 (sesudah stabil)

1. Pindahkan parsing payload pyPOS ke `PyPosConnector`.
2. Controller lama menjadi facade ringan ke gateway service.
3. Tambahkan status endpoint canonical.
4. Tambahkan contract tests provider/consumer.

## 9. Desain Plugin Connector

Interface minimum (konseptual):

```php
interface ConnectorInterface {
    public function getProviderCode();
    public function supportsEvent($eventType);
    public function validateInbound($eventType, $rawRequest);
    public function normalizeInbound($eventType, $rawRequest);
    public function mapToCanonical($eventType, $normalized);
    public function buildResponse($eventType, $canonicalResult);
}
```

`PyPosConnector` menjadi implementasi pertama dan referensi untuk connector berikutnya.

## 10. Rencana Rollout Bertahap

## Phase 0 - Foundation

1. Tambah modul `pos_gateway` dan contract canonical v1.
2. Tambah registry idempotency/inbox khusus gateway.
3. Tambah tenant-device-provider binding table.

## Phase 1 - pyPOS Bridge Hardening

1. Endpoint pyPOS lama tetap aktif, tapi internal call ke gateway service.
2. Gunakan `PyPosConnector` untuk mapping event pyPOS.
3. Aktifkan guard auth dan log korelasi.

## Phase 2 - Operational Stabilization

1. Tambah status endpoint canonical.
2. Tambah health checks antrean inbox/worker.
3. Tambah alert untuk pending lama dan failure berulang.

## Phase 3 - Multi Provider Enablement

1. Tambah `RaptorPosConnector`.
2. Aktifkan provider per tenant/branch/device via konfigurasi.
3. Uji coexistence pyPOS + provider eksternal dalam tenant yang sama.

## 11. Checklist Eksekusi Teknis

1. Buat migration SQL untuk tabel gateway.
2. Buat `ConnectorInterface` + `ConnectorResolver`.
3. Buat `PyPosConnector` (event yang sudah berjalan sekarang).
4. Buat service ingest + dispatch.
5. Ubah endpoint lama pyPOS jadi facade (tanpa breaking response awal).
6. Buat contract test minimal untuk upload + settlement + sync.
7. Tambah monitoring dashboard query sederhana.

## 12. Acceptance Criteria

1. pyPOS existing tetap jalan tanpa ubah besar di sisi toko.
2. Semua request pyPOS memiliki trace yang bisa diikuti end-to-end.
3. Tidak ada duplicate insert pada replay request yang sama.
4. Endpoint lama masih kompatibel selama masa transisi.
5. POS baru dapat ditambahkan tanpa ubah logic ERP core.

## 13. Risiko & Mitigasi

1. Risiko breaking response legacy.  
Mitigasi: facade mempertahankan shape response lama.

2. Risiko latensi bertambah karena lapisan baru.  
Mitigasi: ingest cepat + proses berat async worker.

3. Risiko perbedaan business rule antar POS.  
Mitigasi: rule adapter ada di connector, bukan di core ERP.

4. Risiko operasional saat cutover.  
Mitigasi: feature flag per endpoint dan rollback switch cepat.

## 14. Keputusan yang Perlu Ditetapkan Owner

1. Deadline penghentian endpoint legacy (tanggal target).
2. Policy auth final untuk bootstrap scenario.
3. Prioritas provider setelah pyPOS (mis. RaptorPOS dulu atau lain).
4. SLA retry + timeout standar untuk semua connector.

## 15. Referensi Dokumen Terkait

1. `docs/PYPOS_ERP_CHECKLIST_RENCANA_2026-04-09.md`
2. `docs/POS_PAYLOAD_CHECKLIST.md`
3. `docs/POS_PRECHECK_2026-03-02.json`
4. `docs/POS_GATEWAY_PHASE0_EXECUTION_PACK_2026-04-09.md`
5. `docs/sql/POS_GATEWAY_PHASE0_SCHEMA_2026-04-09.sql`
6. `docs/POS_GATEWAY_PHASE1_LEGACY_FACADE_2026-04-09.md`
7. `docs/PYPOS_ENDPOINT_GATEWAY_MAPPING_2026-04-09.md`
