# Features — pernodstaff

Evidence date: 2026-10-07.

Source: `main` at `2ec41f8` (2026-08-27).

Status words:

- **Current** — reachable behaviour in this revision.
- **Completed** — a change that is in history and still present, called out because a commit describes it.
- **Present, not linked** — the page exists and is not in the module navigation.
- **Unused in this tree** — source exists and no caller was found.
- **Planned** — not used. Nothing in the repository is marked as a future feature.
- **Removed** — a commit says the behaviour was taken out, and the current code matches that.

## Current — order portal

| Feature | Where | Notes |
|---|---|---|
| Microsoft sign-in | `login.aspx`, `oauth_callback.aspx`, `App_Code/OAuthService.vb` | Azure AD authorization code with PKCE. No password form on this page. |
| Dev SSO bypass | `login.aspx.vb` `TryDebugSsoBypass` | Only when `AllowSsoBypass` is true. Template value is false. |
| Employee# gate | `main.master.vb`, `oauth_callback.aspx.vb` | Blank `DSVAccount` cannot stay in the order portal. |
| Home / cart | `dashboard.aspx` | Cart lines, quantity update, delete, send order, link to order history, last 10 orders (`ORDER_HEADER_SpSelTop10`). |
| Product catalogue | `products.aspx` | Category, search, options, add to cart. Inactive products dropped in `JSON_DATA_SERVICE`. |
| Basket count | `main.master`, `js/cart-sync.js` | `CART_TOTALS_SpSel` / `SHOPPING_CART_SpSel`. |
| Order history | `history.aspx`, `history_details.aspx` | Header search navigates to `history.aspx?search=`. |
| Returns capture | `history.aspx`, `returns.aspx` | `ORDER_RETURNS_SpIns`. `returns.aspx` is not linked from `main.master`. |
| Profile edit | `profile.aspx` | `USERS_SpSel` / `USERS_SpUpd`. No navigation link found. |
| Terms | `terms.aspx` | Footer link. Template legal text. |
| Order emails | `App_Code/EmailService.vb` | Confirmation and failure, called from `JSON_DATA_SERVICE`. |
| Login history | `App_Code/LoginLogger.vb` | Success and failure for order, admin, and merch. |

## Current — administration

| Feature | Where | Notes |
|---|---|---|
| Admin Microsoft sign-in | `admin/admin_login.aspx` | Allowed only for `accesslevel` 1. |
| User list and edit | `admin/admin_users_mini.aspx` | Linked in the nav. Includes inactive users. Sets order access level and merch access level. |
| Product categories and products | `admin/admin_products.aspx` | Linked in the nav. |
| Registration call | `admin/admin_login.aspx` script `USERS_spREGISTER` | Activation email via `activate.aspx`. SSO is the sign-in path. |
| Account activation | `activate.aspx` | `USERS_spACTIVATE` with query `g`. |
| Forgot / reset password | `forgot.aspx`, `resetpassword.aspx` | Token link. Used by non-AD merch users who have no hash. |

### Present, not linked from `admin.master`

| Page | Stored procedures or role seen in the page |
|---|---|
| `admin/admin_users.aspx` | Same user procedures as the mini page. Older full-page user editor. |
| `admin/admin_prices.aspx` | `ADMIN_PRODUCTS_spSel`, `ADMIN_PRODUCTS_spUpd` |
| `admin/admin_reps.aspx` | `REPS_SpSel`, `REPS_SpIns`, `REPS_SpUpd`, assign users |
| `admin/admin_reports.aspx` | Code-behind is a stub (class only). |
| `admin/admin_unresponded.aspx` | `UNRESPONDED_ORDERS_spsel` |
| `admin/admin_orderstoday.aspx` | `TODAYS_ORDERS_spsel`, order header and detail |
| `admin/admin_data.aspx` | Code-behind is a stub. |
| `admin/GenerateXML.aspx` | Page exists. `JSON_DATA_SERVICE.CREATE_XML_FILE_spSel` builds XML for an order id. |
| `admin/image.aspx` | Serves an image by id. History markup requests `admin/image.aspx?id=` for a rep photo. |
| `admin/default.aspx` | Stub code-behind. |

The admin master shows Users and Products only when `accesslevel` is 1. The master itself only checks that `userid` is in session.

## Current — merchandising

