# Project plan — Paymyfines-CronJob

Evidence date: 2026-10-07.

Source repository: `git@bitbucket.org:overdrive/paymyfines-cronjob.git`.

Inspected revision: `master` at `cbc8461` (2021-10-18 15:46:58 +0200, Lloyd `sherewalloyd@gmail.com`, "Add project files."). That commit is `origin/HEAD`. The only remote branch is `master`. There are no tags.

The scan-host path named on the onboarding issue (`~/projects/sonar_scan/repos/Paymyfines-CronJob`) was not on this machine. The tree below was read from a clone of the git revision above. That revision is the same commit the issue records (`cbc8461`, 2021-10-18 15:46:58 +0200).

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

There is no README, license, product brief, or prior Silicon Ark set for `Paymyfines-CronJob`.

## Product

**Inferred** from the project name `TMTCronJob`, the mail subject `PMF Error Payments`, the database name `paymyfines_qa` in `TMTCronJob/appsettings.json`, and the settlement calls to `infringement/payinfringement` and `IForce/registerpayment`.

What the code does is an ASP.NET Core 3.1 web application that, when `GET /CronJob` is called:

- reads infringement payments from MySQL;
- posts them to an internal HTTP API for eNaTIS or iForce;
- writes settlement status back to `transaction` and `infringement`;
- attempts an email when a previously failed payment fails again and the try count goes above 3.

No file states a product owner, a schedule, or a written objective. The name "CronJob" is the controller route. This repository does not contain a timer, a Windows task definition, or a hosted background service.

**Unknown / Requires Confirmation:** whether this process is still deployed, who calls `GET /CronJob`, and how often.

## Relationship to other Pay My Fines repositories

This repository does not name any other repository.

Silicon Ark already documents Pay My Fines trees. The closest overlap is `pmf-backend-ah` (evidence date 2026-10-06, `master` at `064c4fa`, 2022-05-06). That PRD's WF-6 describes a settlement routine with the same status strings (`Source Failed Payment`, `Source Approved Payment`), the same two upstream paths, the same mail subject `PMF Error Payments`, and the same in-code comment `what goes here??` on `terminalId`. That later tree is an AWS Lambda (`RunCronJob` / `GET /runcronjob`), not this web project. Several behaviours differ. They are listed in `prd.md` under [Conflict with the pmf-backend-ah record](prd.md#conflict-with-the-pmf-backend-ah-record). Whether `Paymyfines-CronJob` is an earlier copy of that job is **Inferred** from the overlap and **Requires Confirmation**.

These Silicon Ark sets do not describe this code, and this code does not mention them:

| Directory | What Silicon Ark records |
|---|---|
| `pmf-backend-ah` | Lambda API that includes a similar settlement job |
| `pmf-frontend-ah` | Pay My Fines frontend |
| `paymyfines-frontend` | Separate frontend repository |
| `paymyfines-frontend-new` | Separate frontend repository |
| `paymyfines-worker` | Remote with no application source |
| `paymyfines-pdf-application` | Remote with no application source |

`paymyfines-worker` is not this job. Its tree has no solution and no source.

## What this repository is

A Visual Studio 2019 solution with one ASP.NET Core web project. Two commits, both on 2021-10-18, both by Lloyd.

| Path | What it is |
|---|---|
| `TMTCronJob.sln` | Visual Studio 16 solution. One project |
| `TMTCronJob/TMTCronJob.csproj` | SDK web project, `netcoreapp3.1` |
| `TMTCronJob/Program.cs`, `Startup.cs` | Generic host and pipeline |
| `TMTCronJob/Controllers/CronJobController.cs` | `GET /CronJob` |
| `TMTCronJob/Services/PaymentService.cs` | Load, post, and update payments |
| `TMTCronJob/Services/MailService.cs` | SMTP mail for payments that keep failing |
| `TMTCronJob/Model/` | Six JSON and row types |
| `TMTCronJob/Helper/Helper.cs` | Certificate callback that returns true |
| `TMTCronJob/appsettings.json` | Logging, connection string, `AllowedHosts` |
| `TMTCronJob/appsettings.Development.json` | Logging levels only |
| `TMTCronJob/Properties/launchSettings.json` | IIS Express and Kestrel profiles. Launch URL `CronJob` |
| `.gitignore`, `.gitattributes` | Added in the first commit (`14106e7`) |

17 files were added in `cbc8461` (843 lines). Provenance: **Implemented**.

## History

