# Project plan — pernodstaff

Evidence date: 2026-10-07.

Source repository: `git@bitbucket.org:overdrive/pernodstaff.git`.

This plan describes what the repository contains. It does not decide what the product should become.

## Product

Pernodstaff is the Pernod Ricard staff website at `https://www.pernodstaff.co.za` (application name `Pernod-Online` in `Web.config.template`). It has four signed-in areas in one ASP.NET Web Site:

- An order portal where a staff user with an Employee number browses products, keeps a shopping cart, and submits an order.
- An administrator area for user records and the staff product catalogue.
- A merchandising area with a point of sale, stock, invoices, and reports.
- A sales-rep area that lists that rep's clients.

Provenance: **Implemented** in the page set, master pages, and `Web.config.template`. The public name on the pages is Pernod Ricard. Provenance: **Implemented** (`terms.aspx`, master pages).

`readme.txt` is the Bootstrapious e-commerce theme readme (template versions 1.0 through 2.1.0, 2015–2019). It is not a product specification. Provenance: **Documented** in that file, and it does not describe the staff, admin, merch, or rep behaviour.

There is no product requirements document inside the source repository. `Documentation/` is listed in `.gitignore`, and the security templates point at `Documentation/SECURITY_CONFIG_GUIDE.md`, which is not in the git tree that was read.

## Branch reality

Default branch is `main`. `origin/HEAD` points at `main`. After a full fetch, only `main` is present on the remote.

| Line | Tip | Date | What it is |
|---|---|---|---|
| `main` | `2ec41f8` | 2026-08-27 | "Merged in josh_work (pull request #4)". 57 commits from `b5bbe09` (2025-03-18, "Initial commit") |

This documentation set is based on `main` at `2ec41f8135ed86a034138d7b994c887148e9b45a`.

The onboarding scan that created this task recorded tip `6469038` (2025-10-31, "added logging and updated order confirmation email format"). That commit is not the tip of `main` on 2026-10-07. Later work on `main` includes the 12-bottle calendar-month cap, JDE error exclusion, employee-number checks, and SSO changes through August 2026.

`josh_work` was merged by pull requests #1 (2026-04-22), #2 (2026-06-19), #3 (2026-06-23), and #4 (2026-08-27). That branch is not on the remote after the merge.

Which environment is deployed, and whether production matches `2ec41f8`, is **Unknown / Requires Confirmation**.

## Scope in the repository

In scope of what is implemented on `main`:

- ASP.NET Web Site (VB.NET, target framework 4.7.2) with Web Forms pages, master pages, and ASMX-style JSON web methods in `App_Code/JSON_DATA_SERVICE.vb`.
- Azure AD sign-in for the order portal and the admin portal, and for merchandising users marked as AD users.
- Password sign-in plus email one-time code for merchandising users who are not AD users.
- Password sign-in for sales reps (`REPS_spLOGIN`).
- Staff catalogue, cart, order submit, order history, and a returns page.
- Admin maintenance of users and products. Additional admin pages exist and are not linked from the admin navigation.
- Merchandising POS, stock movements, invoices (PDF), and Excel reports.
- SQL Server, with incremental scripts under `App_Data/DbScripts/`. The scripts name the database `PSOrder`.
- Bitbucket Pipelines running a SonarQube scan on `main` and on pull requests.

Out of scope of the code that was found, or not present as a committed application:

- The JD Edwards (JDE) order-creation component. SQL comments and `ERROR_LOG` filters refer to component `PernodIntegration` and operation `CreateOrder`. No class with that name is in this repository.
- A migration runner. The SQL files are scripts to be applied to SQL Server. Whether they have been applied to any environment is **Unknown / Requires Confirmation**.
- Automated product tests. No test project was found. `.gitignore` mentions `TEST*.xml` and ignores `Documentation/`.
- The live `Web.config` and secret files. Only `*.template` files are committed. `.gitignore` excludes `Web.config`, `Web.Secrets.*.config`, and `.env`.

## System architecture

```text
Browser
  → ASP.NET Web Site (VB.NET, .NET Framework 4.7.2)
      → Order portal (main.master): login, products, cart, history
      → Admin (admin.master): users, products
      → Merch (merch.master): POS, stock, invoices, reports
      → Rep (rep.master): client list
      → JSON_DATA_SERVICE web methods → SQL stored procedures
  → SQL Server database named PSOrder in the scripts
      → SQL Server session state (cookieless, in the config template)
  → Azure AD (OpenID Connect authorization code + PKCE) and Microsoft Graph
  → SMTP (smtp.pernodstaff.co.za) for password reset, activation, MFA, order mail
  → JDE CreateOrder — referenced by ERROR_LOG, not implemented in this repo
```