| Feature | Where | Who |
|---|---|---|
| Microsoft or password sign-in | `merch/merch_login.aspx` | Password path rejects AD users. |
| Email OTP | `merch/merch_mfa.aspx`, `App_Code/MFAService.vb` | Non-AD users after a correct password. |
| POS | `merch/pos.aspx` | Levels 3 and 4. Session cart. Card sale. PDF invoice. |
| Invoice list, print, download | `merch/invoices.aspx`, `invoice_print.aspx`, `invoice_download.aspx` | Levels 3 and 4. |
| Stock on hand, daily sales, transactions | `merch/reports_*.aspx` | Levels 3 and 4. Excel export. |
| Products and product edit | `merch/products.aspx`, `product_edit.aspx` | Level 4. Excel on the list page. |
| Opening stock import | `merch/stock_import.aspx` | Level 4. ClosedXML. |
| Receive stock | `merch/stock_receive.aspx` | Level 4. |
| Adjust stock | `merch/stock_adjust.aspx` | Level 4. |
| Categories and brands | `merch/categories.aspx`, `brands.aspx` | Level 4. |
| Settings | `merch/settings.aspx` | Level 4. Keys used by POS include `vatrate`, `invoiceprefix`, and the invoice seed. |

`merch.master` links POS, Invoices, Products (including stock), Reports, and Admin (categories, brands, settings). Level 3 users who open a level-4 URL are redirected to `../dashboard.aspx`.

## Current — sales reps

| Feature | Where |
|---|---|
| Email and password sign-in | `rep/rep_login.aspx` → `REPS_spLOGIN` |
| Remember email for 35 days | Cookie `RepInfo` |
| My Clients | `rep/rep_users.aspx` → `REP_USERS_SpSel` |
| Rep home | `rep/default.aspx` | Stub code-behind. Login redirects to `rep_users.aspx`, not `default.aspx`, after a successful password check. The master redirects an existing `REP_ID` to `default.aspx` on a fresh GET of the login page. |

## Completed changes still in force

| Change | Evidence |
|---|---|
| Mail sent from .NET rather than SQL mail | Commit `6e8477b` (2025-04-02). `EmailService.vb` sends the messages. |
| SSO does not auto-create users | Commit `a5d297c`. `GetOrCreateUser` no longer calls `CreateUserRecord`. |
| Birthday extra bottles removed | Commit `7b7b95d` (2026-04-21). Current cart comment: same cap for every user. |
| Bottle cap is 12 | Commit `abf0802` (2026-06-05). Constant `MaxShoppingCartBottles = 12` and SQL `IF @ICOUNT > 12`. |
| Failed JDE creates do not consume the monthly cap | Commit `a091092` (2026-08-27). Scripts `015`–`017`. |
| Inactive products hidden from the staff catalogue | Commit `312c3ee` (2026-04-21). Filter in `JSON_DATA_SERVICE`. |
| Order-failure email | Commit `4a0c394` (2026-04-21). `SendOrderFailureNotification`. |
| Employee-number duplicate check and deactivation of the other row | Commits `0e63cd8`, `4b23220`, `3a17c7e`. `JSON_DATA_SERVICE` `USERS_SpUpd` block. |
| Cart delete with an empty result is success | Commit `ede1f26` (2026-06-23). |

## Removed

| Behaviour | Evidence |
|---|---|
| Birthday-based bottle allowance | Commit message "Remove birthday bottle limit extension" (`7b7b95d`). Later SQL comments say "no birthday-based limits". |
| SSO auto-provisioning of `USERS` | Commented out in `oauth_callback.aspx.vb`. The method `CreateUserRecord` is still in the file. |

## Unused in this tree

| Item | Evidence |
|---|---|
| `App_Code/SMS.vb` | Posts to Payless4SMS. No reference from another file. Contains embedded gateway credentials. |
| `FILE_UPLOAD_SERVICE.BAUSCH_UPLOAD_FILE` | No caller. |
| `functions.Options_Event_Type`, `Options_Locations`, `Options_Rooms`, `Table_Events_Upcoming` | No caller. Session keys `EVENT_PK` and `COMPANY_PK`. |
| `App_Code/jacques.vb`, `pierre.vb`, `danie.vb` | Empty-style classes (a few lines). No product behaviour found. |
| Merch viewer level 5 | Named only in `002_add_merchaccesslevel.sql`. Not in the admin dropdown. Login accepts 3 and 4 only. |

## Not in the repository

| Item | Why it is listed |
|---|---|
| JDE / `PernodIntegration.CreateOrder` | Named in SQL and `ERROR_LOG` filters. No project file implements it. |
| Automated tests | No test project. Pipeline is SonarQube only. |
| In-repo product manual | `readme.txt` is the theme vendor readme. `Documentation/` is gitignored. |

## Planned

No roadmap, TODO product list, or feature flag for unfinished product work was found, other than a code comment in `merch/pos.aspx.vb` to move PDF generation from iTextSharp 5 to iText 7 when the site becomes a Web Application project. Provenance: **Planned** only as that comment. It is not scheduled.
