327 lines
12 KiB
Markdown
327 lines
12 KiB
Markdown
# PROJECT_KNOWLEDGE.md
|
||
|
||
Project-specific technical and domain knowledge for RollCalcPython.
|
||
|
||
## Purpose
|
||
|
||
RollCalcPython is an internal roll calculator for Naue roll products. The backend is a minimal Flask application that provides authentication, routing, static file delivery, and access logs. Most domain behavior runs in the browser inside `templates/roll_calculator.html`.
|
||
|
||
The tool is not intended as an unchecked source of truth. Inputs and outputs must be checked for plausibility before operational use.
|
||
|
||
## Current Architecture
|
||
|
||
Backend:
|
||
|
||
- `app.py` creates the Flask app.
|
||
- HTTP Basic Auth is implemented with `Flask-HTTPAuth`.
|
||
- Users are configured in local deployment file `config/users.json` with Werkzeug password hashes. This file is ignored by Git.
|
||
- `/` renders the active calculator template.
|
||
- `/help` renders the authenticated Help landing page.
|
||
- `/help/user-manual` renders `docs/de/user_manual.md` server-side inside the RollCalc Help layout.
|
||
- `/help/quick-reference` renders `docs/en/quick_reference.md` server-side inside the RollCalc Help layout.
|
||
- `/help/recent-changes` renders `docs/de/recent_changes.md` server-side inside the RollCalc Help layout.
|
||
- `/help/user-manual/screenshots/<path:filename>` serves German manual screenshots from `docs/de/screenshots/`.
|
||
- `/static/<path:filename>` is intended to serve static files behind Basic Auth.
|
||
- `/api/health` returns health/version information.
|
||
- `/api/user` returns the authenticated user.
|
||
- Access events are appended to `access_log.json`.
|
||
- `build_info.json` is loaded at startup and exposed to all templates as `build_info`.
|
||
|
||
Frontend:
|
||
|
||
- `templates/roll_calculator.html` is the active application page.
|
||
- The page contains most CSS and JavaScript inline.
|
||
- `window.ARTICLE_DATA` is loaded from `/static/article-data.json`.
|
||
- `window.APP_CONFIG` is currently defined inline for forklift rules.
|
||
- A disclaimer modal blocks use until the user checks the confirmation checkbox.
|
||
- The footer displays build metadata: version, branch, commit, and timestamp.
|
||
|
||
## Build Info
|
||
|
||
Build/deployment metadata is read from:
|
||
|
||
```text
|
||
build_info.json
|
||
```
|
||
|
||
Expected fields:
|
||
|
||
- `version`
|
||
- `branch`
|
||
- `commit`
|
||
- `timestamp`
|
||
|
||
If `build_info.json` is missing, malformed, or does not contain a usable value, RollCalc falls back to `unknown` for that value and continues serving the site.
|
||
|
||
The data is loaded centrally in `app.py` and made available to every template as `build_info`.
|
||
|
||
## Help and User Manual
|
||
|
||
The in-app Help area keeps `docs/de/user_manual.md` as the leading German documentation source. RollCalc reads the Markdown file on each `/help/user-manual` request and renders it server-side with `markdown-it-py`.
|
||
|
||
`docs/en/quick_reference.md` is the English Quick Reference source and is rendered at `/help/quick-reference`. It is derived from the full German User Manual and must remain a concise workflow reference rather than an independently diverging technical source.
|
||
|
||
The documentation structure is prepared for language-specific manuals:
|
||
|
||
```text
|
||
docs/
|
||
de/
|
||
user_manual.md
|
||
screenshots/
|
||
en/
|
||
quick_reference.md
|
||
```
|
||
|
||
Additional languages can follow the same structure later. The current public route still opens the German manual, the Quick Reference is currently English only, and no language switcher is implemented.
|
||
|
||
Rendering rules:
|
||
|
||
- Raw HTML from the Markdown source is disabled.
|
||
- Heading ids and the table of contents are generated from the Markdown content.
|
||
- Relative image references such as `screenshots/disclaimer.png` are rewritten to the authenticated manual screenshot route.
|
||
- Screenshots belong in the active language's `screenshots/` directory, currently `docs/de/screenshots/`; the screenshot route must remain limited to that directory.
|
||
|
||
The Help pages use the same HTTP Basic Auth protection as the calculator.
|
||
|
||
### Recent Changes and What's New
|
||
|
||
Full user-facing release notes are maintained in:
|
||
|
||
```text
|
||
docs/de/recent_changes.md
|
||
```
|
||
|
||
The calculator header links directly to `/help/user-manual`. The Help landing page lists only existing documents, currently User Manual, Quick Reference, and Recent Changes.
|
||
|
||
The startup What's New dialog uses `build_info.version` and is suppressed when the version is empty or `unknown`. The last acknowledged version is stored only in browser `localStorage` under:
|
||
|
||
```text
|
||
rollcalc_last_seen_version
|
||
```
|
||
|
||
The short dialog item list is maintained separately in:
|
||
|
||
```text
|
||
static/recent_changes.json
|
||
```
|
||
|
||
This JSON is a compact summary for the dialog, not the complete release history. Keep it aligned with the most relevant current entries from `docs/de/recent_changes.md`.
|
||
|
||
## Authentication
|
||
|
||
RollCalc uses HTTP Basic Auth. User entries are stored in the local deployment file:
|
||
|
||
```text
|
||
config/users.json
|
||
```
|
||
|
||
This file is intentionally ignored by Git. The versioned file `config/users.example.json` documents the JSON format only and must not contain real usernames, hashes, or passwords.
|
||
|
||
The file stores username-to-password-hash mappings:
|
||
|
||
```json
|
||
{
|
||
"username": "<hash>"
|
||
}
|
||
```
|
||
|
||
Password verification uses `werkzeug.security.check_password_hash`. Users are managed with:
|
||
|
||
```bash
|
||
python3 scripts/manage_users.py
|
||
```
|
||
|
||
The management tool provides a text menu for listing users, creating users, changing passwords, and deleting users. New hashes use the existing RollCalc method `pbkdf2:sha256:600000`.
|
||
|
||
The Flask app requires a readable, valid, non-empty `config/users.json` at startup and does not silently create an empty user file. If the file is missing or invalid, startup should fail with a message pointing to `python3 scripts/manage_users.py`.
|
||
|
||
Passwords must not be logged. Password hashes should only be stored in `config/users.json` or a future protected deployment-specific secret source.
|
||
|
||
Deployment notes:
|
||
|
||
- The systemd/service user must be able to read `config/users.json`.
|
||
- Suitable server permissions can be owner `martin`, group `www-data`, mode `640`, adjusted to the actual deployment users.
|
||
- Do not hard-code deployment owners or groups in Python.
|
||
- Back up the productive `config/users.json` before deploying or replacing a server instance.
|
||
|
||
## Roll Geometry
|
||
|
||
Calculations assume an ideal cylindrical winding.
|
||
|
||
Assumptions:
|
||
|
||
- Constant material thickness.
|
||
- No compression.
|
||
- No air gaps.
|
||
- Roll geometry is derived mathematically, not physically measured in the app.
|
||
|
||
Nominal diameter formula used by the Direct Calculation tab:
|
||
|
||
```text
|
||
D = sqrt(d^2 + (4 * L * 1000 * t) / pi)
|
||
```
|
||
|
||
Variables:
|
||
|
||
- `D`: roll diameter in mm.
|
||
- `d`: core diameter in mm.
|
||
- `L`: product length in m.
|
||
- `t`: material thickness in mm.
|
||
|
||
When a tolerance/stddev value is present, the UI also displays a `-2σ` and `+2σ` diameter range.
|
||
|
||
## Product Length and Extrapolation
|
||
|
||
Product length from a known diameter is calculated by rearranging the diameter formula:
|
||
|
||
```text
|
||
L = (pi / (4 * t)) * (D^2 - d^2) / 1000
|
||
```
|
||
|
||
The extrapolation tab estimates a new diameter from a known roll diameter/length pair:
|
||
|
||
```text
|
||
D1 = sqrt(d^2 + (L1 / L0) * (D0^2 - d^2))
|
||
```
|
||
|
||
Variables:
|
||
|
||
- `D0`: known/measured roll diameter.
|
||
- `L0`: known/measured roll length.
|
||
- `L1`: target length.
|
||
- `D1`: extrapolated roll diameter.
|
||
|
||
## Roll Weight
|
||
|
||
Roll weight is calculated client-side when width, area weight, and length are available:
|
||
|
||
```text
|
||
weight_kg = area_weight_g_m2 * length_m * width_m / 1000
|
||
```
|
||
|
||
Material thickness and area weight values are loaded from article data and are generated automatically. They are not guaranteed to be complete or reviewed.
|
||
|
||
## Article Data
|
||
|
||
Active data source:
|
||
|
||
```text
|
||
static/article-data.json
|
||
```
|
||
|
||
The UI expects article records with fields such as:
|
||
|
||
- `nr`
|
||
- `name`
|
||
- `thickness`
|
||
- `thickness_stddev`
|
||
- `area_weight`
|
||
- `area_weight_stddev`
|
||
- `core_type`
|
||
|
||
Observed additional fields include min/max/count values for material thickness and area weight.
|
||
|
||
Important data rule:
|
||
|
||
- Article data is generated from ERP-derived sources.
|
||
- These values should not be manually changed unless the task is explicitly data maintenance.
|
||
|
||
Article-data architecture decision:
|
||
|
||
- Article data should evolve from a simple article catalogue into a shared production knowledge base.
|
||
- Each article may optionally provide production-related default values.
|
||
- Initial defaults include `Product Thickness`, `Area Weight`, `Core Diameter`, and `Roll Width`.
|
||
- Future production-related defaults can be added without changing the overall architecture.
|
||
- When an article is selected, available defaults are copied into the calculator fields.
|
||
- Missing optional values must never overwrite existing user input.
|
||
- All automatically populated values remain editable by the user.
|
||
- The planned Article-Data-Admin application will become the authoritative editor for these production defaults.
|
||
|
||
Known domain caveat from existing project notes:
|
||
|
||
- For articles in the groups Secugrid, Combigrid, Carbofol MF/MF, Carbofol F/F, Carbofol s/F, and Carbofol BF/s, the thickness from `article-data.json` must not be used without domain validation.
|
||
|
||
## Forklift and Heavy-Roll Rules
|
||
|
||
The active template currently evaluates forklift warnings through `checkForklift()` and inline `window.APP_CONFIG`.
|
||
|
||
Current inline rule behavior:
|
||
|
||
- Applies to category `bentofix`.
|
||
- Warning threshold: `1700 kg`.
|
||
- Hard limit: `2750 kg`.
|
||
- Minimum core outer diameter: `170 mm`.
|
||
|
||
There is also a richer JSON configuration in:
|
||
|
||
```text
|
||
static/config.json
|
||
```
|
||
|
||
That file includes localized messages and additional equipment requirements. Before changing forklift behavior, verify whether the active inline config or the static JSON should be authoritative.
|
||
|
||
## Load Optimizer
|
||
|
||
The Load Optimizer is implemented inline in `templates/roll_calculator.html`.
|
||
|
||
Classes:
|
||
|
||
- `LoadOptimizer`
|
||
- `LoadOptimizerUI`
|
||
|
||
It uses calculated roll data from the Direct Calculation tab:
|
||
|
||
- Roll diameter.
|
||
- Core diameter.
|
||
- Roll width.
|
||
- Roll weight.
|
||
- Product length.
|
||
- Square meters per roll.
|
||
|
||
It supports transport presets:
|
||
|
||
- 20ft Container.
|
||
- 40ft Container.
|
||
- 40ft High Cube.
|
||
- LKW Sattelzug.
|
||
- LKW Tandem.
|
||
|
||
It calculates limiting scenarios by:
|
||
|
||
- Weight.
|
||
- Volume.
|
||
- Geometry.
|
||
|
||
It also draws a side-view SVG visualization.
|
||
|
||
## Disclaimer Gate
|
||
|
||
The active calculator page includes a disclaimer modal shown after Basic Auth login and before calculator use.
|
||
|
||
The modal:
|
||
|
||
- Contains German and English disclaimer text.
|
||
- Requires checkbox confirmation.
|
||
- Enables the confirmation button only after the checkbox is selected.
|
||
- Hides the overlay after confirmation.
|
||
|
||
This is client-side only. It is not persisted, logged, or enforced server-side.
|
||
|
||
## Admin Area State
|
||
|
||
RollCalc no longer contains an admin UI or admin API. The previous `/admin/logs` route and `templates/admin.html` have been removed.
|
||
|
||
Login/access logging remains part of RollCalc, but log viewing and article-data administration should not be implemented inside this app. Maintenance of `article-data.json` is planned for a separate application.
|
||
|
||
## Known Technical Risks
|
||
|
||
- Password hashes are currently configured in `app.py`; this should eventually move to a protected external configuration or secrets mechanism.
|
||
- Basic Auth only; no sessions or role framework beyond the user dictionary.
|
||
- `access_log.json` is rewritten on every logged request and is not concurrency-safe.
|
||
- No log rotation or retention policy is implemented.
|
||
- Flask's default static route may conflict with the intended authenticated `/static/<path:filename>` behavior; verify effective routing before relying on protected static files.
|
||
- Most active logic is concentrated in one large HTML template.
|
||
- Multiple similar static JavaScript files exist; not all are necessarily active.
|
||
- No automated test suite is visible.
|
||
- Some docs and filenames in `docs/` may reflect earlier package/archive versions.
|