| Commit | Date | Author | Subject |
|---|---|---|---|
| `14106e7` | 2021-10-18 15:46:56 +0200 | Lloyd (`sherewalloyd@gmail.com`) | Add `.gitignore` and `.gitattributes` |
| `cbc8461` | 2021-10-18 15:46:58 +0200 | Lloyd (`sherewalloyd@gmail.com`) | Add project files |

Nothing in git is dated after 2021-10-18.

## Scope in this repository

In scope, because it is committed:

- One HTTP entry point that runs both settlement passes and then returns `200` with the text `Cronjob completed`.
- MySQL reads and writes against `infringement`, `transaction`, `paymentProvider`, and `user`.
- HTTP posts to a base URL hardcoded as `http://192.168.0.41:8080/`.
- An SMTP attempt via `smtp.gmail.com`.

Out of scope, because it is not in this repository:

- The schema (`CREATE TABLE` is absent). Column names exist only as SQL text.
- The internal fine API that serves `infringement/payinfringement` and `IForce/registerpayment`.
- A scheduler. Nothing in the tree invokes `GET /CronJob` on a timer.
- Authentication of the caller.
- Tests, a pipeline, Docker, Serverless, or infrastructure-as-code.
- A README or a written business rule.

## Architecture

```text
Caller (unknown)
  → GET /CronJob          CronJobController.Get
      → MySQL             paymyfines_qa on Amazon RDS (connection string in appsettings.json)
      → POST              http://192.168.0.41:8080/infringement/payinfringement
      → POST              http://192.168.0.41:8080/IForce/registerpayment
      → SMTP              smtp.gmail.com:587   only when a retry's try count exceeds 3
  ← 200 "Cronjob completed"
```

The controller opens its own `MySqlConnection`. `Startup` also registers a `MySqlConnection` with dependency injection. The controller does not inject it.

`PaymentService.LoadInfringements` sorts rows by `strInfringementSource`. The controller passes the two result lists in the opposite order from the method parameters, so the list named for eNaTIS is the one later sent to the iForce method, and the reverse. Detail and the status each path writes are in `prd.md` and `business-rules.md`.

## Milestones and implementation plan

No milestone, roadmap, or implementation plan is in the repository.

**Inferred** sequence from the two commits: ignore files, then the whole application, two seconds apart, on 2021-10-18. That is history, not a plan.

`pmf-backend-ah` was committed later (2022-05-06) and contains a recognisably similar routine. That date is evidence about the other repository, not a milestone written in this one.

## Dependencies

| Package | Version | Where |
|---|---|---|
| `MySql.Data` | 8.0.26 | `TMTCronJob.csproj` |
| `Newtonsoft.Json` | 13.0.1 | `TMTCronJob.csproj` |

Framework: `netcoreapp3.1`. The ASP.NET Core metapackage comes from the web SDK. No `packages.lock.json`.

Runtime services named in code, not shipped here: MySQL (`paymyfines_qa`), the HTTP API at `192.168.0.41:8080`, Gmail SMTP.

## Current status

Dormant in git. One branch (`master`), last change 2021-10-18.

The application is complete enough to build and to run `GET /CronJob`. It is not complete as an operated job: no scheduler, no authentication, credentials in source, and the list arguments are reversed relative to the method signature. Whether any host still runs this binary is **Unknown / Requires Confirmation**.

## Discrepancy — scan-host file list

The onboarding issue (recorded 2026-09-28) lists this top-level structure from the scan host:

```text
sonar-project.properties
sonarqube_scan.bat
TMTCronJob
TMTCronJob.sln
```

`TMTCronJob/` and `TMTCronJob.sln` match git at `cbc8461`. `sonar-project.properties` and `sonarqube_scan.bat` are not in git. The clone used for this document does not contain them either.

**Unknown / Requires Confirmation:** those two files may be untracked files that exist only on the scan host.

## Human confirmation

1. Is `Paymyfines-CronJob` still deployed, or was it replaced by the settlement job in `pmf-backend-ah`?
2. Who calls `GET /CronJob`, and on what schedule?
3. Is the reversed list order in `LoadInfringements` an unintentional swap?
4. Is `http://192.168.0.41:8080/` still the fine API, and for which environment?
5. Is database `paymyfines_qa` the intended target? The password is committed in `appsettings.json`. It is omitted here. Rotate it.
6. Are the live column names `refTrasactionID` and `strRecieptNumber`, as the SQL spells them?
7. What value belongs in iForce `terminalId`? The code sends `0` with the comment `what goes here??`.
8. Is failure mail supposed to go to the Gmail address in `MailService`, with CC taken from `user.strRole = '["ADMIN"]'`?
9. Do `sonar-project.properties` and `sonarqube_scan.bat` exist outside git?
