# Project plan — flutter_webportal (Datafy Web)

Evidence date: 2026-10-14. Source of implementation: `git@bitbucket.org:overdrive/flutter_webportal.git`, branch `main`, commit `b98b9e2` (2026-09-24, message `completed update`). Package name in `pubspec.yaml`: `datafy_web`, version `1.0.10+1`.

There was no `silicon_ark/flutter_webportal/` directory before this onboarding. The repository already contains product docs under `docs/` (`SCOPE.md`, `PROJECT_DOCUMENTATION.md`, `FEATURE_REFERENCE.md`, `data-isolation.md`, `greenfield-env.md`, `DB_FUNCTION_MIGRATION_MAP.md`). Those were incorporated and checked against the current tree. Where they disagree with code or with each other, the disagreement is recorded. It is not resolved here.

Git history beyond this commit was not fetched (shallow clone). “Recently changed” items come from `CHANGELOG.md` and migration filenames, not a full log.

## Product purpose

The Datafy web portal is a browser operations console for retail / FMCG customers. Administrators and managers monitor rep activity, store scores, tasks, surveys, Specials (promos), and KaChing campaigns, and they import and export operational reports (Sjreport workbooks, SDC week reports, combined week views). Field visits themselves belong to a separate mobile app. That split is **documented** in `docs/SCOPE.md` and **implemented** by this repo being a Flutter web client with no offline sync product of its own.

Provenance of the purpose statement: **Documented** in `docs/SCOPE.md` and `docs/PROJECT_DOCUMENTATION.md`. A formal external PRD was not found. `testsprite_tests/PRD.md` is a test-automation brief, not the product PRD.

## Objectives

Documented in the repository, not invented:

1. Give portal users a signed-in web UI over Supabase Auth, PostgREST, Storage, and Postgres RPCs (`docs/PROJECT_DOCUMENTATION.md`, `lib/backend/supabase/supabase.dart`).
2. Scope operational data to a selected customer (`FFAppState().selectedCustomer`), with role differences for SuperAdmin, Admin, and Manager (`docs/data-isolation.md`, `lib/pages/includes/navbar/navbar_widget.dart`).
3. Move hosting from legacy FTP to S3 + CloudFront, and move heavy work that cannot stay inside Postgres onto AWS API Gateway (Portal Functions, Datafy import triggers, Bedrock image analysis). **Documented** in `DEPLOY_AWS.md`, `docs/greenfield-env.md`, and `bitbucket-pipelines.yml`. Whether every production database has the matching migrations applied is **Unknown / Requires Confirmation**.

## Scope

### In scope (this repository)

- Flutter web UI (FlutterFlow pages plus custom widgets and actions).
- Direct Supabase access from the browser (anon key compiled into the web bundle).
- Customer, user, store, task, survey, promo, KaChing, product, notification, and report screens listed in the PRD.
- Excel import/export and PDF/CSV exports implemented in `lib/custom_code/actions/`.
- SQL migrations under `supabase/migrations/` (165 `.sql` files on this commit, including underscore-prefixed helper scripts).
- Bitbucket Pipelines build and S3/CloudFront deploy for branches `main` and `AWS-migration`.

### Out of scope (documented)

From `docs/SCOPE.md`:

- Mobile rep offline app (`flutter_app` is named as a related repo; it was not inspected).
- Primary field-rep “fix a task in store” flow (portal edits tasks administratively).
- Callsheet as a delivered business UI.
- Native iOS/Android as the product. Platform folders `android/`, `ios/`, and `windows/` exist because this is a Flutter project. `README.md` says to run it as Flutter **web**.

### Current status

**Implemented and on `main`.** The app is not a greenfield skeleton. `CHANGELOG.md` records a long Unreleased set of KaChing, survey, dashboard, bulk-link, and deploy fixes through mid-September 2026.

