# Features — greenfields_web

Evidence date: 2026-10-13. Source: `main` at `c8fce1f`.

Status values:

- **Current** — code for the behaviour is in this tree and does not depend on a missing class.
- **Partial** — UI, route, or controller exists, and a required class, table migration, or branch is missing or empty.
- **Documented only** — named in README or overview, not found in application code.
- **Planned** — a comment says the function is not written yet.
- **Removed / inactive** — present only as comments or `*_old.php` copies.

No feature flag file was found. "In development" cannot be separated from "present on `main`" because the history is four commits on one day.

## Identity and shell

| Feature | Status | Where |
|---|---|---|
| Repository name greenfields_web and Sonar project key | Current | `sonar-project.properties` |
| Transactflow login title, mail from-address, mail footer, `composer.json` description | Current | `app/Views/common/login.php`, `app/Helpers/mail_helper.php`, `composer.json` |
| Admin Overdrive navbar logo and README title "Admin Overdrive Starter" | Current | `app/Views/layouts/header.php`, `README.md` |
| System settings titled "Label System Settings" | Current | `app/Controllers/SystemSettings.php` |
| Deploy script labelled "SAWIS: Label" | Current | `public/deploy.php` |
| `overview.md` narrative that the product is Transactflow and that AWS, PDF, and Excel features are likely | Documented only | `overview.md`. No AWS, mPDF, or PhpSpreadsheet use under `app/` |

## Access

| Feature | Status | Where |
|---|---|---|
| Email and password login, shared error for unknown user and bad password | Current | `app/Controllers/Welcome.php` |
| Email 6-digit code when the last confirmed code is at least one day old | Current | `app/Models/UserModel.php` `check2faEmailConfirmationDate` |
| Password reset token in `password_reset`, no expiry read | Partial | `Welcome::sendResetPasswordLink`. No migration for `password_reset` |
| IP block check on `Welcome` | Partial | `BlockedUsersModel` table `blockedusers`. Migration creates `blocked_users_list` |
| Login history statuses (failure, success, logout, 2FA failure, bad reset token, reset requested) | Current | `Welcome`, `LoginHistory` |
| Roles Developer, Admin, Company Admin, Company User | Current | `app/Database/Seeds/UserRole.php` |
| Company scope for roles 1–3 | Current | `Welcome::setCompanyUsersAndAdminSessionVars` |
| Company scope for Company User (role 4) | Partial | Role is seeded. Session method does not set keys |
| Menu grant filter | Current | `app/Filters/Authorization.php` |
| Self-registration | Removed / inactive | `Welcome::register` is empty. `Welcome::registration` still hashes a user but has no explicit route |
| SAWIS Online password check and role map | Removed / inactive | `Welcome::getHasLoginFromSawisOnline` commented out |
| CSRF and honeypot on requests | Removed / inactive | Commented out in `app/Config/Filters.php` |
| JWT resource for app sessions | Current class, no route found | `app/Controllers/ApiSimulation.php`, `app/Libraries/JwtLibrary.php` |

## Menus seeded for a new database

`app/Database/Seeds/UserMenu.php`:

| Menu | URL | Category |
|---|---|---|
| Dashboard | `home` | General |
| Users | `users` | Settings |
| Menu Management | `menuManagement` | Developers |
| CRUD Generator | `crudGenerator` | Developers |
| Media Files | `media` | General |
| System Settings | `system_settings` | Settings |
| Orders | `orders` | General |
| Company | `company` | General |
| Users | `system_users` | General |

`home`, `users`, `menuManagement`, `crudGenerator`, and `system_settings` / `system_users` have controllers. `media` has views under `app/Views/mediaFile/` and no `Media` controller was found (upload controllers are `Upload` and `UploadedFile`). `orders` and `company` have views and no controllers.

## EDI

