Melody Project — System Architecture

AutoCount x QianYi WMS Integration Plugin | Quotation PQ-260203 | RM 13,900 | Prepared 2026-04-03

1. System Context Diagram

The big picture: how all systems and actors relate.

graph TB
    subgraph MELODIES["Melodies Distributors (Ulu Tiram)"]
        direction LR
        OFFICE["Office Staff
(AutoCount Desktop)"] WH["Warehouse Staff
(QianYi WMS + Scanners)"] end subgraph PLUGIN["Prisma Integration Plugin"] direction TB PL["Plugin .dll
(C# .NET)"] HTTP["Embedded HTTP Server"] QUEUE["Retry Queue"] end NGROK["ngrok Tunnel
(Fixed Domain)"] QIANYI["QianYi WMS Server
(China, 59.60.9.28)"] RICKY["Ricky
(AutoCount Vendor)"] SUPPLIER["Suppliers
(FMCG Goods)"] RETAIL["Retail Customers"] OFFICE -->|"Creates Picking List
Creates PO"| PL PL -->|"Push jobs / Sync items"| HTTP HTTP -->|"TLS tunnel"| NGROK NGROK -->|"HTTPS"| QIANYI QIANYI -->|"Callback status"| NGROK NGROK --> HTTP HTTP --> PL PL -->|"Creates GRN
Updates status"| OFFICE QIANYI -->|"Picking tasks"| WH WH -->|"Scan & confirm"| QIANYI SUPPLIER -->|"Deliver goods"| WH OFFICE -->|"Ship orders"| RETAIL RICKY -.->|"SDK & API support"| PL style MELODIES fill:#e8f4f8,stroke:#0f3460,stroke-width:2px style PLUGIN fill:#fff3cd,stroke:#ffc107,stroke-width:2px style QIANYI fill:#f8d7da,stroke:#dc3545,stroke-width:2px style NGROK fill:#d4edda,stroke:#28a745,stroke-width:2px

2. Picking Flow (Outbound)

When the office creates a Picking List, the plugin pushes it to QianYi WMS. Warehouse staff picks items, and status flows back to AutoCount in real time.

sequenceDiagram
    actor Office as Office Staff
    participant AC as AutoCount
    participant Plugin as Prisma Plugin
    participant ngrok as ngrok Tunnel
    participant WMS as QianYi WMS
    actor Warehouse as Warehouse Worker

    Office->>AC: Create Picking List (PL-001)
    AC->>Plugin: Event: PL Created
    Plugin->>Plugin: Map PL to WMS format
    Plugin->>ngrok: POST /api/picking/create
    ngrok->>WMS: Forward request

    WMS->>Warehouse: New picking task appears
    Warehouse->>WMS: Scan items, confirm picked

    WMS->>ngrok: POST /callback/picking/status
    ngrok->>Plugin: Forward callback
    Plugin->>AC: Update PL-001 status = "Picked"
    AC->>Office: PL-001 shows "Picked" ✅

    Note over Office, Warehouse: Cancellation Flow
    Office->>AC: Cancel Picking List (PL-001)
    AC->>Plugin: Event: PL Cancelled
    Plugin->>ngrok: DELETE /api/picking/PL-001
    ngrok->>WMS: Forward cancellation
    WMS->>Warehouse: Task cancelled ❌
Key question: Does AutoCount's Picking List module fire an event when a PL is created? If not, the plugin must poll the database or use a database trigger.

3. Receiving Flow (Inbound → Auto GRN)

When QianYi WMS confirms goods received against a Purchase Order, the plugin auto-creates a GRN in AutoCount.

sequenceDiagram
    actor Supplier as Supplier Truck
    actor Warehouse as Warehouse Worker
    participant WMS as QianYi WMS
    participant ngrok as ngrok Tunnel
    participant Plugin as Prisma Plugin
    participant AC as AutoCount

    Supplier->>Warehouse: Deliver goods
    Warehouse->>WMS: Scan items, confirm receipt
    WMS->>WMS: Match to PO reference

    WMS->>ngrok: POST /callback/grn/create
    Note right of WMS: Payload: PO ref, items received, qty

    ngrok->>Plugin: Forward GRN request
    Plugin->>Plugin: Validate against AC Purchase Order
    Plugin->>AC: Create GRN (Goods Received Note)
    AC->>AC: GRN auto-links to PO

    Plugin->>Plugin: Log to Integration Result List
    Plugin->>ngrok: 200 OK + GRN DocNo
    ngrok->>WMS: Forward response
    WMS->>WMS: Mark receipt as synced ✅
Risk: If AC is locked (month-end closing) or PO doesn't exist, GRN creation will fail. Plugin must queue the request and retry, with clear error in the Integration Result List.

4. Item Code Sync (One-Way: AC → WMS)

sequenceDiagram
    actor Staff as Office Staff
    participant AC as AutoCount
    participant Plugin as Prisma Plugin
    participant ngrok as ngrok Tunnel
    participant WMS as QianYi WMS

    Staff->>AC: Create/Edit Item Code
    AC->>Plugin: Event: Item Changed
    Plugin->>Plugin: Map to WMS format

    alt Normal sync
        Plugin->>ngrok: POST /api/item/sync
        ngrok->>WMS: Forward item data
        WMS->>WMS: Create/Update SKU master
        WMS-->>ngrok: 200 OK
        ngrok-->>Plugin: Success
        Plugin->>Plugin: Log: ✅ Synced
    else Network error
        Plugin->>ngrok: POST /api/item/sync
        ngrok-->>Plugin: Timeout / Error
        Plugin->>Plugin: Add to retry queue
        Plugin->>Plugin: Log: 🔄 Queued for retry
        loop Exponential backoff
            Plugin->>ngrok: Retry POST
            ngrok->>WMS: Forward
            WMS-->>ngrok: 200 OK
            ngrok-->>Plugin: Success
        end
        Plugin->>Plugin: Log: ✅ Synced (after retry)
    end
Initial bulk sync: On first deployment, all existing Item Codes (~1000s of SKUs) must be synced to QianYi WMS. This should be a batch job with rate limiting, not individual pushes.

5. Deployment Architecture

graph TB
    subgraph LOCAL["Melodies Office (On-Premises)"]
        AC["AutoCount Accounting
(.NET Desktop App)"] PLUGIN["PrismaWMS.dll
(Plugin in AC Plugins folder)"] HTTPSVR["Embedded HTTP Server
(localhost:5080)"] NGROK_AGENT["ngrok Agent
(Windows Service)"] QUEUE_DB["SQLite Queue
(retry_queue.db)"] LOG["Integration Log
(integration_results.json)"] SQLSERVER["SQL Server / LocalDB
(AutoCount Database)"] AC --- PLUGIN PLUGIN --- HTTPSVR PLUGIN --- QUEUE_DB PLUGIN --- LOG AC --- SQLSERVER HTTPSVR --- NGROK_AGENT end subgraph CLOUD["Internet"] NGROK_EDGE["ngrok Edge
(melody.ngrok-free.app)"] end subgraph CHINA["China Data Center"] WMS_SERVER["QianYi WMS
(59.60.9.28:8077)"] WMS_DB["WMS Database"] WMS_SERVER --- WMS_DB end NGROK_AGENT ==>|"TLS Tunnel"| NGROK_EDGE NGROK_EDGE ==>|"HTTPS"| WMS_SERVER WMS_SERVER ==>|"HTTPS Callback"| NGROK_EDGE NGROK_EDGE ==>|"Relay"| NGROK_AGENT style LOCAL fill:#e8f4f8,stroke:#0f3460,stroke-width:2px style CLOUD fill:#d4edda,stroke:#28a745,stroke-width:2px style CHINA fill:#f8d7da,stroke:#dc3545,stroke-width:2px

6. Error Handling & Resilience

flowchart TD
    START["Operation Triggered
(Pick/GRN/Sync)"] --> SEND["Send to QianYi WMS"] SEND --> CHECK{"Response?"} CHECK -->|"200 OK"| SUCCESS["✅ Log Success"] CHECK -->|"4xx Error"| PARSE["Parse Error Message"] CHECK -->|"5xx / Timeout"| RETRY_Q["Add to Retry Queue"] CHECK -->|"Network Down"| RETRY_Q PARSE --> FIXABLE{"Fixable?"} FIXABLE -->|"Yes (e.g. bad data)"| ALERT_USER["⚠️ Alert User
Show in Result List"] FIXABLE -->|"No (e.g. 403)"| ALERT_ADMIN["🚨 Alert Admin
Config issue"] RETRY_Q --> WAIT["Wait (exponential backoff)
5s → 30s → 2m → 10m → 1h"] WAIT --> RETRY["Retry Send"] RETRY --> CHECK2{"Response?"} CHECK2 -->|"200 OK"| SUCCESS CHECK2 -->|"Still failing"| COUNT{"Attempts < 5?"} COUNT -->|"Yes"| WAIT COUNT -->|"No (5 fails)"| DEAD["💀 Dead Letter
Manual intervention needed"] DEAD --> ALERT_USER style SUCCESS fill:#d4edda,stroke:#28a745 style ALERT_USER fill:#fff3cd,stroke:#ffc107 style ALERT_ADMIN fill:#f8d7da,stroke:#dc3545 style DEAD fill:#f8d7da,stroke:#dc3545

7. Data Mapping

Item Code Mapping

AutoCount FieldDirectionQianYi WMS FieldNotes
ItemCodeSkuCodePrimary key, must be unique
DescriptionSkuNameProduct name
UOMBaseUOMUnit of measure (PCS, CTN, etc.)
BarcodeBarcodeFor scanner matching
ItemGroupCategoryProduct category
IsActiveStatusActive/Inactive flag

Picking List Mapping

AutoCount FieldDirectionQianYi WMS FieldNotes
DocNoOrderNo / ExternalRefUnique picking reference
DocDateOrderDate
DebtorCodeCustomerRefRetail customer code
ItemCode (line)SkuCode (line)
Qty (line)OrderQty (line)
PickedQtyActual quantity picked
StatusTaskStatusPending/Picking/Picked/Cancelled

GRN Mapping (WMS → AutoCount)

QianYi WMS FieldDirectionAutoCount FieldNotes
AsnNo / InboundRefGRN DocNo (auto)Auto-generated by AC
PO ReferencePurchaseOrderNoLinks GRN to PO
SupplierRefCreditorCode
SkuCode (line)ItemCode (line)
ReceivedQty (line)Qty (line)
ReceiveDateDocDate

8. Risk Matrix

#RiskProbabilityImpactMitigation
1QianYi WMS has no documented APIHIGHCRITICALContact vendor NOW. If no API → project redesign
2ngrok tunnel drops during business hoursMEDIUMHIGHPaid plan + daemon + retry queue + monitoring
3AC Picking List has no event hooksMEDIUMHIGHFallback: DB trigger or polling every N seconds
4China firewall blocks ngrokLOWCRITICALTest early. Alt: Cloudflare Tunnel, VPN
5Bulk SKU sync overloads WMS APIMEDIUMMEDIUMBatch sync with rate limiting
6AutoCount version mismatchLOWHIGHConfirm version before dev starts
7GRN creation conflicts with manual processMEDIUMMEDIUMUAT with real users; auto/manual toggle
8Scope creep at UATHIGHMEDIUMClear scope doc; Phase 2 pricing ready