The onboarding scan of 2026-09-28 described `main` at `1da36c6` (2025-09-09) and a root `SECURITY_SETUP.md`. That snapshot is stale. Current `main` is `b98b9e2` (2026-09-24). `SECURITY_SETUP.md` is not in the tree.

## System architecture

```text
Browser (Flutter web, go_router)
  ├─ Supabase Auth (implicit flow) + PostgREST + Storage + RPCs
  ├─ Portal Functions HTTP API (JWT) — delete user, SDC upload, phone, geocode,
  │    Waterwheel control, Datafy trigger proxies
  ├─ Datafy API — trigger-read-files, trigger-read-promos-kaching
  ├─ Bedrock API — analyze-image
  └─ Apache Superset (Waterwheel) — external reports iframe / popup
Hosting: Bitbucket OIDC → S3 datafy-prod-webportal → CloudFront
```

Provenance: **Documented** in `docs/PROJECT_DOCUMENTATION.md` and **implemented** in `lib/backend/api_env.dart`, `portal_functions_client.dart`, `datafy_api_client.dart`, `waterwheel_client.dart`, and `bitbucket-pipelines.yml`.

## Major components

| Component | Location | Role |
|---|---|---|
| App shell and routes | `lib/flutter_flow/nav/nav.dart`, `lib/main.dart` | Auth gate, go_router |
| Pages | `lib/pages/`, `lib/view_survey/`, `lib/view_survey_response/`, `lib/create_survey/` | Route screens |
| Custom UI | `lib/custom_code/widgets/` (83 Dart files, including `index.dart` and web/stub pairs) | Manage tabs, dashboard cards, campaign panels |
| Custom actions | `lib/custom_code/actions/` (117 Dart files, including `index.dart` and platform stubs) | RPC wrappers, imports, exports |
| Supabase bindings | `lib/backend/supabase/database/tables/` (82 table/view bindings) | PostgREST rows |
| Portal / Datafy / Bedrock clients | `lib/backend/` | AWS HTTP |
| Migrations | `supabase/migrations/` | Shared schema and RPCs |
| Pipeline | `bitbucket-pipelines.yml` | Flutter 3.41.4 image, web release build, S3 sync |

`docs/PROJECT_DOCUMENTATION.md` still says “106 custom actions” and “75 custom widgets” and “~108” SQL files. The counts above are from this commit’s tree. Treat the older counts as stale documentation.

## Milestones (from evidence, not a formal plan)

No milestone schedule was found. The sequence below is **inferred** from docs, changelog, and migration dates:

| When (evidence) | What |
|---|---|
| FlutterFlow origin | `README.md` still opens with “A new Flutter project” and FlutterFlow stable-channel guidance |
| Through 2025–early 2026 | Dashboard, users, stores, tasks, surveys, promos, KaChing, products, SDC (`CHANGELOG.md` older entries; not re-listed here) |
| 2026-06 | Customer data-isolation audit marked completed in `docs/index.md` (2026-06-08) |
| 2026-07 | RLS tenant-policy migrations (`20260710120000` family) and Option A import path described in project docs |
| 2026-08 | Bulk-link and dashboard store-scope fixes (SCL gate removed from several RPCs) |
| 2026-09 | KaChing customer-scoped linking, actor tracking, survey response viewer, Waterwheel session control (`CHANGELOG.md` Unreleased; `docs/index.md` TASK-0017) |
| 2026-09-24 | `main` at `b98b9e2` |

Whether TASK-0017’s migration is applied on every database is **Unknown / Requires Confirmation**. The changelog says to apply specific SQL files.

## Implementation plan (as found, not proposed)

The repository’s own plan for the AWS move is:

1. Build Flutter web with compile-time defines: `SUPABASE_URL`, `SUPABASE_ANON_KEY`, `BEDROCK_ANALYSIS_API_URL`, `DATAFY_API_URL`, `PORTAL_FUNCTIONS_API_URL`, plus `E2E_SEMANTICS=true` (`bitbucket-pipelines.yml`).
2. Publish `build/web` to S3 bucket variable `AWS_S3_BUCKET` (documented example `datafy-prod-webportal`) and invalidate CloudFront.
3. Keep branch `AWS-migration` as a temporary alias of the same pipeline “until the default branch swap is verified” (`bitbucket-pipelines.yml` comment).
4. Apply `supabase/migrations/` on the target database. The app does not run migrations itself.

