Carry 'INCL' tariffs through instead of arriving blank
The engineer reported that some of his tariffs on Blueberry Square were saying 'included' and did not pull through. He was right, and it was not a big issue for the wrong reason - it was a real gap. Candy prints a WORD in the rate column where a tariff is carried inside a sum above rather than priced separately - INCL, incl VAT, PROV. Those lines have a quantity but no figure, so there was nothing numeric to write and the cells arrived BLANK. To the consultant that is indistinguishable from a failed conversion. The source's own wording is now written into the rate cell and the line is listed as a note: F15 = 'INCL' a) Office buildings F17 = 'INCL' b) Survey Equipment 20 such lines on the Blueberry pair. The amount column is left alone because there genuinely is no figure for that line - the money is in the sum above it. Caught a placement bug doing it: the write sat after the early return for lines whose quantity already matched, which is most of them, so it fired zero times. Moved it before the quantity block. Both pairs re-verified after: formulas intact, 0 damaged, gate not blocked.
This commit is contained in:
parent
a9b74e5859
commit
848f3093ea
3 changed files with 48 additions and 0 deletions
19
README.md
19
README.md
|
|
@ -232,6 +232,25 @@ checked rather than intended. On the SANS 1200 template, where quantities are
|
|||
derived (`=G35`, `=CEILING.MATH(...)`), writing a literal over that would
|
||||
destroy the engineer's model while looking like it worked.
|
||||
|
||||
## Tariffs carried inside a sum
|
||||
|
||||
Candy sometimes prints a **word where a rate would go** — `INCL`, `Incl VAT`,
|
||||
`PROV` — meaning that tariff is included in the sum above rather than priced
|
||||
separately. Those lines have a quantity but no figure, and they used to arrive
|
||||
in the consultant's file as **blank cells**, which read as a failure to pull
|
||||
through. That is exactly what the engineer reported.
|
||||
|
||||
They now carry the source's own wording into the rate cell, and are listed as a
|
||||
note rather than a disagreement:
|
||||
|
||||
```
|
||||
F15 = 'INCL' a) Office buildings
|
||||
F17 = 'INCL' b) Survey Equipment
|
||||
```
|
||||
|
||||
The amount column is left alone, because there is genuinely no figure for that
|
||||
line — the money is in the sum above it. 20 of these on the Blueberry pair.
|
||||
|
||||
## A person decides the rest
|
||||
|
||||
The aligner leaves some lines unplaced because nothing scored high enough, and
|
||||
|
|
|
|||
|
|
@ -147,6 +147,11 @@ class Row:
|
|||
qty: float | None = None
|
||||
rate: float | None = None
|
||||
amount_txt: str = ""
|
||||
# Candy prints a WORD in the rate/amount column when a tariff is carried
|
||||
# inside a sum rather than priced separately - "INCL", "Incl VAT", "PROV".
|
||||
# That is a real tariff decision, not a missing number, and it has to
|
||||
# survive into the consultant's file instead of arriving as a blank.
|
||||
tariff_note: str = ""
|
||||
top: float = 0.0
|
||||
page: int = 0
|
||||
|
||||
|
|
@ -196,9 +201,13 @@ def _page_rows(page, pno: int) -> list[Row]:
|
|||
continue
|
||||
if col == "rate" and r.rate is None:
|
||||
r.rate = _to_num(txt)
|
||||
if r.rate is None and not txt.replace(".", "").isdigit():
|
||||
r.tariff_note = (r.tariff_note + " " + txt).strip()
|
||||
continue
|
||||
if col == "amount":
|
||||
r.amount_txt = (r.amount_txt + " " + txt).strip()
|
||||
if _to_num(txt) is None and not txt.replace(".", "").isdigit():
|
||||
r.tariff_note = (r.tariff_note + " " + txt).strip()
|
||||
continue
|
||||
if UNIT_X_MIN <= x0 < UNIT_X_MAX:
|
||||
r.unit = (r.unit + txt).strip()
|
||||
|
|
@ -348,6 +357,7 @@ def _merge_continuations(rows: list[Row]) -> list[Row]:
|
|||
@dataclass
|
||||
class Line:
|
||||
kind: str = "line"
|
||||
tariff_note: str = ""
|
||||
number: str = ""
|
||||
desc: str = ""
|
||||
unit: str = ""
|
||||
|
|
@ -505,6 +515,7 @@ def _build(content: list[Row]) -> Group:
|
|||
and t.depth(num) >= 3
|
||||
|
||||
line = Line(
|
||||
tariff_note=r.tariff_note,
|
||||
number=num,
|
||||
desc=f"{sub}) {body}" if sub else body,
|
||||
unit=r.unit.strip(),
|
||||
|
|
|
|||
|
|
@ -507,6 +507,7 @@ def source_lines(tree: dict, *, with_prices: bool = True) -> list[dict]:
|
|||
return
|
||||
out.append({
|
||||
"number": node.get("number", "") or "",
|
||||
"tariff_note": (node.get("tariff_note") or "").strip(),
|
||||
"desc": (node.get("desc") or "").strip(),
|
||||
"unit": (node.get("unit") or "").strip(),
|
||||
"qty": node.get("qty"),
|
||||
|
|
@ -885,6 +886,23 @@ def _write_one(wb, name: str, lay: Layout, ln: dict,
|
|||
field="unit", template_value=cur,
|
||||
source_value=ln["unit"])
|
||||
|
||||
# --- a tariff carried inside a sum ("INCL", "incl VAT") -----------------
|
||||
# Written as the literal text the source printed. A blank cell here reads
|
||||
# as a failure to the consultant; the source's own wording is the honest
|
||||
# answer, and the amount column is left alone because there is no figure.
|
||||
note = (ln.get("tariff_note") or "").strip()
|
||||
if note and ln["rate"] is None and c_rate and \
|
||||
ws.cell(r, c_rate).value in (None, ""):
|
||||
if _writable(ws, r, c_rate, res, name, label, "rate"):
|
||||
ws.cell(r, c_rate, note)
|
||||
res.wrote(name, r, c_rate, note)
|
||||
res.written += 1
|
||||
res.add("info", name, r, label,
|
||||
f"carried in the sum - the source prints \"{note}\" rather "
|
||||
f"than a rate, so that wording was kept. There is no amount "
|
||||
f"for this line.",
|
||||
source=note)
|
||||
|
||||
# --- quantity ------------------------------------------------------------
|
||||
stop = False
|
||||
if c_qty and ln["qty"] is not None:
|
||||
|
|
|
|||
Loading…
Reference in a new issue