Synaplan
開源 AI 平台,供企業使用:自行託管的 AI 代理、符合 GDPR 的聊天機器人小工具、RAG 知識庫、WhatsApp 與 Outlook AI、MCP、多模型路由。Docker、Kubernetes 或託管於 Germ
AI 翻譯
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗A pharmacy operations platform for sales, staff, inventory, reporting, closing, attendance and AI-assisted operational insights.
BT Sales IC is a single-pharmacy operations workspace built around the needs of Bahria Town. Its main application is a browser-based Progressive Web App (PWA), supported by Supabase services, a standalone inventory-search PWA and native Android companion applications.
[!IMPORTANT] This repository is designed for one pharmacy and its authorised users. It is not a multi-tenant SaaS product. Some companion applications and integrations have their own data, authentication and operational constraints; read their documentation before deploying or changing them.
| Project information | Details |
|---|---|
| Live application | bt.duapharma.com |
| Repository | sysalmanyasin/BT-Sale-Data2 |
| Default branch | main |
| Web hosting | GitHub Pages with a custom domain |
| Main backend | Supabase |
| Web application | Static HTML, CSS and JavaScript PWA (no production bundle) |
| Release notes | CHANGELOG.md; the live service-worker cache version is in sw.js and build-manifest.json |
| Native applications | Kotlin-based Android projects |
The platform brings several pharmacy workflows into one operational environment.
| Area | Main capabilities |
|---|---|
| Cover | Operational hub with a Summary / Detailed view, section tiles, cross-domain signals and Herald headlines |
| Sales | Daily sales entry, dashboard, historical records, reports, payments, reconciliation, cash-deposit reporting and the Daily Check List |
| Management | Staff Registry, staff notes, targets, ledger, salary, payslips, petty cash, credit, incentives and attendance |
| Inventory | Inventory overview, Stock Ledger, excess stock, reorder analysis and inventory-health indicators |
| STR | Stock transfer requests and awaited, dispatched and received workflows |
| Closing | Closing summaries, shift information and credit-ledger views |
| Audit | Audit assignments and read-only integration with the separate Pharmacy Audit Hub |
| Emergency Billing | Break-glass billing, cart, held bills, receipts, history and validated refund operations |
| Documents and Sheets | Notes, multi-file workbooks and live-data materialisation |
| Utilities | Sync Center, PDF Library, activity log, global search, read-only Gmail briefing, Send via Gmail, settings and Google Drive backup |
| Herald | Rule-based daily operational headlines |
| BT Intelligence | AI-assisted analysis, operational findings, forecasts, investigations and the Dua assistant |
| Inventory Search | Standalone medicine-reference and inventory-search PWA |
| Repository fact | Count |
|---|---|
JS modules under js/ | 198 |
| Supabase Edge Functions | 7 |
| Dated SQL migrations | 29 |
Test files (*.test.js) | 127 |
| Android home-screen widgets | 22 |
| GitHub Actions workflows | 5 |
These counts are generated from the repository. Run npm run readme:sync after structural changes.
This repository contains multiple related but independently maintained applications.
The root directory contains the primary PWA.
Entry point: index.html
Important files: manifest.json, sw.js, build-manifest.json, CHANGELOG.md, js/ and css/.
Located in inventory-search/.
A separate, lightweight PWA for medicine reference and inventory search, with an AI-assisted chat interface. It has its own entry point, service worker (inv-search-shell-* cache) and icon set, and uses the public inventory-chat and medicine-ai-info Edge Functions (no sign-in step).
It is a reference and operational search tool, not a clinical decision-support system.
Each Android application is an independent Gradle project with its own source code and GitHub Actions workflow.
| Application | Directory | Purpose |
|---|---|---|
| Dua Closing (Closing Summary Widgets) | android-widget/ | 22 home-screen widgets covering closing, sales, credit, inventory and STR information; mirrors key web calculations so it works without the PWA open |
| Dua Attendance (BT Attendance) | android-attendance/ | Staff attendance using geofencing, check-in/check-out events, QR fallback, offline queue and manager notifications |
| Dua Mail (MailRoutine) | android-mailroutine/ | Scheduled, template-driven work emails through an authorised Google Workspace/Gmail account, with two home-screen widgets |
The Android projects do not share a single Gradle project or application lifecycle. The former Trusted Web Activity wrapper (android-app/) has been removed.
MailRoutine highlights
MailRoutine scheduling is device-local and subject to Android background-execution restrictions. It is not a cloud scheduler.
See each application's README for setup, permissions, build instructions, security considerations and limitations.
| Layer | Technologies |
|---|---|
| Web frontend | HTML, CSS, vanilla JavaScript and ES modules |
| PWA | Web App Manifest, Service Worker and browser storage |
| Backend | Supabase PostgreSQL, Auth, Storage, REST, RPC and Edge Functions |
| AI | bt-agent Edge Function over a fail-over pool of external providers (Groq, Cerebras, Gemini, OpenRouter), a browser-driven tool loop, pgvector-backed knowledge search and the browser's Web Speech API for voice |
| Charts and documents | Chart.js, jsPDF, jsPDF-AutoTable, html2canvas and XLSX |
| Android | Kotlin, Android SDK, Gradle, Jetpack Compose, Room and WorkManager where applicable |
| Quality | Node.js built-in test runner, jsdom, ESLint (no-undef as an error, zero warnings), c8 coverage floor and an esbuild bundle check |
| CI/CD | GitHub Actions |
The web application is served as static files straight from the repository root. Its release build script updates content-hash asset stamps and service-worker cache metadata. esbuild is used only to verify that every module entry resolves (npm run bundle:check); no bundled or minified production build is shipped yet, so the app still relies on script load order.
The normal business-data flow is:
UI / Page
↓
Action
↓
Repository
↓
State and persistence
↓
EventBus
↓
UI refresh and dependent modules
| Component | Responsibility |
|---|---|
| Pages and UI | Render screens and collect user interactions |
| Actions | Provide the normal business-data mutation boundary |
| Repository | Encapsulate business-data access and persistence |
| State | Hold the application's working data |
| EventBus | Notify other modules about meaningful changes |
| Shared modules | Keep reusable calculations and business rules consistent |
js/platform/ (state, sync, auth, boot), ui/ (shell, navigation, search) and lib/ (date, format, print, rules, Gmail send, PDF library).sales/, manager/, inventory/, str/, closing/, audit/, emergency-billing/, ledger/, sheets/, mail/, cover/, herald/, plus agent/ and ai-center/.shared/: pure, reusable calculations and business rules. A domain may import only shared/, the core layer and its own folder; tests/static/domain-boundaries.test.js enforces this, and scripts/move-module.mjs moves modules and rewrites references.on*= handlers. js/shared/dom-actions.js dispatches data-on-click style attributes, and tests/static/no-inline-handlers.test.js keeps the count at zero.no-undef is an ESLint error. The names the app still reads as implicit globals are listed in config/legacy-globals.mjs, a registry that may only shrink (ratcheted by tests/static/legacy-globals.test.js).index.html carries a script-src policy and has no inline scripts; tests/static/csp-and-cors.test.js keeps allowed script hosts consistent.js/shared/backend-config.js only.Important exceptions: Emergency Billing has a separate cart, local held-bill state and database/RPC transaction path. Some integrations are read-only bridges to external or separately maintained data sources. Do not assume every screen writes through the standard Repository/Actions pipeline.
BT Intelligence (#ai-center) is the operational intelligence interface, not a second business-data system. It owns no business logic, no data layer and no write path.
Assistant safety model
Actions / LedgerActions, audited (agent_audit) and undoable, including after a reload.tool-registry.runTool refuses to run a write or critical tool when locked, unapproved or rejected. BTAgent.decide() refuses approvals that are not a trusted user gesture, so scripts and voice cannot approve.DELETE, and the model must name the exact record it read first.js/agent/core/hard-blocks.js) cover salary finalisation, refunds and bulk deletes. A server-side kill switch disables the assistant on all devices.core/auditor.js adds warnings for repeated or large changes; provider usage is rate-limited server-side.bt-agent requires a signed-in session and an active bt_authorized_users row. Salary, credit, staff and email content is never sent to providers that may train on free-tier prompts, and arguments are redacted before storage.tests/eval/ holds routing, tool-offering and golden-answer cases, and requires every registered tool to appear in at least one case. It runs inside npm test, which also gates the Supabase deploy.AI output is assistance, not an authoritative financial, inventory, medical or operational record. Provider availability and quality vary.
Definitions used across the app: the official daily sale is TOTAL; COMP SALE is a comparison figure and DIFF = TOTAL − COMP SALE. The dashboard, targets, daily push briefing and assistant all use TOTAL.
For internals, see AI Center architecture, KPI verification, final report and Manager Intelligence status.
The following is a high-level map, not an exhaustive file listing.
BT-Sale-Data2/
├── index.html # Main PWA entry point
├── manifest.json # Web app manifest
├── sw.js # Service worker and app-shell cache
├── build-manifest.json # Generated release/build metadata
├── CHANGELOG.md # Release notes (moved out of sw.js)
├── eslint.config.js # Lint rules (no-undef is an error)
├── package.json # Scripts and development dependencies
│
├── js/ # Main application JavaScript (see docs/module-index.md)
│ ├── platform/ ui/ lib/ # Core layer: state, sync, auth, shell, navigation, utilities
│ ├── shared/ # Shared business calculations and rules
│ ├── sales/ # Dashboard, entry, reports, payments, Daily Check List
│ ├── manager/ # Staff Registry, salary, targets, attendance
│ ├── ledger/ # Ledger, Petty Cash, Jazz Cash
│ ├── inventory/ str/ # Inventory analytics and STR workflows
│ ├── closing/ audit/ # Closing and Audit Hub bridges
│ ├── emergency-billing/ # Break-glass billing
│ ├── sheets/ # Notes and workbooks
│ ├── mail/ # Gmail briefing and Cover mail strip
│ ├── cover/ herald/ # Cover hub and daily headlines
│ ├── agent/ # Dua assistant: core/, tools/, ui/
│ └── ai-center/ # BT Intelligence
│
├── css/ # Per-domain stylesheets
├── icons/ # Main PWA icons and DuaPharma wordmarks
├── config/ # legacy-globals.mjs (shrink-only registry)
├── inventory-search/ # Standalone Inventory Search PWA
│
├── android-widget/ # Dua Closing: 22 home-screen widgets
├── android-attendance/ # Dua Attendance
├── android-mailroutine/ # Dua Mail (MailRoutine)
│
├── supabase/
│ ├── config.toml # Per-function JWT settings
│ ├── functions/ # Edge Functions (each with DEPLOY.md)
│ ├── migrations/ # Dated database migrations
│ ├── audit-project/ # SQL for the separate Audit Hub project
│ ├── pdf_library/ # PDF Library backend notes
│ └── activity_log/ # Activity-log schema
│
├── docs/ # Architecture, roadmap, brand and module docs
├── scripts/ # build, brand, bundle-check, readme-facts, repo index
├── tests/ # static/, unit/, dom/, eval/, helpers/
└── .github/workflows/ # test, supabase-deploy and three APK builds
For a curated map of important modules and their responsibilities, see docs/module-index.md.
For the main web application:
For Android builds:
The Android projects currently use the Gradle installation supplied by the developer or CI; do not assume a repository Gradle wrapper is available.
git clone https://github.com/sysalmanyasin/BT-Sale-Data2.git
cd BT-Sale-Data2
npm ci
The application is static and can be served from the repository root:
npx serve .
Alternatively:
python3 -m http.server 8080
Open the local URL shown by the server. Service workers require localhost or HTTPS.
A complete working environment requires the appropriate Google Sign-In and Supabase configuration, including access to the intended backend projects and database policies.
The automated JavaScript tests do not require live Supabase credentials or a real Google sign-in.
Do not copy production secrets into source files, test fixtures, commits or public documentation. Follow the relevant deployment guide for any required environment configuration.
Run these commands from the repository root unless a command explicitly changes directory.
| Command | Purpose |
|---|---|
npm ci | Install locked dependencies |
npm test | Run the JavaScript test suite |
npm run test:verbose | Run tests with detailed output |
npm run test:watch | Re-run tests while developing |
npm run lint | Run ESLint with zero warnings allowed |
npm run build | Update asset stamps and PWA cache metadata |
npm run build:check | Verify generated build metadata without changing files |
npm run bundle:check | Verify module entry points with esbuild |
npm run test:coverage | Run tests and enforce configured coverage thresholds |
npm run eval | Run the assistant evaluation tests |
npm run eval:live | Run advisory live-model evaluation; requires provider configuration |
npm run index:repo | Rebuild the repository intelligence index |
npm run brand / brand:check / brand:png | Regenerate or verify generated brand assets (brand:png needs sharp) |
npm run readme:sync | Regenerate the README repository-facts block |
npm run readme:check | Check that generated README facts are current |
For changes to shipped application files:
npm run build
npm run build:check
npm run lint
npm run bundle:check
npm run test:coverage # or npm test
CI (test.yml, Node 22) runs lint, build:check, bundle:check and test:coverage (floor: 68% lines, 72% branches, 65% functions). Release notes go in CHANGELOG.md, not in sw.js; npm run build only bumps the cache number.
The build script:
index.html.build-manifest.json when shipped assets change.It does not bundle or minify the web application. Review service-worker cache entries when adding or changing files, especially modules loaded through imports.
The repository uses Node's built-in test runner and jsdom for automated JavaScript checks.
The test suite includes:
The main CI workflow runs linting, build validation, module bundling checks and the coverage-enforced test suite. Tests also guard architecture rules: domain boundaries, no inline handlers, legacy-global ratchet, CSP/CORS, file-size budgets, brand-icon consistency and README facts.
| Workflow | Purpose |
|---|---|
| test.yml | Main JavaScript quality and test checks |
| supabase-deploy.yml | Deploy changed Supabase functions and apply new migrations |
| build-widget-apk.yml | Build the Closing Widgets APK |
| build-attendance-apk.yml | Build the Attendance APK |
| build-mailroutine-apk.yml | Test and build MailRoutine; optionally create a signed release |
Android workflows are path-scoped to their respective projects. Their debug APKs and other build outputs are uploaded as GitHub Actions artifacts.
Automated tests do not replace real-device or live-service testing. Google authentication, Supabase integration, printers, geofencing, background execution, and actual Gmail sending require their own verification.
See tests/README.md for testing details.
Each Android application has its own Gradle configuration and build workflow.
Example — build the Attendance debug APK:
cd android-attendance
gradle assembleDebug
Example — run MailRoutine unit tests and build its debug APK:
cd android-mailroutine
gradle testDebugUnitTest
gradle assembleDebug
The widget application can be built in the same way from android-widget/.
For installation, OAuth setup, device permissions, signing and release instructions, use the README inside the relevant Android project. Do not treat a debug APK as a production release.
The repository uses Supabase for database operations, authentication, file storage, RPCs and Edge Functions.
The Edge Functions currently cover these areas:
bt-agent — AI assistant server-side model/provider operations.send-daily-ntfy-briefing — scheduled operational briefing notifications.closing-ntfy-notify — closing notifications.set-staff-login — staff login/PIN management.google-drive — Google Drive backup operations.inventory-chat — inventory-context chat.medicine-ai-info — medicine reference information.verify_jwt is pinned per function in supabase/config.toml. set-staff-login, medicine-ai-info and google-drive allow only https://bt.duapharma.com as origin by default (ALLOWED_ORIGINS overrides); bt-agent uses AGENT_ALLOWED_ORIGINS. Deployment instructions are maintained beside each function in its DEPLOY.md.
Database changes belong in dated SQL files under supabase/migrations/.
The Supabase deployment workflow:
Configure the required GitHub Actions secrets described in supabase-deploy.yml before relying on automated deployment. Provider API keys belong in Supabase secrets, not in the repository.
The SQL under supabase/audit-project/ is intended for the separate Pharmacy Audit Hub project. It is not part of the main project's migration directory and must be applied to the correct project.
The main PWA is hosted through GitHub Pages using the repository's custom domain configuration. Changes to the shipped web app should include the generated asset/cache updates described above.
Check the latest GitHub Actions run and the live application after deployment rather than relying on historical version numbers in documentation.
This application handles sensitive pharmacy, financial, staff and operational information. Security must be considered at the database, server, browser and Android layers.
Current database posture (from the migrations; verify against the live project):
bt_is_authorized_user(), checks that the caller's JWT email is an active row in bt_authorized_users. It exists because signInWithIdToken accepts any Google account, so "authenticated" alone does not mean "one of our people".20261024120000, 20261024130000).20261024150000, 20261024160000): widget summary functions require an allow-listed user or the widget service account; TRUNCATE/REFERENCES/TRIGGER were removed from client roles; legacy open bt_sessions policies were dropped; attendance manager-PIN verification locks after repeated failures; attendance location writes need an allow-listed user; the pdf-library bucket is private and served through short-lived signed URLs.inventory-chat, medicine-ai-info, the ntfy functions) either hold no private data or authenticate with a shared secret header.tests/static/ntfy-functions.test.js scans supabase/functions/ for leaks.Important operational distinction: the companion applications do not all have identical authentication or data-access models. Attendance, widgets, Emergency Billing, MailRoutine and the main PWA must be reviewed independently. Consult their current application documentation and database migrations before changing permissions or deploying a release.
If a credential is exposed, treat it as compromised and rotate or revoke it.
Main PWA
window.* bridges and the registry in config/legacy-globals.mjs remain, and several files exceed 1,000 lines (caps in tests/static/file-size-budget.test.js).Attendance
attendance_locations is readable with the public key because the installed app reads the active location, including its QR secret, with it; closing that needs a new APK. Moving to authenticated users or Edge-Function-controlled writes is on the structure roadmap.Emergency Billing
BT Intelligence
npm run index:repo). agent_schedules exists but nothing executes it yet.MailRoutine
android-mailroutine/docs/MANUAL_TEST.md.DuaPharma is the parent brand; BT Pharmacy Operations is the platform and BT Intelligence the AI layer. Product names, package IDs and application IDs are unchanged. Tagline: Technology for better pharmacy operations.
| Colour | Hex | Use |
|---|---|---|
| Primary Navy | #101B2D | Headers, launcher-icon field, dark surfaces, theme-color |
| Intelligence Teal | #18A999 | Logo line, highlights, glows. Not for white text (2.9:1) |
| Teal, AA-safe | #0E8074 (light) / #14998B (dark) | --accent: buttons, links, focus |
| Insight Amber | #F2B84B | Logo endpoint, nav underline end, aggregate highlights |
| Slate | #465166 | Secondary text |
| White | #FFFFFF | Logo cross, text on navy |
All five apps carry the DuaPharma pharmacy cross in the same position and size. Each app gets its own background colour and one corner glyph, so they stay recognisable as one family but are easy to tell apart on a home screen. App labels share the Dua prefix; package names and application IDs are unchanged.
| App | Label | Background | Glyph |
|---|---|---|---|
Main PWA (icons/) | Dua BT Sales | Primary Navy | Rising line + amber point (the original logo) |
Inventory Search (inventory-search/icons/) | Dua Inv Search | Deep teal #0C6A60 | Magnifier |
android-attendance/ | Dua Attendance | Insight Amber (navy cross) | Location pin |
android-widget/ | Dua Closing | Info blue #2C5282 | 2×2 widget tiles |
android-mailroutine/ | Dua Mail | Violet #4C3A8A | Envelope |
scripts/build-brand.mjs generates everything except the main PWA's hand-exported masters: the Inventory Search SVG and PNG set, the Android adaptive foreground, themed monochrome and legacy layers, the launcher background colours, and the duapharma-wordmark-*.svg files (the wordmark is converted to outlines, so it needs no font). Change a glyph or colour there, then run npm run brand (text outputs) and npm run brand:png (PNGs; needs npm i --no-save sharp). npm run brand:check and tests/static/brand-icons.test.js fail if a generated file is stale or two apps share a launcher layer. Use icons/duapharma-wordmark-dark.svg on navy and -light.svg on white.
The original logo is a geometric pharmacy cross with a rising data curve ending in an amber point. icons/icon.svg is the master; the PNG sizes, maskable icons, monochrome mark and watermarks in icons/ are exported from the same geometry. The Android apps carry the same mark as vector adaptive icons (with a themed monochrome layer) and a monochrome ic_stat_duapharma notification icon.
Semantic colours (success, warning, error, inventory status, MailRoutine "sending") are intentionally not brand colours. Inventory "excess" uses --info, the old blue, so it stays distinct from the teal accent. Changing shipped icons or CSS needs npm run build so the service-worker cache version moves.
Order of truth: running implementation and deployed database policies take precedence over descriptive documentation. Tests and focused application guides should be consulted before relying on a README statement.
Use these documents for deeper, feature-specific information:
| Document | What it covers |
|---|---|
| Module Index | Important JavaScript modules, responsibilities and conventions |
| Per-domain READMEs | js/<domain>/README.md for agent, ai-center, audit, closing, cover, emergency-billing, herald, inventory, ledger, mail, manager, sales, sheets and str |
| AI Center Architecture | BT Intelligence design, data sources, assistant integration and security model |
| AI Center KPI verification | Cross-check of AI Center figures against their source calculations |
| AI Center final report | Delivery status of the AI Center work |
| Manager Intelligence status | What is actually live in the manager-intelligence work |
| Structure Roadmap | Architecture phases, progress and remaining refactoring |
| Release notes | Version history of the web app |
| Testing Guide | Test structure, execution and coverage boundaries |
| Closing Widgets and UX roadmap |
Project principle: maintain reliable pharmacy operations, protect data integrity, keep business calculations consistent, and use automation and AI as controlled assistance—not as substitutes for verified records or human accountability.
| Widget features, setup, build and planned improvements |
| Attendance | Installation, device setup and limitations |
| MailRoutine and manual test | Email routines, Gmail OAuth, scheduling, backup and release process |
| Supabase Functions | Function-specific implementation and deployment guides (DEPLOY.md) |