# Project plan — pernod-ricard-prod

Evidence date: 2026-10-07.

Source repository: `git@bitbucket.org:overdrive/pernod-ricard-prod.git`.

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

## Product

The application is the Pernod Ricard South Africa supplier portal. The supplier login caption is "Welcome to the PRSA Supplier Portal". `.env.example` titles it "Pernod Ricard Supplier Portal". Production host names in the root entry script are `prsa-supplierportal.co.za` and `www.prsa-supplierportal.co.za`.

A visitor who opens the site root is redirected to `/supplier/`. Signed-in suppliers capture invoices, upload supporting documents, and submit an invoice to JD Edwards (JDE). Pernod Ricard accounts-payable users work in `/webadmin/`: they maintain suppliers and users, query invoices, mark invoices paid, and run reports. A daily script assigns due dates, moves invoice status, imports JDE payments, and sends escalation mail.

Provenance: **Implemented** (`index.php`, `supplier/index.php`, `webadmin/invoice.php`, `webadmin/cron.daily.php`). There is no product requirements document in the source repository.

## Branch reality

Default branch is `master`. This documentation set is based on `master` at `19e9775f702abbd3dfd664dba3b670c73e670b8a` (2026-06-11, "Merged in josh_work (pull request #41)"). History was read 40 commits deep from that tip, not the full history.

| Line | What the inspected history shows |
|---|---|
| `master` | Tip `19e9775` (2026-06-11). Recent merges include `josh_work` pull requests #40 and #41, and a series of `Security_changes_2026` pull requests |
| `production` | Named in `bitbucket-pipelines.yml` as the branch that FTP-deploys to production. That branch was not checked out |
| `josh_work` | Merged by pull requests #40 and #41. Not present as a separate checkout in this inspection |

The onboarding scan that created this task recorded tip `31fb478` (2025-02-11, "Updated User sessions to include profile picture paths for both Admin and Supplier") and listed `sonar-project.properties` and `sonarqube_scan.bat` at the repository root. Neither file is in the tree at `19e9775`. The profile-picture session fields are still in `webadmin/login.php`, `webadmin/auth.php`, and `supplier/login2fa.php` (comment dated 2025-02-11). Provenance of the missing Sonar files: **Unknown** — they may have been untracked on the scan host, or removed after that scan.

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

## Scope in the repository

In scope of what is implemented on `master`:

- Two PHP applications that share one MySQL database: `supplier/` (supplier portal) and `webadmin/` (Pernod Ricard administration).
- A custom page framework whose classes are named `Nemo*` (`_framework/`).
- Supplier sign-in with email, password, and an emailed one-time code.
- Webadmin sign-in with Microsoft Azure AD. The email-and-password form on `webadmin/login.php` is still in the file and is commented out of the page.
- Invoice capture, document upload, JDE voucher-match submission, payment import, remittances, reports, FAQ, email templates, users, security groups, and AP teams.
- Bitbucket Pipelines that deploy with `git ftp`: `master` to the QA host path `prsa.overdriveqa.co.za`, branch `production` to `public_html`.

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

- A database schema dump or migration runner. Table shapes are implied by SQL in the PHP files. Whether those tables exist in any environment is **Unknown / Requires Confirmation**.
- Automated tests. No test suite was found. `.gitignore` mentions `TEST*.xml`.
- The live `.env`. Only `.env.example` is committed.
- Menu labels and security-group names, other than the hardcoded supplier group id `10` and the name `'Supplier'`. Menus and permissions are rows in `sysMenuLevel1`, `sysMenuLevel2`, `sysSecurity`, and `sysSecurityGroup`.
- A scheduler definition. `webadmin/cron.daily.php` and `webadmin/cron.inactive-users.php` exist. What invokes them, and how often, is **Unknown / Requires Confirmation**.

## System architecture