The staff UI is the Bootstrapious theme (Bootstrap 4, jQuery, Font Awesome 4.7, Owl Carousel, SweetAlert2) plus page scripts that post JSON to `JSON_DATA_SERVICE`. Provenance: **Implemented**.

## Major components

| Component | Location | Role |
|---|---|---|
| Order portal | `login.aspx`, `dashboard.aspx`, `products.aspx`, `history.aspx`, `main.master` | Staff browse, cart, and checkout |
| Admin | `admin/` | User and product maintenance; SSO for access level 1 |
| Merchandising | `merch/` | POS, stock, invoices, reports |
| Rep portal | `rep/` | Rep password login and client list |
| JSON gateway | `App_Code/JSON_DATA_SERVICE.vb` | Session-gated calls to stored procedures, cart cap, order email |
| Identity | `OAuthService.vb`, `PasswordService.vb`, `MFAService.vb`, `LoginLogger.vb` | Azure AD, PBKDF2 passwords, email OTP, login history |
| Mail | `App_Code/EmailService.vb` | SMTP messages |
| SQL scripts | `App_Data/DbScripts/StaffPortal`, `SSO`, `Merch` | Cart rules, SSO columns, merch schema |
| Pipeline | `bitbucket-pipelines.yml` | SonarQube scan |

`App_Code/functions.vb` also contains event, room, and location helpers (`Options_Event_Type`, `Table_Events_Upcoming`). `FILE_UPLOAD_SERVICE.BAUSCH_UPLOAD_FILE` and `App_Code/SMS.vb` have no callers in this repository. Provenance: **Implemented** as source that is not referenced. Those names look carried over from another product. Provenance: **Inferred**.

## Milestones visible in git

| When | Commit | What landed |
|---|---|---|
| 2025-03-18 | `b5bbe09` | Initial commit |
| 2025-04-02 | `6e8477b` | Order and account mail moved from SQL mail into .NET |
| 2025-06-20 | `e797ccc` | Bitbucket Pipelines SonarQube scan |
| 2026-04-21 | `7b7b95d` | Birthday bottle-limit extension removed |
| 2026-04-22 | `a5d297c` | SSO no longer auto-creates a user |
| 2026-04-23 | `4a0c394` / `014d8e7` | Order-failure email; bottle counting tightened |
| 2026-05-21 | `b88f4a1` | SSO bypass tied to a config key |
| 2026-06-05 | `abf0802` | Bottle limit set to 12 |
| 2026-08-26 | `d2a6504` | Bottle-count fix |
| 2026-08-27 | `a091092` | Orders that failed in JDE CreateOrder are left out of the monthly count |
| 2026-08-27 | `2ec41f8` | Merge of `josh_work` (pull request #4) |

There is no project plan, roadmap, or milestone file in the repository. Anything beyond this history is **Unknown / Requires Confirmation**.

## Known dependencies

- .NET Framework 4.7.2, ASP.NET Web Site, IIS (inferred from the Web Site project and `Web.config.template`).
- SQL Server. Scripts use `USE [PSOrder]`. Connection name in the template: `Pernod_ConnectionString`.
- NuGet packages in `packages.config`: Newtonsoft.Json 13.0.3, ClosedXML 0.95.4, iTextSharp 5.5.13.3, BouncyCastle 1.8.9, DocumentFormat.OpenXml 2.12.3, ExcelNumberFormat 1.0.10.
- Azure AD app registration (client id, tenant, redirect URL, secret). Values are placeholders in the templates.
- SMTP account `no-reply@pernodstaff.co.za` on `smtp.pernodstaff.co.za:587`.
- SonarQube via Bitbucket Pipelines (`sonarsource/sonarqube-scan:3.0.2`). Project key in `sonar-project.properties`.

## Current project status

The repository is an active Web Site on `main`, last changed 2026-08-27. The order rules in the latest SQL scripts (flat 12 bottles per calendar month, excluding a status-99 header that has a JDE CreateOrder error, plus a 17:00 cutoff message) are the current checked-in behaviour.

Deployment target, who operates production, and whether the SQL scripts match the live database are **Unknown / Requires Confirmation**.

## Human confirmation

- Is `https://www.pernodstaff.co.za` the live site, and does it run `2ec41f8`?
- Have the scripts in `App_Data/DbScripts/` been applied to `PSOrder`, and in which order when older scripts alter the same procedures?
- Where does `PernodIntegration` / JDE `CreateOrder` run, and which order statuses mean fulfilled, pending, and failed?
- Is the checkout cutoff always 17:00, or only whatever is stored in `ORDER_TIMES.CLOSE_TIME`?
- Should admin pages that are not in the navigation still be reachable by URL?
- Merch access level 5 ("Merch Viewer") is described in a SQL comment and is not offered in the admin user form or accepted at merch login. Is it still a role?
