- Go 100%
| .github/instructions | ||
| cmd/worker | ||
| internal | ||
| logs | ||
| .gitignore | ||
| go.mod | ||
| go.sum | ||
| README.md | ||
PPNL Worker
One-shot Go worker service designed to run from Windows Task Scheduler. It collects data from a hospital pharmacy MySQL database and sends it to the PPNL API.
Each execution performs one cycle:
- Connect to MySQL.
- Run the undelivered medicine worker (every day).
- Run the supply and traffic workers (Mondays only, or when forced).
- Exit.
Project Structure
cmd/worker/ application entrypoint and CLI flags
internal/config/ environment-based runtime configuration
internal/service/ worker orchestration (supply, traffic, undelivered)
internal/domain/ domain models and payload types
internal/adapter/db/ MySQL collector (supply, traffic, undelivered queries)
internal/adapter/api/HTTP sender with Basic Auth
logs/ dated info and error log files (auto-created)
Workers
Undelivered medicine (daily — DPT 54)
Reports medicines that could not be fully dispensed on the previous day.
One POST per item to /Transaction/SendNumberOfUndeliveredMedicine.
Supply (Monday — DPT 55)
Calculates current stock across all depot departments using the latest inventory check as a baseline, then sums movements since that point.
Sent in batches to /Transaction/SendSuppliesBulk.
Traffic (Monday — DPT 56/57/59)
Calculates medicine movement for the previous calendar week (Mon–Sun):
| DataProcessingType | Document types env vars | Amount calculation |
|---|---|---|
| 56 | IZDATNICA_BIS |
SUM(izlaz), 2 decimal places |
| 57 | IZDATNICA_TROSAK, IZDATNICA_DEPO, IZDATNICA_RASHOD |
SUM(izlaz / kolicina), 2 decimal places |
| 59 | STORNO_PRIMKA (storno) |
SUM(ABS(ulaz) / kolicina), rounded to integer |
| 59 | POVRATNICA |
SUM(izlaz), rounded to integer |
Sent in batches to /Transaction/SendTrafficBulk.
Configuration
All configuration is loaded from environment variables. Place them in a .env file next to the executable (or set them in the system environment).
Required
| Variable | Description |
|---|---|
MYSQL_DSN |
MySQL DSN, e.g. user:pass@tcp(host:3306)/dbname?parseTime=true |
API_BASE_URL |
Base URL of the PPNL API |
API_USERNAME |
Basic Auth username |
API_PASSWORD |
Basic Auth password |
SENDER_ID |
Pharmacy sender identifier sent in every payload |
IZDATNICA_BIS |
skladisni.id for BIS issue documents (DPT 56) |
IZDATNICA_TROSAK |
skladisni.id for expense issue documents (DPT 57) |
IZDATNICA_DEPO |
skladisni.id for depot issue documents (DPT 57) |
IZDATNICA_RASHOD |
skladisni.id for write-off documents (DPT 57) |
STORNO_PRIMKA |
skladisni.id for storno receipt documents (DPT 59) |
POVRATNICA |
skladisni.id for return documents (DPT 59) |
Optional
| Variable | Default | Description |
|---|---|---|
API_TIMEOUT_SECONDS |
15 |
Per-request HTTP timeout |
SUPPLY_BATCH_SIZE |
100 |
Payloads per bulk request (applies to both supply and traffic) |
LOG_RETENTION_DAYS |
30 |
Days to keep info_*.log files |
DRY_RUN |
false |
Set to true to log payloads instead of sending them |
LJEKARNA_ODJEL_ID |
(unset) | For pharmacies without a depot: use this single odjel.id for supply calculations instead of querying odjel WHERE depo=1 |
CLI Flags
ppnl-worker.exe [flags]
| Flag | Description |
|---|---|
| (none) | Run all workers; supply+traffic only on Monday |
-force |
Run supply and traffic regardless of day of week |
-only-undelivered |
Run only the undelivered worker |
-only-supply |
Run only the supply worker (day-of-week check bypassed) |
-only-traffic |
Run only the traffic worker (day-of-week check bypassed) |
Build & Run
# Run directly
go run ./cmd/worker
# Build
go build -o ppnl-worker.exe ./cmd/worker
# Dry run (no API calls, payloads logged to stdout)
$env:DRY_RUN="true"; .\ppnl-worker.exe -force
Windows Task Scheduler
Schedule the built executable to run every Monday morning:
schtasks /Create /TN "PPNL Worker" /SC WEEKLY /D MON /ST 09:00 /TR "C:\path\to\ppnl-worker.exe" /F
The .env file must be in the same directory as the executable. Logs are written to a logs\ subdirectory next to the executable.