# Features — sawis_staging

Evidence date: 2026-10-04. Source: `git@bitbucket.org:silicon_bit_bucket/sawis_staging.git`.

Status words used here:

- **Current** — present on `qa_staging_2020` at `5040b8b` (2026-09-21), the latest staging tip.
- **Production-only** — present on `prod_staging_2020` at `39368c5` (2026-09-14) and not on the QA tip.
- **Master-only** — present on `master` at `9d06011` and absent from the QA tip.
- **Historical file** — a dated copy kept on `master`, removed from the staging tip.
- **Stub** — the file is present and the behaviour does not do the job the filename suggests.
- **Not in git** — named by code and no file exists on these branches.

## Current

### Public page

| Feature | Location | Notes |
|---|---|---|
| Redirect message | `index.php` | "Please visit www.sawis.co.za." Destroys the session. Comment: home moved off this file on 2015-06-11. |

### Sync engine

| Feature | Location | Notes |
|---|---|---|
| Main sync | `cron.sync.php` | Entity definitions, stage SQL, `sql_mode` clear, `blnEnableSync` gate |
| Sync used by the UI | `cron.sync.new.php` | Included by `sync.ui.php` action `Execute`. Same entity type list as `cron.sync.php` |
| Operator console | `sync.ui.php` | Entity groups, stage checkboxes, enable/disable, dates, log tools |
| Shared sync functions | `project.functions.inc.php` | `switchBD`, `UpdateSTG`, `UpdateSTG_Mapped`, `UpdateENV`, `emailSyncLog`, `doQueryUpdateStg` |
| BlendMaster duplicate-key skip | `isMysqlDuplicateKeyError`, `doQueryUpdateStg` | Warning log row. Third `doQuery` argument is honoured on the production branch only |
| Database switch | `switchBD`, `switchBD2` | `mysqli_connect` plus charset `utf8` |
| Mapper import | `cron.mapper.php` | Cultivar from `GRAPE VARIETY TABLE.csv` |
| Daily cron file | `cron.daily.php` | Includes the framework. The `switch` default is empty |

Entity types defined in `cron.sync.php` / `cron.sync.new.php`:

`Cultivar`, `Irrigation`, `MemberType`, `Trellis`, `ProductType`, `WineType`, `Location`, `MemberRelationship`, `Member`, `Member_Address`, `Member_Contact`, `Farm`, `Block`, `User`, `SecurityGroup`, `UserCompanyGroup`, `Password`, `Year`, `BlockMovement`, `EmailTemplate`, `Harvest`, `HarvestItem`, `BG2Master`, `BG2Cellar`, `BG2Farm`, `TitleDeed`, `IPW`, `Login`, `Certification`, `LabAnalysis`, `ExportTransaction`, `PackingMaterial`, `SawisLocation`, `WietaCertification`, `Incoterm`, `CountryCode`, `SingleVineyard`, `BG911Type`, `CertificateTransationCode`, `CertificateRejectionCode`, `CertificatePackingCode`, `Email`, `BlendMaster`, `WSB`, `WSB_Vintage`, `WSB_Cultivar`, `WSB_ProductionArea`.

`Year` is in that list. It is not in the `sync.ui.php` checkbox groups below.

Operator groups in `sync.ui.php`:

| Group | Entities |
|---|---|
| LOOKUPS 1 | Cultivar, Irrigation, MemberType, Trellis, ProductType, WineType, Location, SawisLocation |
| FARMS | Farm, TitleDeed, Block, BlockMovement, SingleVineyard |
| MEMBERS | Member, Member_Address, Member_Contact, MemberRelationship |
| BG2 | Harvest, HarvestItem, BG2Master, BG2Cellar, BG2Farm |
| IPW | IPW |
| LOOKUPS 2 | PackingMaterial, Incoterm, CountryCode, BG911Type, CertificatePackingCode, CertificateRejectionCode, CertificateTransationCode, Certification, WietaCertification, LabAnalysis, ExportTransaction |
| SYSTEM | SecurityGroup, User, Password, UserCompanyGroup, Login, EmailTemplate, Email |
| BLEND MASTER | BlendMaster, WSB, WSB_Vintage, WSB_Cultivar, WSB_ProductionArea |

`CertificateTransationCode` is spelled that way in the source.

### Sync maintenance actions

| Feature | Location | Notes |
|---|---|---|
| Enable / disable sync | `sync.ui.php` | Updates S3 `sysSettings.blnEnableSync` |
| Set last sync date | `sync.ui.php` | Format `Y-m-d H:i:s` or the UI reports an invalid date |
| Reset sync / set synced | `sync.ui.php` | Today's `sysSyncProcess.blnProcessed` to `0` or `1` |
| Email sync logs | `sync.ui.php`, `emailSyncLog` | Query date is hard-coded `2017-01-31` |
| Clear logs, collation, member address, reset data, load mapper | `sync.ui.php` | Each includes `cron.sync.new.php` |

