CHAPTER 40: Validated daily values and report preservation

40a: Validate text, store cents, then total the day
40b: A failed run must leave the last good report visible

HOW TO RUN
Open a terminal in the extracted companion folder, the folder containing
automation, sql and visual_labs. Run:

    python visual_labs/ch40/walkthrough.py

Use python3 or py instead of python if that is the command established in
Chapter 15. No extra Python package is needed. Run it only after predicting
the displayed states. The exact output is also in expected_output.txt.

When a lab imports the automation examples, its short Path/sys.path setup
locates those existing modules relative to this file. It changes where this
Python process looks for imports; it does not change your operating-system
configuration. Preserve the extracted folder structure.

SOURCE AND MEANING
The lab reads the original 1 October daily fixture. It calls the existing
read_campaign_day, summary_csv and run functions. All intentionally wrong
inputs and generated reports are placed in a temporary folder and removed
when the lab finishes. None of the original files or reports is altered.

FOLLOW BEFORE YOU RUN
Locate positions 0, 1, 2 and 3 in each validated tuple. Add cents and enquiry
counts separately, then convert cents to euros for display. A tuple keeps
related values in a fixed order; its labels in the explanation tell you what
that order means.

PREDICT, RUN, COMPARE
The first run creates a valid disposable report. A changed configuration
then expects the wrong date. Predict the validation failure and whether the
report bytes will change. Next the correct date is restored and one copied
money value becomes 12.345. Predict the fractional-cent error. The script
compares the saved report bytes after each failure and prints True when they
are unchanged. Calling run directly demonstrates its core behaviour; the
chapter's command-line main adds its logging and exit-code handling.

ONE MORE INPUT TO REASON THROUGH
Keep 1 October's cost amounts but change both enquiry counts to zero. What
must the output preserve, and what should the ratio field contain?

EXPLAINED ANSWER
The report retains EUR 420.00 cost and zero enquiries. The ratio field is empty
under this chapter's documented CSV convention. Empty means unavailable,
not zero cost. Reproduce in a separate copied fixture with the original job's
configuration method; leave the baseline file available for comparison.

ABOUT THE SMALL HARNESS
TemporaryDirectory creates an isolated practice folder; with removes it after
the demonstration. read_bytes compares the entire old and new report contents.
These helpers make a deliberate bad-input exercise safe to repeat.

EXPECTED OUTPUT (verified by execution)

40a: Checked tuples
('2026-10-01', 'Spring search', 30000, 12)
('2026-10-01', 'Office newsletter', 12000, 8)
Daily report:
report_date,cost_eur,enquiries,cost_per_enquiry_eur
2026-10-01,420.00,20,21.00
40b: Successful run accepted 2 rows
Wrong-date failure: Line 2: unexpected business date
Previous report unchanged: True
Fractional-cent failure: Line 2: use at most two money decimals
Previous report still unchanged: True

All data in this lab are fictional teaching examples.
