Replaced the inline Substring-based truncation (which cut mid-word,
e.g. "...เนื่องจากป") with a TruncateAtWord() helper in the report's
ScriptText that backs off to the last space before the length limit
when one exists, falling back to a hard cut only when the text has no
spaces at all within that range (common in run-on Thai text).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0153wBt23EjW125ZsADwWVAs
FastReport doesn't support splitting a single growing text object
mid-paragraph across multiple physical pages — an oversized field
just clips at the page boundary instead of flowing to a new page.
Capped the free-text fields most prone to this (reason, old/new
workload) at 200-300 characters with a "..." suffix when truncated,
so pathologically long input degrades gracefully instead of clipping
mid-sentence or overlapping following content.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0153wBt23EjW125ZsADwWVAs
Data1b (the checklist section) was a separate sibling band positioned
right after P1PositionsList. FastReport's CanGrow only reliably shifts
down objects within the SAME band — a long reason text growing past
its declared box didn't push the next sibling band down with it,
causing visible overlap. Merged the checklist into P1PositionsList so
everything shares one growable band.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0153wBt23EjW125ZsADwWVAs
overall_reason is never populated on this record (or apparently any
real one) — the actual "เหตุผลความจำเป็น" data users fill in on the web
form lives on form_1_2_positions.reason (the same field already shown
on page 2). Moved the heading+value into the position-list band so it
reads from there instead.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0153wBt23EjW125ZsADwWVAs
Split the page-1 band into Data1a (header through สังกัด งาน + the
list heading) and Data1b (เหตุผล.../checklist), with the repeating
position list band in between — matching the reference form's actual
ordering instead of pushing the list to the bottom of the page.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0153wBt23EjW125ZsADwWVAs
Data1's declared Height (1000) consumed nearly the whole A4 page,
pushing the sibling P1PositionsList band onto its own extra page.
Trimmed to 810 (just past the last real content) so both bands share
page 1 as intended. Also widened the "ที่ อว 0653." label — it was
being clipped at the old narrow width.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0153wBt23EjW125ZsADwWVAs
Two fixes needed together to make the new 3-page เอกสารแนบ ร.1 template
actually render:
1. rmutr_report keeps its own separate copy of the form_1_2 C# model
(Models/RoReport/form_1_2.cs), which never got the New2570-spec
fields (division_name, request_count, overall_reason, signer_*,
approver_*) or the form_1_2_positions child list that rmutr-api's
model already has. FastReport's RegisterData binds by reflecting
the actual runtime object, so any Dictionary column not present on
this local class silently fails to compile ("does not exist in
current context") for every field on it.
2. Nested BusinessObjectDataSource fields must be referenced by their
full dotted path from the report root ([form_1_2.form_1_2_positions.
field]), not the bare child name ([form_1_2_positions.field]) —
confirmed against another working report (academic_position.frx)
in this same codebase that uses the identical nesting pattern
correctly.
Verified locally: report now compiles and reaches PDF export (the
only remaining local failure is a NullReferenceException in libgdiplus
font handling specific to this macOS dev machine, unrelated to the
report itself — production runs Linux where this already works for
every other report using TH Sarabun New).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0153wBt23EjW125ZsADwWVAs
Replaces the old 1-page บันทึกข้อความ memo layout (which didn't match
the actual paper form used) with the real 3-page แนบ ร.1 attachment:
page 1 summary + position list, page 2 old/new position detail table
(repeats once per position via form_1_2_positions, one A4 sheet per
อัตรา), page 3 signatures + หัวหน้าหน่วยงาน decision. All blanks bound
to existing form_1_2 / form_1_2_positions fields (no new backend
fields needed — the New2570 spec fields were already there, just
never wired into a template).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0153wBt23EjW125ZsADwWVAs
Bind to durable_articles_three.subject and shift the following
elements (รายการครุภัณฑ์ header, data band, footer, summary band)
down by 28.35 to make room.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>