QIIUB — Integration Architecture

Visualizacion de arch-integration-architecture. Status: Exploratory — decisiones pendientes marcadas.

Created: 2026-04-14 | Last Updated: 2026-04-14

Integration Architecture — Overview

Cloud-Level — Accounting, ERP, Ecommerce, CRM, Analytics
External SystemQuickBooks, Shopify,
SAP, Xero...
REST + Webhooks
Event BusAzure Service Bus
Topics + Dead Letter
Domain Events
QIIUB Cloud APIIntegration Handlers
POS terminals don't know about these. Data flows through cloud after sync.
POS-Level — Pharmacy (Rx30), Payments, Peripherals
Local DeviceRx30, PAX terminal,
printer, scale...
Socket / File /
USB / Serial
POS TerminalDirect local connection
possync.exe
QIIUB CloudConfig down, results up
Physical hardware at the store. Cloud delivers config and receives results — no real-time interaction.
Key principle: Modules control visibility (what features a merchant sees). Integrations control connectivity (what external systems connect). Different lifecycles.
Industry Comparison
PlatformModel# IntegrationsPattern
ShopifyOpen App Store10,000+Kafka event bus, REST + webhooks
SquareCurated Marketplace300+Direct REST + webhooks
ToastCurated Partners200+Kafka Data Connector (push)
CloverApp Market500+Direct REST + device APKs
QIIUBCurated PartnersPhase 1: 5-10Service Bus Topics + REST + Webhooks

Integration Categories

Cloud-Level Integrations
CategoryExamplesDirectionFrequencyPriority
AccountingQuickBooks Online, QB Desktop (IIF), XeroPush (primary)Hourly/daily batchHigh
PharmacyRx30, Liberty, PioneerRxBidirectionalReal-time (local)POS-level — first integration
EcommerceShopify, WooCommerceBidirectionalNear-real-timeHigh
ERPAcumatica, SAP B1, Dynamics 365 BCBidirectionalBatchMedium
Government/TaxSURI (PR IVU filing)PushMonthly/quarterlyMedium
CRMSalesforce, HubSpotPushDailyLow
DeliveryDoorDash Drive, Uber DirectPush + webhookEvent-drivenLow
AnalyticsPower BI, Data FactoryPushNightlyPlatform-level
POS-Level Integrations (Terminal Hardware)
DeviceExamplesProtocolNotes
Payment TerminalPAX A-series, Ingenico, VerifoneTCP/IP or Serial via SDKPrimary: Dynamics Payments
Receipt PrinterEpson TM-T88 (ESC/POS), Star TSP100USB, TCP/IP, BTCash drawer kick via printer
Label PrinterZebra GK/ZD (ZPL), TSC (TSPL)TCP (9100), USBAlready in Phase 13
ScaleMettler-Toledo, CASSerial RS-232Produce, deli, bulk hardware
Barcode ScannerHoneywell, Zebra, Socket MobileUSB HID (keyboard)Most emulate keyboard — no driver
Customer DisplayPole display (VFD), second screenSerial, HDMI/HTTPSecond screen: HTML rendered by QIIUB
POS device settings flow through the 4-level settings cascade (ADR-0033). Terminal receives resolved config via sync. No integration configuration at the POS — all via portal.
NOT Integrations (Internal Infrastructure)
ServiceWhy Not an Integration
Email (Mandrill)Platform-wide, no per-merchant config
Bot Protection (Turnstile)Platform-wide, invisible to merchants
Error Tracking (Sentry)Developer tooling
IoT HubInfrastructure layer (ADR-0016)
Rule: If a merchant never configures it, never sees its status, and never provides credentials — it's infrastructure, not an integration.

Entity Model