### Blend master notes file

| Feature | Location | Notes |
|---|---|---|
| WSB blend-master column list and update/insert SQL | `cron.blendmaster.php` | Header comment `20230418 - WSB BLENDMASTER`. Not a class. The runnable sync path is the BlendMaster entity inside the cron scripts |

Recent history on this feature (commit subjects on the QA line): litres-out processing (2024-05-15), product-type code (2025-08-18), wine type (2025-08-27 and 2025-12-17), duplicate-key handling on the production tip (2026-09-14).

### SQL console

| Feature | Location | Notes |
|---|---|---|
| Multi-database query form | `query.php`, `includes/query.cls.php` | IP prefix gate. Checkboxes per database and environment. Optional foreign-key-check bypass |

### Messages and layout

| Feature | Location | Notes |
|---|---|---|
| Session expired, logout, no access, internal error | `message.php` | `MID` `s13`, `s44`, `r09`, `r10` |
| Page chrome | `layouts/header.incl.php`, `layout.menu.incl.php`, `layout.basic.incl.php` | Title from the framework. jQuery from Google. Local `js/*.js` script tags are commented out |
| Language switcher script | `layouts/header.incl.php` `setLanguage` | Posts to `ajaxfunctions.php`, which is **not in git** |
| English and Afrikaans cultivar names | `cron.mapper.php` | Columns `EN_strCultivar` and `AF_strCultivar` |

### Connection profiles

| Feature | Location | Notes |
|---|---|---|
| PROD, QA, and DEV MySQL profiles | `system.server.PROD.php`, `system.server.QA.php`, `system.server.DEV.php` | Keyed by host name. Passwords are in the files and are not copied into Silicon Ark |
| Settings table | `system.php` | `sysSettings` on the S3 connection |

### Framework

| Feature | Location | Notes |
|---|---|---|
| Nemo page, menu, list, details, tabs, wizard, report, FAQ, email, database | `_framework/_nemo.*.php` | In-repo framework. Several classes have no caller in the sync scripts |
| Register-globals shim | `_framework/system.functions.inc.php` | Copies POST, GET, or cookies into globals |
| Login session helper | `Login()` | Writes username, password, and email into `$_SESSION` and into cookies `celusername` and `celpassword`. No caller in this repo's sync scripts |
| Password change check | `checkChangePassword` | `password_verify` against the stored hash, and new password must equal confirmation. Comment says it is used from `user.php`, which is **not in git** |
| Security lockout | `CheckSecurityLock` | Reads the last 5 `sysLogin` rows. At 5 failures sets `blnLogin` to `0` and `strLastUser` to `Security Lockout`. The `Save()` call is commented out |
| SMS helper | `SendSMS` | POST to MyMobileAPI. No sync caller |
| Mail | `NemoEmail::Send` | PHP `mail()`. File ends with an `if ($Action == "Test")` block that addresses `exiledbandit@gmail.com` and loads a template named `Course Start` |

### Deploy

| Feature | Location | Notes |
|---|---|---|
| Git hard reset | `deploy.php` | QA tip resets `qa_staging_2020` into `/var/www/html/sawis_staging/`. Page title remains `SAWIS Upload QA` |

## Production-only

| Feature | Location | Notes |
|---|---|---|
| Johannesburg timezone | `system.php` | `Africa/Johannesburg` |
| CLI server defaults | `system.php` | Missing `$_SERVER` keys. Host falls back to `SAWIS_SERVER_NAME` or `10.0.0.62` |
| Query errors caught | `_framework/_nemo.database2.cls.php` `doQuery` | `$blnDieOnError`. BlendMaster skip depends on this |
| IPW profile change | `system.server.PROD.php` | Host `10.0.0.155`, database `ipw_staging_20260823`, user `sawis_readon`. Previous `ipw_live` profile is commented. A comment repeats the password in clear text |
| Deploy target | `deploy.php` | Resets `prod_staging_2020` |

## Master-only

| Feature | Location | Notes |
|---|---|---|
| SonarQube pipeline | `bitbucket-pipelines.yml` | Pipe `sonarsource/sonarqube-scan:3.0.2` on branch `{master}` and on pull requests. Docker memory 3072 MB. Full clone |
| Sonar project key | `sonar-project.properties` | `sonar.projectKey=sawis_staging` |
| Deploy target | `deploy.php` | No `cd`. Resets `dev_staging_2020`. Title `SAWIS Upload QA` |
| PROD profile overwrite of server name | `system.server.PROD.php` | Assigns `$_SERVER[SERVER_NAME] = "10.0.0.62"`. The QA tip comments that assignment out |
| Dated sync copies | `cron.sync.20180926.php`, `cron.sync.maanie.php`, `cron.sync.pj.php` | Removed on the staging tip |
| Dated functions copy | `project.functions.inc.20181101.php` | Removed on the staging tip |