| Feature | Status | Where |
|---|---|---|
| HTTP cron runner with weekday 08:00–22:59 window, recurrence in minutes, `override` and `action` query switches | Current | `app/Controllers/CronJobs.php` |
| Production cron key check | Current | `CronJobs::SECURITY_KEY`. Value not copied into Silicon Ark |
| Pull buyer orders through `GetXMLData` | Current | `CronJobs::getAllOrders` |
| Folder XML orders and invoices | Current | `GetXMLData::processFolderXMLOrders`, `processFolderXMLInvoices` |
| Shoprite REST order pull, file copy, and confirmation | Current | `GetXMLData::processAPIJSONOrdersShoprite`, `app/Controllers/Rest.php` |
| Pick n Pay SOAP pull, QA default, production WSDL when the endpoint matches the production URL | Current | `app/Controllers/Soap.php` |
| Godrej and Namaqua invoice XML parsers | Current | `GetXMLData::getInvoiceDetailsGodrej`, `getInvoiceDetailsNamaqua` |
| Shoprite order detail parser and generic order parser | Current | `getOrderDetailsShoprite`, `getOrderDetails` |
| Save order and invoice rows | Partial | Methods exist on `GetXMLData`. Tables have no migrations |
| Export seller orders | Partial | `CronJobs::exportAllOrders` instantiates missing `OrdersModel` |
| Pick n Pay SOAP invoice generation | Current | `Soap::generateSOAPInvoicePnP` |
| M2North SOAP invoice generation | Current | `Soap::generateSOAPInvoiceM2North` |
| Shoprite REST invoice generation | Current | `Rest::generateRESTInvoiceShoprite` |
| Makro invoice XML by email | Current | `Email::generateEmailXmlInvoicesMakro` |
| Example XML for M2North, Godrej, and TAF orders | Current | `writable/invoice_xml_templates/`, `writable/orders_xml_templates/` |
| Email transport for orders and invoices | Planned | Comments in `GetXMLData::main` |
| API transport for invoices | Planned | Empty branch in `GetXMLData::main` |
| Move exported orders | Partial | `CronJobs::moveExportedOrders`. Depends on company rows and order export state |
| Scheduled email queue | Partial | `sent_queue` migration exists. Sending depends on SMTP |
| Company seller/buyer/store/vendor-number model | Current | `app/Models/CompanyModel.php` |
| Company maintenance screen | Partial | Views under `app/Views/edioverdrive/company/`. Route helpers call `Company::…`. No `Company` controller |
| Orders screen | Partial | Views under `app/Views/edioverdrive/orders/`. No `Orders` controller |
| Products screen and CSV product import | Partial | Routes and `Csv` controller. `Products` controller and `ProductsModel` are missing. Views exist |
| Invoices screen | Partial | `InvoicesModel` and views under `app/Views/edioverdrive/invoices/`. No `Invoices` controller. Invoice list route is commented out |
| Store page | Current | `app/Controllers/Store.php` renders `edioverdrive/store/store` |
| `store-api` resource | Partial | Route names `StoreApiController`, which is not in the tree. Filter excepts it from login |
| Organisations resource API | Partial | `OrganisationModel` and migration exist. Resource route has no controller file. Filter excepts it from login |
| Fault finder screen and order/invoice/product processors | Partial | `app/Controllers/FaultFinder.php`. Order and product paths need missing models |
| Fault type settings | Partial | Seeder and `SystemSettings` methods. `fault_type` has no migration |
| Transport method active flag | Partial | Seeder inserts only `Folder`. Settings endpoints exist. `transport_method_options` has no migration |
| Reports charts, BI filters, uninvoiced orders, unmatched invoices | Partial | `app/Controllers/Reports.php` and `app/Views/reports/`. Order and product queries need missing models |
| Daily, client, and billing report emails from cron | Partial | HTML builders in `CronJobs`. Order tables need `OrdersModel` |

## Operations and developer tools

| Feature | Status | Where |
|---|---|---|
| System settings shell (cron, holidays, email logs, templates, login history, blocked list) | Partial | `SystemSettings`. Email template methods need missing `EmailTemplateModel` |
| Server monitoring page and threshold updates | Current | `app/Controllers/ServerMonitoring.php` |
| CLI `php spark monitor:system` loop every 5 seconds, PID file `writable/monitoring.pid` | Current | `app/Commands/MonitorSystemUsage.php`. Uses `posix_kill`, so it assumes a POSIX PHP build |
| Menu management that writes a controller and a view | Current | `app/Controllers/Developers/MenuManagement.php` |
| CRUD generator page | Current | `app/Controllers/Developers/CRUDGenerator.php` |
| DB table data view and Adminer pages | Current | `DbTableDataView`, `app/Views/projects/adminer.php` |
| ChatGPT page | Partial | `app/Controllers/ChatGPT.php`. API key in `.env` is commented |
| Selenium `.side` upload and run | Current | `app/Controllers/Test.php` (`uploadsidefile`, `runsingleproject`, `runmultipleproject`) |
| Site health and masterfile views | Current views | `SiteHealth`, `app/Views/projects/sitehealth.php`, `masterfile.php` |
| Email open pixel | Current | `app/Controllers/EmailPixelTracking.php` |
| File and uploaded-file screens | Current | `File`, `Upload`, `UploadedFile` |
| Slack send helper and `GET slack` | Current | `app/Helpers/slack_helper.php`, `app/Controllers/Slack.php` |
| Salesforce helper | Removed / inactive | `salesforceConnect()` body is commented |
| Africa's Talking SMS helper | Removed / inactive | `smsMessage()` body is commented |
| Label status, label groups, label email templates | Partial | Routes and views under `app/Views/label/`. Controllers `LabelStatus`, `LabelUserGroups`, `LabelEmailTemplates` are not in the tree. Migration `label_email_template` exists |
| Car list views | Current views only | `app/Views/car/`. No `Car` controller found |
| Independent landing page mentioning TransactFlow | Current static files | `app/Views/landingPage (Independent)/` |
| SAWIS layout partials | Current files | `app/Views/layouts/sawis-header.php`, `sawis-menu.php` |
| SonarQube on `main` | Current | `bitbucket-pipelines.yml` |
| PHPUnit app tests | Documented only | `tests/` contains CodeIgniter examples (`HealthTest` checks `APPPATH` and base URL). No EDI tests |
| AWS, PDF, Excel features | Documented only | `overview.md` and `composer.json`. No use under `app/` |

## Old copies

`app/Config/Filters_old.php`, `Routes_old.php`, and `Kint_old.php` are previous config copies. They are not the files CodeIgniter loads by convention (`Filters.php`, `Routes.php`, `Kint.php`).