Integration Entities (Central DB)
IntegrationDefinition
Seed data — registry of available integrations
Code, Name, Category, IntegrationType
Scope (Global/Vertical), VerticalAffinity
ConfigurationSchema (JSON Schema)
RequiresOAuth, Status
1:N →
MerchantIntegration
Per-merchant activation + config
MerchantId, LocationId (nullable)
Status (Configuring/Active/Paused/Error)
Configuration (encrypted JSON)
CredentialVaultKey → Azure Key Vault
LastSyncUtc, ConsecutiveErrorCount
IntegrationSyncLog
Audit trail per sync operation
Direction (Push/Pull)
Status (Success/Partial/Failed)
RecordsPushed, RecordsPulled
ErrorCount, DurationMs
IntegrationMapping
External ID mapping per merchant
MapGroup ("PaymentMethod", "TaxCategory")
SourceCode ↔ TargetCode
SourceEntityType ↔ TargetEntityType
PartnerIntegrationTemplate
Partner-managed defaults
PartnerId, IntegrationDefinitionId
DefaultConfiguration (JSON template)
DefaultMappingsJson
IsDefault (auto-apply)
Relationships
IntegrationDefinition —1:N→ MerchantIntegration —1:N→ IntegrationSyncLog
IntegrationDefinition —1:N→ MerchantIntegration —1:N→ IntegrationMapping
IntegrationDefinition —1:N→ PartnerIntegrationTemplate
Partner —1:N→ PartnerIntegrationTemplate
Merchant —1:N→ MerchantIntegration
Location —0..1:N→ MerchantIntegration (nullable LocationId)
Multi-location: LocationId NULL = merchant-wide (e.g., QuickBooks). LocationId set = per-location (e.g., Rx30 — each pharmacy has its own instance). UNIQUE constraint on (MerchantId, IntegrationDefinitionId, LocationId).
Integration Lifecycle
Discovered
Configuring
Active
Paused
Enable → OAuth/credentials + test connection → Active. 3 consecutive errors → auto-pause + alert email. Fix credentials + test → Active again.
Disable preserves the sync watermark (the “last synced up to” timestamp) — when re-enabled, sync resumes from where it left off instead of re-processing everything from the beginning.

Event Bus Architecture

Azure Service Bus Standard — Topics + Fan-out DECISION PENDING
QIIUB API Publishes domain events
after business operations
sale.completed
product.updated
inventory.changed
customer.created
shift.closed
QuickBooks Handler
Rx30 Handler
Shopify Handler
Webhook Dispatcher
Analytics Pipeline
Fan-out: One event (e.g., sale.completed) can trigger QuickBooks posting + analytics + webhook notification simultaneously via topic subscriptions. Dead-letter queue catches failures.
Cost at Scale (~$19/month for 1,000 merchants)
ScaleMessages/dayOperations/monthCost/month
1,000 merchants, 3 subs avg200K24M~$19
1,000 merchants, 1 sub (queues only)200K12M~$10
10x growth2M240M~$110
Service Bus Standard: $10/month base + tiered per million operations. First 12.5M included. BCPOS already uses Service Bus in production (WIDS365 → SAP).
Sync Patterns
PatternWhenExample
Webhook pushReal-time TO externalSale completed → QB journal entry
Webhook receiveReal-time FROM externalShopify order → inventory deduction
Scheduled batchPeriodic bulkNightly sales summary → accounting
PollingExternal has no webhooksCheck Acumatica for product changes
Polling at Scale: 1,000+ Merchants DECISION PENDING
PollOrchestratorBackgroundService
every 60s: find due polls
Service Bus Queue"integration-poll"
batch of 500 max
PollWorkersResolve handler per code
Execute poll, log result
1,000 merchants × 2 integrations × poll every 5 min = ~200K messages/day. Well within Standard tier.

Payment Processing

PCI Compliance — P2PE Card Data Flow
Customer PaymentCard (chip/swipe/tap) or
phone/watch (NFC contactless)
Payment TerminalPAX / Ingenico / Verifone
P2PE encrypted at device
Processor HSMONLY place card data
is decrypted
What QIIUB receives (POS + Cloud) Transaction ref, auth code, last 4 digits, card brand, entry method, amount NEVER: full PAN, CVV, PIN block, track data
P2PE (Point-to-Point Encryption): the card data is encrypted the instant the card touches the terminal and stays encrypted until it reaches the processor. QIIUB never sees the actual card number.