`master` does not contain `sync.ui.php`, `cron.sync.new.php`, `cron.blendmaster.php`, `system.server.QA.php`, or `system.server.DEV.php`. Its `system.php` still includes the QA and DEV files.

## Stub or unused in this tree

| Feature | Location | Notes |
|---|---|---|
| `cron.daily.php` | Root | No work in the default branch of the switch |
| `phpinfo.php` | Root | Calls `phpinfo()` with no gate |
| `zindex.html` | Root | Apache2 Debian default page "It works" |
| `prettify.html` | Root | Small static file. Not referenced by the sync flow |
| GIS environment | `cron.sync.php` | Commented out |
| Nemo FAQ, report, wizard, tabs, details translator | `_framework/` | Classes exist. No sync script instantiates them |
| Test email block | `_nemo.email.cls.php` bottom | Runs when `$Action` is `Test` |

## Not in git

| Name | Where it is referenced |
|---|---|
| `ajaxfunctions.php` | `layouts/header.incl.php` |
| `registration.member.php`, `resetPassword.php` | `layouts/header.incl.php` background condition |
| `user.php` | Comment on `checkChangePassword` |
| `modules/` | `NemoBasic` loads the directory when the page is constructed |
| `js/jquery.js` and the other local scripts | Commented tags in the header |
| `DATA/IN` and the archive directories | `cron.mapper.php` |
| `_sync.cls.php` | Commented includes in the cron files |

## Planned or called out as unfinished

| Item | Evidence | Status |
|---|---|---|
| Stage "Send log email (wip)" | `sync.ui.php` checkbox `STAGE O.1` is `Disabled` | **Current** UI, not selectable |
| Stage -1 reset map date | Checkbox `Disabled` | **Current** UI, not selectable |
| `emailSyncLog` date filter | Comment retains `CURDATE()`; SQL uses `2017-01-31` | **Current** behaviour is the fixed date |
| Certification removed from sync | Commit `2025-06-27` "remove certification from sync entities" | **Not the current tree.** `Certification` is in the QA UI group LOOKUPS 2 |
| PHP 8.2 / 8.4 upgrade | Commit subjects `2025-12-15` and `2026-03-09` | **Inferred** intent. No `composer.json` or image pins the version |

## Deprecated or removed on the staging tip

| Item | Evidence |
|---|---|
| Dated cron copies and `project.functions.inc.20181101.php` | Present on `master`, deleted in the diff to `default_staging_2020` |
| Sonar pipeline | On `master` only. Staging diff deletes it |
| Name `weita` | Comment in `cron.sync.php` `20171010 - renamed all occurrences of "weita" to "wieta"` |
| IPW host `10.0.0.105` / `ipw_live` for the production host key | Commented as old on `prod_staging_2020` only. Still active on the QA tip |

## Recently changed

Taken from non-merge subjects on `qa_staging_2020` since 2024, plus the production tip. Subjects are evidence of intent; the tree at the tips is the evidence of what remains.

| When | Subject | Still visible in the tip |
|---|---|---|
| 2024-05 | Member sync updates; BlendMaster litres out | Member and BlendMaster entities exist. Litres fields are in `cron.blendmaster.php` |
| 2025-03-06 | Set `sql_mode` to empty when the cron runs | `set global sql_mode=''` in `cron.sync.php` |
| 2025-03-12 | Error handling so one failure does not take the system offline | Production `doQuery` catch. QA signature does not have `$blnDieOnError` |
| 2025-06-13 | `strProducerType` and `strCertNameCode` added to sync | Not re-quoted here. Certification entity is present |
| 2025-06-27 | Certification removed from sync entities; `blnSent` to `strSent`; origin code | Certification is back on the QA UI list. Field-level diff not extracted |
| 2025-08-18 | BlendMaster product type code | Entity still synced |
| 2025-12-15 / 2026-03-09 | PHP 8.2 and 8.4 upgrade subjects | QA `system.php` uses quoted keys and `??`. `qsQuery` still calls `get_magic_quotes_gpc` |
| 2026-04-14 | "testing if deploy works" | `deploy.php` still the hard-reset script |
| 2026-08-12 | `strMapperWO` on API and location sync | On the QA history. Not on the 2026-09-14 production tip unless that commit was cherry-picked. The production tip date is earlier, so this commit is not an ancestor of `39368c5` |
| 2026-09-14 | Duplicate-key sync test | Production `doQuery` and IPW profile |
| 2026-09-21 | "Prod changes pushed to other branches" | QA, dev, and default tips |