There is no checked-in roadmap beyond that.

## Known dependencies

| Dependency | Evidence |
|---|---|
| Flutter stable, SDK `>=3.0.0 <4.0.0`; CI image `ghcr.io/cirruslabs/flutter:3.41.4` | `pubspec.yaml`, `bitbucket-pipelines.yml` |
| `supabase_flutter` 2.9.0 / `supabase` 2.7.0 | `pubspec.yaml` |
| `go_router` 12.1.3, Provider, Hive, shared_preferences | `pubspec.yaml` |
| Excel, PDF, printing, fl_chart, flutter_map | `pubspec.yaml` |
| Self-hosted Supabase documented as `https://supabase.datafy.co.za` | `docs/greenfield-env.md` |
| Related repos named but not inspected: `flutter_app`, `datafy-lambda-new` | `docs/PROJECT_DOCUMENTATION.md` |
| Apache Superset at `https://superset.waterwheel.datafy.co.za/login/` | `CHANGELOG.md` |

## Discrepancies that need a human

1. **Deploy target of `main`.** `README.md`, `DEPLOY_AWS.md`, and `docs/greenfield-env.md` say `main` still uses legacy `SUPABASE_URL` / `SUPABASE_ANON_KEY` and FTP, and that S3/CloudFront is the `AWS-migration` branch. `bitbucket-pipelines.yml` on this commit builds **both** `main` and `AWS-migration` with `SUPABASE_URL_GREENFIELD` and the Bedrock/Datafy/Portal defines, then syncs to S3. The pipeline header says legacy FTP variables belong to branch `datafy-old`. **Requires confirmation:** which document is the live contract.
2. **RLS.** `docs/index.md` says business data is scoped in app code and there is **no RLS**. `docs/data-isolation.md` and `docs/SCOPE.md` say legacy production has RLS off, and greenfield enables it via `20260710120000_enable_rls_tenant_policies.sql`. The same isolation doc later says KaChing linking does not use RLS. Migrations that enable RLS are in the tree. Whether the database behind production `main` has them applied is **Unknown**.
3. **Navbar vs scope doc.** `docs/SCOPE.md` lists SDC Report as SuperAdmin-only. `navbar_widget.dart` shows SDC Report when `userRole` is Admin or Manager, or when `superAdmin` is true. README (Mar 2025 note) agrees with the navbar.
4. **Sjreport / Callsheet navigation.** Routes `/sjreport` and `/callsheet` exist. The navbar does not open them. Both menu items (SuperAdmin only) open `ComingsoonWidget` in a modal. `/sjreport`’s body (`SjreportPageTabs`) is itself a coming-soon panel whose title text is “SDC Report”.
5. **Create account.** `CreateAccountWidget` defines `/createAccount` and calls `createAccountWithEmail`, but `nav.dart` does not register that route.
6. **Login customer.** After a successful sign-in, `login_widget.dart` sets `FFAppState().selectedCustomer = 1` before navigating to the dashboard. Isolation docs say queries must use a valid linked customer and must not run when the id is `<= 0`. Whether `1` is a real tenant, a sentinel, or a defect is **Unknown / Requires Confirmation**.

## Human confirmation list

- Which environment `main` at `b98b9e2` actually deploys to, and whether `datafy-old` is the only remaining FTP path.
- Whether greenfield RLS migrations are applied on the database this portal uses.
- Whether hard-coded `selectedCustomer = 1` on login is intentional.
- Whether Callsheet and the Sjreport page are still planned or abandoned.
- Product owner and formal goals beyond the in-repo scope doc. None were found.