SAQ (Self-Assessment Questionnaire): the annual PCI compliance form every business that accepts cards must complete. With P2PE, QIIUB qualifies for SAQ P2PE (~30 questions) instead of SAQ D (~300+ questions) — dramatically simpler compliance.
Payment Gateway Abstraction
IPaymentGateway
AuthorizeAsync()
CaptureAsync()
VoidAsync()
RefundAsync()
GetStatusAsync()
← implements →
DynamicsPaymentGateway
Primary processor
StripeGateway
Rare, case-by-case
This abstraction is for cloud settlement and reconciliation — not the terminal interaction. Terminal SDKs (PAX, Ingenico) are vendor-specific and should NOT be abstracted.
Offline Policy — No Card Payments Without Internet
QIIUB does NOT support Store-and-Forward (SAF). If the terminal has no internet connection, card payments are not accepted. Cash, check, and charge accounts (AR) remain available offline.
Why not? SAF means accepting a card offline and submitting it later. If the card is stolen, cancelled, or has no funds, the merchant loses that money — 100% liability, no chargeback possible. Most modern platforms (Square, Shopify POS, Clover) have already eliminated SAF for this reason. The few that still support it (Toast, Dynamics) require processor pre-arrangement and merchant acknowledgment of full risk.
PCI Compliance — Who Does What
ResponsibilityWhoDetails
SAQ completion Each merchant individually Every business that accepts cards completes their own annual SAQ. BCPOS does not do it for them.
SAQ version Determined by QIIUB's design Because QIIUB uses P2PE terminals and never stores card data, merchants qualify for SAQ P2PE (~30 questions) instead of SAQ D (~300+ questions).
P2PE certification Payment terminal vendor (PAX, Ingenico) The terminal hardware and its encryption are certified by the vendor, not by QIIUB.
Processor relationship Each merchant with their processor Merchant signs agreement with Dynamics Payments (or other). QIIUB facilitates the connection, not the contract.
QIIUB's role: Design the platform so card data NEVER enters our systems. This keeps our merchants on the simplest compliance path possible. The P2PE architecture is a business advantage — simpler compliance = faster merchant onboarding.

Per-Merchant Configuration

The Configuration Challenge
A pharmacy partner managing 500 pharmacies. Each needs: QuickBooks OAuth tokens + chart of accounts mapping + sync toggles + Rx30 server URL + API credentials + NDC mapping + insurance plans. That's 6+ config dimensions per integration per merchant per location.
Solution: Partner Templates + Encrypted Config
Partner Template "Standard QB for Pharmacies"
Default config + 15 mappings
Merchant Enables QB System copies template
Merchant customizes 3 fields
Active Integration Config in encrypted JSON
Secrets in Key Vault
What is a Partner Template? A pre-built configuration that a partner (e.g., PharmaTech) creates once for all their pharmacies. Instead of configuring QuickBooks from scratch for each of 500 pharmacies, the partner creates a template with standard account mappings (CASH → account 1000, CREDIT → 1100, IVU tax → 2100). When a new pharmacy enables QuickBooks, the template is copied automatically — the pharmacy only needs to enter their own OAuth credentials and adjust any fields that differ.
Why encrypted JSON + Key Vault? Each integration stores two types of data:
Configuration (sync frequency, account mappings, which data types to sync) — stored as encrypted JSON in the database.
Secrets (API keys, OAuth tokens, passwords) — stored in Azure Key Vault (a dedicated vault for secrets, separate from the database). The database only stores a pointer to the vault entry, never the actual secret.
Examples needed: This section is still abstract. Concrete examples of how QuickBooks (API + file export), Dynamics Payments, Evertec, SAP, and Acumatica would each be configured — including what goes in the JSON, what goes in Key Vault, and whether the tables are generic or per-processor — have not been designed yet. This is a future design task.
Health Monitoring — Who Sees What
RoleViewActions
Merchant AdminStatus badge, last sync, 24h success/failure, error messagePause, resume, disconnect, re-auth
Partner AdminAll merchants sorted by health (errors first), aggregate statsBulk enable, template management
SystemAdminCross-partner view, error rate trends, integration-level healthDeprecate, force-pause all, registry CRUD
POS CashierNothing — cloud integrations are invisibleNone
Alert thresholds: 1-2 failures = log + retry. 3 failures = auto-pause + email. 10+ = SystemAdmin review.

Pharmacy Integration — Rx30 (First Concrete Integration)