```text
Browser
  → HTTPS redirect (.htaccess)
  → index.php redirects to /supplier/
  → supplier/          supplier users (security group 10)
  → webadmin/          Pernod Ricard users (other security groups)
       both
         → PHP Nemo pages and classes
         → MySQL (credentials from .env, settings from sysSettings)
         → file store under ADMIN_Document_Path (sysSettings)
  → Azure AD (webadmin only) via jumbojett/openid-connect-php
  → SMTP (settings SMTP Send As, SMTP BCC)
  → JDE REST orchestrations, behind an OAuth token (sysSettings API_* keys)
       invoice submit: API_JDE_POST_INVOICE_URL
       payment fetch: API_JDE_FETCH_JSON
```

Timezone in both `system.php` files is `Africa/Johannesburg`. Provenance: **Implemented**.

## Major components

| Area | Role | Evidence |
|---|---|---|
| `supplier/` | Supplier login, terms and password gate, own invoices, profile, FAQ, messages, reports | `supplier/login.php`, `supplier/index.php`, `supplier/my.invoice.php` |
| `webadmin/` | Admin login, invoices, suppliers, users, remittances, reports, email, FAQ, settings, security groups, cron | Page scripts at the `webadmin/` root |
| `_framework/` | Shared Nemo list, detail, menu, email, password, and database classes. Each app has its own copy | `supplier/_framework/`, `webadmin/_framework/` |
| `webadmin/includes/` | Domain classes: invoice, payment, JDE import, supplier, user, remittance, reports | `invoice.cls.php`, `import.jde.payments.cls.php` |
| `vendor/` | Composer packages, committed in the tree | `composer.json` |
| Pipelines | FTP deploy of the tree | `bitbucket-pipelines.yml` |

Dated copies such as `webadmin/invoice20210215.php`, `webadmin/invoice20210216.php`, `webadmin/cron.daily20210215.php`, and `supplier/my.invoice20210215.php` remain in the tree. Later comments (2022 through 2026) are on the undated files. Provenance: **Inferred** that the undated files are the ones maintained. Whether a menu row still points at a dated copy is **Unknown**, because menus are stored in the database.

## Milestones visible in the code

These are dates written in file comments and commit subjects, not a project plan.

| When | What the comments or commits say |
|---|---|
| 2016-04 to 2016-10 | Invoice module, password policy, due dates, escalation, inactive-account locking |
| 2018-07 to 2018-10 | Phase 2: JDE payments, paid-invoice email, payments exception report |
| 2020-11 to 2021-03 | Submit invoice to JDE, VAT fields, match statuses, three-day exception report |
| 2022-08 to 2022-11 | OAuth token in front of JDE; PHP 8 comment on `system.php` |
| 2025-02-11 | Profile picture path stored on the session |
| 2025-11 | `.env` loading; supplier email OTP (`supplier/includes/security.cls.php` comment 2025-11-06) |
| 2026-03-23 | Standalone inactive-user script, 6 months (`webadmin/cron.inactive-users.php`) |
| 2026-06-11 | Tip of `master`: download gateway, session path, SSO bypass, invoice download fix |

## Implementation plan

No implementation plan is committed. The repository is the running application plus historical page copies.

## Known dependencies

- PHP. Comments dated 2022-09-15 say "PHP 8 Upgrades". `composer.lock` constraints for the required packages allow PHP 8. The exact runtime version on the server is **Unknown / Requires Confirmation**.
- Composer packages: `phpoffice/phpspreadsheet` ^1.29, `jumbojett/openid-connect-php` ^1.0, `vlucas/phpdotenv` ^5.6. `system.php` does not call phpdotenv; it parses `.env` itself.
- MySQL, reached with `mysqli`.
- Microsoft identity platform (`login.microsoftonline.com`).
- JDE orchestrations and an OAuth token endpoint, both configured in `sysSettings`.
- SMTP, configured in `sysSettings`.
- FTP hosts used by Bitbucket Pipelines (`FTP_HOST_QA`, `FTP_HOST_PROD`, and matching usernames and passwords as pipeline variables).

## Current project status

`master` at `19e9775` is a maintained production-style PHP application. Recent commits through mid-2026 change authentication, file download, and sessions. There is no README that states a roadmap.

`webadmin/cron.daily.php` sets `$isDebug = true` at the top of the file. Several email sends in that script run only when `$isDebug === false`. The JDE payment import and the status updates are not inside that check. Whether production runs this file as committed, or a copy with the flag changed, is **Unknown / Requires Confirmation**.
