Kelly StudioInternal merchant management.
Kaunter merchants, quotations, invoices and the rest of Kelly Studio, in one place.
| Customer ID | Business Name | Contact | Type | Plan | Subscription Ends | App Version | Account Created | Notes | GrabFood | Bookings | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| Loading... | |||||||||||
| When | Who | Where | Section | What changed |
|---|---|---|---|---|
| Choose a merchant to see their change history. | ||||
| Business Name | Last Backup | Note | |
|---|---|---|---|
| Loading... | |||
| ID | Customer | Contact | Fiuu ID | Units | Hardware | Total Spend | Lifetime Fiuu Commission | |
|---|---|---|---|---|---|---|---|---|
| Loading... | ||||||||
| Category | Serial Number | Received Date | Sold Date | Dispatch Date | Delivery Confirmed | Sold To | Contact | Price Sold | Warranty End | |||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Loading... | ||||||||||||
| Shipment ID | Partner | Item(s) | Customer | Destination | Contact | Tracking ID | Status | POD | Signed By | |
|---|---|---|---|---|---|---|---|---|---|---|
| Loading... | ||||||||||
| DO Number | Dispatch Date | Customer | Item(s) | Serial Number | Address | Assigned To | Status | |
|---|---|---|---|---|---|---|---|---|
| Loading... | ||||||||
| Agreement No. | Date | Merchant | Original S/N | Loaner S/N | Stage | Due | |
|---|---|---|---|---|---|---|---|
| Loading... | |||||||
| Reference | Received | Business | Key contact | Rate card | Documents | Status |
|---|---|---|---|---|---|---|
| Loading... | ||||||
Each onboarding link shows one rate card, picked by its link code (…/onboarding?tier=code).
| Date | Customer Name | Phone | Status | Value (RM) | Comments | Product | Follow Up | Meta Events | |
|---|---|---|---|---|---|---|---|---|---|
| Loading... | |||||||||
| Quote # | Date | Customer | Total (RM) | Status | Valid Until | |
|---|---|---|---|---|---|---|
| Loading... | ||||||
| Invoice # | Date | Customer | Total | Status | Due | |
|---|---|---|---|---|---|---|
| Loading... | ||||||
Clearly define what this AI Agent is responsible for and how it supports your business.
Describe the AI Agent's role, communication style, and the actions it should perform.
Assign actions the AI Agent can take during a conversation. Each action only works once an LLM provider is connected — for now this just saves your configuration.
Documents and links for the AI Agent to reference. Storage only for now — nothing is fed to a model until an LLM is connected.
| Ticket ID | Merchant | Issue | Priority | Status | Created | Last Updated |
|---|---|---|---|---|---|---|
| Loading... | ||||||
| Campaign | Send Date | Recipients | Open Rate | Status |
|---|---|---|---|---|
| Loading... | ||||
| Merchant | Paid At | Amount | Plan | Channel | Transaction ID |
|---|---|---|---|---|---|
| Loading... | |||||
| Merchant | Type | Channels | Txns | Sales (MYR) | Eff. Rate | Commission (MYR) | vs Prev |
|---|---|---|---|---|---|---|---|
| Loading... | |||||||
| Page | Typical depth | Reached bottom | Visits |
|---|
| Campaign | Status | Spend | Impressions | Clicks | CTR |
|---|
| Product | Category | Was | Price | Shown as | |
|---|---|---|---|---|---|
| Loading... | |||||
| Reference | Received | Source | Details | Status | |
|---|---|---|---|---|---|
| Loading... | |||||
| Title | Status | Publish | Category | |
|---|---|---|---|---|
| Loading... | ||||
| Role | Created | ||
|---|---|---|---|
| Loading... | |||
Express.js REST API running inside a Docker container (kellypos-backend-app-1) on an Exabytes VPS. PostgreSQL runs in the kellypos-postgres container on the same VPS and the same Compose network, reachable only from inside it. Postgres user and database are both simplepos, not kellypos.
Environment variables are loaded from backend/.env.local, not .env, and only when the container is created. A docker restart will not pick up a new variable; docker compose up -d is required.
Sync model: Offline-first. The Android app stores everything locally in Room (SQLite), then pushes/pulls deltas using updated_at epoch-ms timestamps as the cursor.
| IP | 45.127.5.203 |
| SSH Port | 8288 |
| Container | kellypos-backend-app-1 |
| Deploy path | /root/kellypos-backend/ — build context is the backend/ subfolder, so only files under /root/kellypos-backend/backend/ survive a rebuild |
| Deploying a file | Two steps, never one: scp to the host path above, then docker cp that same file into /app/.... Verify with docker exec ... grep -c against the CONTAINER path, never the host one. |
| Rebuild | docker compose up -d --build |
| Logs | docker logs kellypos-backend-app-1 --tail 100 -f |
| Restart | docker restart kellypos-backend-app-1 — needed for anything under api/ or lib/. Static files in public/ are read per request and need no restart. |
⚠ Never touch the byondwave user or their containers on this VPS.
⚠ kellypos-api is an OLD, stopped duplicate at /home/kellypos/docker/kellypos-api/, predating the June 2026 migration. Never deploy to it, tail its logs, or restart it: it fights the live container for the pos.kellystudio.work route.
| Endpoint | Method | Description |
|---|---|---|
/api/auth/login | POST | Login with username + password. Returns JWT. |
/api/auth/signup | POST | Create new store + owner account. |
/api/auth/forgotPassword | POST | Send password reset email. |
/api/auth/resetPassword | POST | Reset password using token from email. |
/api/auth/version | GET | Returns latest APK version info. |
/api/sync/push | POST | Android pushes local changes to server (upsert by sync_id). |
/api/sync/pull | GET | Android fetches all records updated after ?since=epoch_ms. |
/api/settings/info | GET/POST | Read/update store info and subscription status. |
/api/upload | POST | Upload item/payment method images. Served at /uploads/filename. |
| Table | Description |
|---|---|
stores | One row per merchant. Holds subscription dates, currency, order types. |
employees | Login accounts. username = email. pin = till PIN. Owner created at signup. |
items | Menu/product items. show_on_sales_tab controls checkout visibility. Soft-deleted. |
sales | Transactions. is_paid=false = Pay Later outstanding. |
sale_items | Line items per sale. Cascade-deletes when parent sale is deleted. |
pos_sessions | Cash drawer open/close sessions with opening/closing balances. |
customers | Customer directory. Soft-deleted. |
payment_methods | Configurable payment methods per store. |
modifier_groups / modifier_options | Item modifiers e.g. Size → Small/Large. |
tax_rules, pricing_rules, promotion_rules | Store-level tax and discount configuration. |
All synced tables use sync_id (device-generated UUID) as primary key — not the local Room autoincrement id — to avoid collisions across devices.
Find a merchant by email:
SELECT id, store_id, name FROM employees WHERE username = 'email@example.com'
Clear a store's sales & sessions:
DELETE FROM sales WHERE store_id = '<store_id>'; DELETE FROM pos_sessions WHERE store_id = '<store_id>'; -- sale_items auto-deletes via ON DELETE CASCADE
Update these env vars in /root/kellypos-backend/backend/.env.local when releasing a new APK. Note .env.local, not .env: the app never reads .env, so appending there does nothing at all.
LATEST_VERSION_CODE=2 LATEST_VERSION_NAME=1.1.0 LATEST_APK_URL=https://... LATEST_RELEASE_NOTES=Bug fixes and improvements
The Android app checks /api/auth/version on launch and prompts the user to update if latestVersionCode is higher than the installed build.
Env vars are read only when the container is CREATED. After editing, run docker compose up -d --build — a docker restart will not pick them up. Verify with docker exec kellypos-backend-app-1 printenv | grep LATEST_.
Publishing only makes a build available. Merchants still install it by hand from Settings → App Update, so a terminal can sit on an old version indefinitely.
| Variable | Description |
|---|---|
DATABASE_URL | PostgreSQL connection string |
JWT_SECRET | Secret for signing/verifying JWTs |
RESEND_API_KEY | Resend.com API key for transactional emails |
LATEST_VERSION_CODE | Integer version code of latest APK |
LATEST_VERSION_NAME | Human-readable version name e.g. 1.0.0 |
LATEST_APK_URL | Public download URL for the latest APK |
LATEST_RELEASE_NOTES | Short release notes shown in-app on update prompt |
| Date | Category | What changed | By | |
|---|---|---|---|---|
| Loading... | ||||
| Store | e-Invoice | TIN | Connection | Valid | Failed | Last sent | |
|---|---|---|---|---|---|---|---|
| Loading... | |||||||
Publish a till update to your test stores first, check it on a real till, then release it to everyone. Tills on 1.7.6 or later show an update bar on their own; older tills only see it under Settings > App Update. From 1.7.8, required updates block new sales once their deadline passes.
Android builds only — kept separate from logos/images below. Direct download links, no login required to open them (uploads are public).
Everything else sitting in the shared uploads volume — logos, product images. Direct download links, no login required to open them (uploads are public).
Kelly Studio
| Item | Quantity |
|---|
Kelly Studio
|
Kelly Studio
Quotation![]() Michael Kelly
Director, Kelly Studio
|
Kelly Studio
| ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Inventory Pre-Dispatch ChecklistDate:
Order / Customer
Shipment
Device / Package
Internal
Checked by
Name: ________________________
Signature: ____________________
Date: ________________________
| ||||||||||||||||||||||||||||||||||||||