Rx30 Integration Profile
FieldValue
Codepharmacy.rx30
CategoryPharmacy
TypePOS-Level (local per store) — NOT cloud-level
ScopeVertical (Pharmacy only)
PrerequisiteModule pharmacy.rx must be active
LocationIdPer-location (each pharmacy has its own Rx30 Linux server)
Reference implD:\BCPOSGit\rmh-pharmacy-extension
How It Works Today (RMH)
Rx30 ServerLinux server
per pharmacy
Socket TCP/IP
or File I/O
RMHPharmacy
Communicator
Windows Service
in the store
Shared
SQL Server DB
RMH POSReads Rx data
from shared DB
Mode 1 — Socket (WithInterface=true): Rx30 sends prescriptions via TCP/IP. Communicator writes to bcPhar_Transaction. Bidirectional — POS sends pickup confirmations back.
Mode 2 — File (WithInterface=false): Rx30 writes a text file periodically. Communicator monitors the file, parses, writes to bcPhar_Data. Unidirectional.
The QIIUB Challenge DESIGN NEEDED
No shared DB in QIIUB. In RMH, the Communicator and POS share a SQL Server database on the store server. In QIIUB, each terminal has its own SQLite — there is no shared local database.
Options to evaluate:
OptionHowProsCons
A — Dedicated Rx relay One designated terminal (or a lightweight service) handles Rx30 communication. Writes Rx data to its SQLite, possync.exe pushes to cloud, cloud pushes to other terminals via IoT Hub C2D. Clean separation. Only 1 connection to Rx30 per store. Other terminals get Rx data via normal sync. Latency (sync cycle delay). Single point of failure at the relay.
B — All terminals connect to Rx30 Each terminal runs its own Rx30 communicator. Each reads from Rx30 independently. No single point of failure. Any terminal can scan Rx. N connections to Rx30 per store. Duplicate data. Rx30 may not support multiple concurrent clients well.
C — Local relay service (possync.exe) possync.exe on ONE terminal also handles Rx30 communication. Rx data goes to local SQLite + immediate push to cloud. Cloud fans out to other terminals. Reuses existing sync infrastructure. No extra process. possync.exe gains pharmacy-specific logic. Coupling concern.
D — All terminals query Rx30 directly Each terminal connects to the Rx30 Linux server as a data source for Rx queries (prescriptions, patient lookup). Rx30 server acts as the shared source of truth — no local copy needed for reads. Simplest architecture. No relay, no sync of Rx data between terminals. Real-time queries, always current. Rx30 must support concurrent connections from N terminals. Requires network access to Rx30 from every terminal. Rx30 partner must provide/allow this access.
Key questions: Does Rx30 support concurrent connections from multiple clients? Does it have an API beyond file/socket? Can the pharmacy partner provide direct access from each terminal? These determine which options are viable.
Data Flows (Regardless of Architecture Option)
DirectionDataCurrent MethodFrequency
Rx30 → POSPrescriptions ready for pickupSocket or fileReal-time / periodic
Rx30 → POSPatient infoSocketOn demand
Rx30 → POSDrug NDC catalogTBDTBD
POS → Rx30Pickup confirmationSocket (bidirectional mode)Per transaction
POS → Rx30Rx sale recordedSocketPer transaction
POS → Rx30Void/return of Rx itemSocketPer event
POS Pharmacy Features (from RMH Extension)
FeatureCurrent ImplementationQIIUB Status
Rx barcode scan at registerPOS Extension + DB lookupDesign needed
Patient searchPOS Extension UIDesign needed
Price verificationDB queryDesign needed
Signature capture (HIPAA)Topaz/Clover/Cayan devicesDesign needed
Pickup authorizationPOS Extension + CommunicatorDesign needed
Prescription reportsCrystal Reports in ManagerDesign needed
HIPAA required. All Rx and patient data encrypted in transit and at rest. Signature capture for medication pickup creates PHI records. Design doc needed before implementation.
Open Questions
#QuestionImpact
1Does Rx30 have an API beyond socket/file? REST? Modern integration options?Determines architecture options
2Can Rx30 handle multiple concurrent socket connections?Option B viability
3Is a local relay (Option A/C) acceptable latency for pharmacy workflow?UX at the register
4Signature capture devices — Topaz still the standard or are there newer options?Hardware procurement
5HIPAA BAA — is it needed with Azure if Rx data stays local (POS-level)?Compliance scope