Business plan draft 0.3 in two versions: Plan A ~180M and Plan B ~225M THB
Deploy test site / deploy (push) Successful in 52s

- One build makes both documents: plan_variant.py switches the
  plan-specific text (pick / is_a / label); build_plan.py writes
  CNX-Vinyl-Business-Plan-A and -B (docx), export_pdf.py exports both PDFs
  with the table of contents filled in. Draft 0.2 (single launch-plant
  plan with contingency) is removed; it stays in the history.
- Plan A: the launch plant with every machine and six cost levers, ~177M
  THB with the ramp-up reserve, no contingency. Plan B: the second Duplex
  at launch, five presses, ~224M THB on the same basis. Each version reads
  as a complete plan with one table comparing it with the other; the
  216M investor-question text is gone, Pheenix is priced at OMS's
  reference plus 20 %.
- Calculator renders in both documents, each from its own preset: the
  plant at a glance (Figure 4), the budget check (Figure 5) and ten years
  of cash (Figure 6), in docs/renders/calculator/.
- Calculator budget card: the verdict and third KPI now name the tightest
  budget the midpoint fits (Plan A: 3.3M to spare under 180M; Plan B:
  0.8M under 225M) instead of always 225M.
- Fixes: CD replication cross-references point to section 4.10; the
  blended price in section 3.3 and roadmap item 1 is 3.76 to 5.27 USD at
  60 % specials (3.50 to 4.60 at a standard-heavy mix).
This commit is contained in:
grabowski committed 2026-10-17 15:42:35 +07:00
1 parent f2ff1eac1f
commit bd357ab03f
19 files changed
+1618 -685

No files matched your search

+245 -85
View File
@@ -1,6 +1,9 @@
"""Part B: what makes it top-notch (traceability, metrology, QC, efficiency); site and building;
regulatory (BOI and licences). Draft 0.2, October 2026."""
regulatory (BOI and licences). Draft 0.3, October 2026: one text for both versions, Plan A (~180M
THB, the launch plant with six cost levers) and Plan B (~225M THB, five presses, everything in); the
plan-specific passages switch with plan_variant.pick(), called inside blocks()."""
from plan_lib import H1, H2, H3, P, B, N, T, KV, IMG, CALL, PB
from plan_variant import pick, is_a, is_b, label, name
def blocks():
@@ -13,7 +16,7 @@ def blocks():
"capabilities are what a regional customer cannot buy today and what justifies export-grade "
"pricing. None of it is exotic: the instruments exist, the data interfaces exist, and the "
"engineering is well understood. What is unusual is putting all of it in one plant from the "
"start rather than bolting it on later. The launch plant makes that possible: with the cutting "
"start rather than bolting it on later. The plan makes that possible: with the cutting "
"room and galvanics in-house from the first release, the whole chain from lacquer to box runs "
"through our own floor, with no bought-in stamper whose history we cannot see."),
@@ -148,16 +151,16 @@ def blocks():
T(["Instrument", "What it measures", "How it is used", "When"], [
["XRF thickness gauge (Fischer or Bowman class)", "Nickel deposit thickness, non-destructive",
"Per serial, read on the outer land zones; replaces the ten-point micrometer. Target total "
"thickness variation 10 to 20 microns", "Launch tier"],
["Inline machine vision", "Cosmetic defects", "100% of parts, fast", "Launch tier"],
"thickness variation 10 to 20 microns", "At launch"],
["Inline machine vision", "Cosmetic defects", "100% of parts, fast", "At launch"],
["3D laser confocal microscope (Keyence VK-X class)", "Groove cross-section, wall roughness, "
"micro-defects; 20 nm vertical, ~120 nm lateral resolution, non-contact", "Sampled radial "
"zones (lead-in, outer, mid, inner) on fathers, mothers and stampers; the full spiral is not "
"feasible and not needed. The optical-disc industry verified its nickel stampers with this "
"instrument class", "Full stack; from revenue if the lever is used"],
"instrument class", pick("From revenue", "At launch")],
["Wide-area optical profiler (Keyence VR-6000 class)", "Form, flatness, gross defects; 0.1 "
"micron height resolution, ~1 s per field, HDR mode for mirror-bright nickel",
"Fast whole-part mapping", "Full stack; from revenue if the lever is used"],
"Fast whole-part mapping", pick("From revenue", "At launch")],
["Stylus profilometer", "Traceable reference", "Calibrates the optical instruments",
"With the optical instruments"],
], widths_mm=[38, 46, 56, 30], font_pt=8.5),
@@ -173,21 +176,34 @@ def blocks():
"scripting, but there is no off-the-shelf connector to a factory system. A small watcher at the "
"metrology bench stamps each result with the part serial scanned from its back, writes the "
"verdict to the part's quality inspection in ERPNext and the raw file to the machine-data store."),
CALL("Metrology: the investor's choice", [
"**Full stack at launch.** The metrology and QC block is USD 350k to 810k (11.6M to 26.7M THB, "
"estimate, section 8): XRF, laser confocal, wide-area profiler, inline vision on the three "
"presses and the audio station. Every father, mother and stamper is measured before the next "
"plating generation or the press.",
"**Launch tier.** XRF, inline vision and the audio station at launch; the laser confocal and "
"the wide-area profiler bought from revenue. That saves ~10.1M THB at the midpoint with its "
"share of the contingency, one of the four levers that bring the plant inside 216M THB. Until "
"they arrive, groove geometry on the metal is judged indirectly, through the test pressing and "
"the audio station, as most plants do today; thickness and cosmetics are still measured on "
"every part.",
"Either way the data path is the same, so the later instruments plug in without rework. "
CALL(f"Metrology in {name()}: " + pick("the launch tier", "the full stack at launch"), pick([
"**At launch: XRF, inline vision and the audio station**, USD 170k to 460k (5.6M to 15.2M THB, "
"estimate, section 8). Every father, mother and stamper still gets its nickel thickness "
"measured per serial by XRF and its surface screened by vision, and every record is still "
"inspected optically on the three presses, logged per cycle and sampled by the audio station "
"(section 5.3).",
"**From revenue: the laser confocal and the wide-area profiler**, USD 180k to 350k (estimate). "
"Buying them later takes ~8.8M THB out of the capital round at the midpoint, one of the six "
"levers that bring the plan to ~180M THB. Until they arrive, groove geometry and form on the "
"metal are judged indirectly, through the test pressing and the audio station, as most plants "
"do today.",
"The data path is the same from the first day, so the later instruments plug in without "
"rework. Distributor quotes for the metrology stack are one of the four requests that settle "
"the budget.",
], [
"**At launch: the full stack.** The metrology and QC block is USD 350k to 810k (11.6M to 26.7M "
"THB, estimate, section 8): XRF, laser confocal, wide-area profiler, inline vision on the presses "
"and the audio station. Every father, mother and stamper is measured before the next plating "
"generation or the press. The block was priced with inline vision on three presses, so the "
"cameras for the second Duplex system are to quote.",
"**If quotes land high,** the laser confocal and the wide-area profiler (USD 180k to 350k, "
"estimate) are the part that can wait and be bought from revenue: thickness and cosmetics "
"would still be measured on every part, and groove geometry judged through the test pressing "
"and the audio station meanwhile, as most plants do today.",
"Either way the data path is the same, so later instruments plug in without rework. "
"Distributor quotes for the metrology stack are one of the four requests that settle the "
"budget.",
]),
])),
H2("5.3 Quality control: three layers for every record, one gate for every material"),
P("Full automated audio checking of every record is physically impossible: a 12-inch record plays "
@@ -202,7 +218,8 @@ def blocks():
"stamper), stitching and flow lines, warp, off-centre spindle holes, surface debris, wrong or "
"off-centre labels. Non-fill and stitching correlate with audible defects, so this is a strong "
"proxy for audio quality", "Custom integration of general machine vision (Keyence or Cognex "
"class) on all three presses; no vinyl-specific product exists"],
"class) on all " + pick("three", "five") + " presses; no vinyl-specific "
"product exists"],
["2. Press telemetry, every cycle", "Mould temperatures, pressures, cycle time, extruder values, "
"yields and drift alerts from the press PLC", "Process drift before it becomes a defect; the "
"record-level context for every other check", "Proven in the industry (Viryl's ADAPT model). "
@@ -214,7 +231,8 @@ def blocks():
"from lead-in silence, channel balance; score and pass/fail to the record", "Wrong master cut "
"into good-looking grooves, EQ and mastering errors, speed and pitch problems; what no camera "
"can see", "Buildable from proven parts (Stamper Discs' Fonograph approach, iZotope-class "
"algorithms); first of its kind as a whole; in the launch tier"],
"algorithms); first of its kind as a whole; " + pick("in the launch tier",
"at launch")],
], widths_mm=[30, 46, 54, 40], font_pt=8.5),
P("**Sampling rule for layer 3:** every test pressing and first-off per stamper, plus pulled "
"samples densifying as the stamper ages (a stamper lasts roughly 1,000 to 2,000 records; the "
@@ -247,10 +265,14 @@ def blocks():
H2("5.4 Efficiency: recover before you generate"),
P("The pressing machinery is a modest electrical load: 32 kVA connected for a full Duplex line. The "
"real demand sits in the utilities around it. At launch the three presses need 450 to 540 kg/h of "
"saturated steam at 10 bar / 180 °C and about 390 kW of cooling at a hot-afternoon peak; the "
"utility backbone is built for the five-press fleet (750 to 900 kg/h of steam, up to ~650 kW of "
"cooling). On top comes whole-plant air conditioning in a tropical climate. Newbilt excludes "
"real demand sits in the utilities around it. " + pick(
"At launch the three presses need 450 to 540 kg/h of saturated steam at 10 bar / 180 °C and "
"~391.5 kW of cooling at a hot-afternoon peak; the utility backbone is built for the "
"five-press fleet (750 to 900 kg/h of steam, up to ~650 kW of cooling). ",
"At launch the five presses need 750 to 900 kg/h of saturated steam at 10 bar / 180 °C and "
"~652.5 kW of cooling at a hot-afternoon peak, on a utility backbone with rooms for four "
"boiler and four chiller modules. ") +
"On top comes whole-plant air conditioning in a tropical climate. Newbilt excludes "
"steam and cooling from its scope, so these systems are ours to design, and the design rests on "
"one observation: the steam's job is to heat the moulds and the cooling water's job is to remove "
"that same heat again. Roughly 98% of the press cooling load is heat the steam put into the "
@@ -261,9 +283,19 @@ def blocks():
"for the five-press fleet: the boiler hall and the chiller compound with room for four modules "
"each, the steam main and condensate return, the cooling mains, the heat-exchanger frame and "
"tanks, and hydraulic and compressed-air ring mains with a valved, capped tee at every press "
"position. The machines that make steam and cold water come in identical modules: at launch "
"two 500 kg/h boilers (B-1, B-2) and two 250 kW air-cooled chillers rated at 40 °C ambient "
"(CH-1, CH-2), sequenced lead and lag by one controller. Identical modules mean one set of spares "
"position. The machines that make steam and cold water come in identical modules: " + pick(
"at launch two 500 kg/h boilers (B-1, B-2) for the 450 to 540 kg/h peak and two 250 kW "
"air-cooled chillers rated at 40 °C ambient (CH-1, CH-2) for ~391.5 kW, sequenced lead and "
"lag by one controller. Either boiler alone carries 93 to 111% of the steam demand; one "
"chiller out leaves ~64% of the cooling peak. The boiler bodies come through the Chinese "
"route and the compressor from a Chinese brand's Thai office (below). ",
"at launch two 500 kg/h boilers (B-1, B-2) for the 750 to 900 kg/h peak and three 250 kW "
"air-cooled chillers rated at 40 °C ambient (CH-1 to CH-3) for ~652.5 kW, sequenced lead "
"and lag by one controller; the boilers and the compressor come from Thai suppliers "
"(below). Five presses on two boilers leave no spare: a third module (B-3) is an RFQ option "
"outside the plan price, and without it a boiler fault costs about two presses until it is "
"fixed; one chiller out leaves ~77% of the cooling peak. ") +
"Identical modules mean one set of spares "
"and one service routine, N+1 later is one more module rather than a redesign, and the plant "
"never runs one oversized boiler at poor part load. Four boilers carry about eight presses with "
"one in reserve; four 250 kW chillers carry the five-press fleet with the fourth in reserve, and "
@@ -311,14 +343,17 @@ def blocks():
"weekdays) and 2.6037 THB/kWh off-peak, plus the Ft fuel adjustment (+0.1623 THB/kWh for "
"September to December 2026; it resets every four months) and reclaimable VAT. Two shifts put "
"about two thirds of process energy into peak hours: a blended ~3.81 THB/kWh before the demand "
"charge. For the five-press fleet the backbone is built for, without electric steam, that is "
"charge. " + pick("For the five-press fleet the backbone is built for", "For the five presses") +
", without electric steam, that is "
"roughly 4.5M to 6.8M THB a year before solar, 0.7M to 1.1M of it demand charge (estimates), on "
"an 800 to 1,000 kVA connection. Three design consequences:"),
B([
"**Biomass heat is far cheaper than electric steam** (below): the demand charge follows the "
"boiler's full-power draw, and the peak window covers 13 of the 16 production hours.",
"**The roof gets PV, not solar thermal.** Self-consumed PV is worth ~3.7 THB/kWh; it cannot "
"lower the demand charge, because the peak window runs to 22:00, long after sunset.",
"**The roof gets PV, not solar thermal.** Self-consumed PV is worth ~3.7 THB/kWh" + pick(
" of grid power displaced, less the PPA price the plant pays for it (below)", "") +
"; it cannot lower the demand charge, because the peak window runs to 22:00, long after "
"sunset.",
"**The battery is for ride-through, not peak shaving.** Charging off-peak and discharging at "
"peak earns ~70k THB a year for the 271 kWh stack, and it can hold demand down by only ~20 kW "
"(~30k THB a year; estimates). Its case is riding through grid dips and outages.",
@@ -327,8 +362,12 @@ def blocks():
KV([
["Rooftop PV", "~247 kWp on the 1,523 m² monopitch roof (425 modules of a generic 580 W "
"placeholder; no module chosen yet), ~335 to 360 MWh a year, ~25 to 35% of mature "
"two-shift use (1,000 to 1,500 MWh). Saves ~1.2M to 1.3M THB a year and pays back "
"in ~4.5 to 7 years at 25,000 to 35,000 THB/kWp (estimates)"],
"two-shift use (1,000 to 1,500 MWh). " + pick(
"Taken through a solar PPA (below): the plant pays the PPA price for this "
"power instead of buying the array, so its saving is the gap between that "
"price and the ~3.7 THB/kWh of grid power it displaces",
"Saves ~1.2M to 1.3M THB a year and pays back in ~4.5 to 7 years at 25,000 "
"to 35,000 THB/kWp (estimates)")],
["Canopies and the second building", "~40 kWp on the parking canopies (construction RFQ; ~54 "
"kWp if fully covered). A phase 2 building's roof adds "
"~251 kWp, ~498 kWp across both roofs"],
@@ -343,27 +382,39 @@ def blocks():
"burning-season dust"],
["Open checks", "Battery rack voltage against the chosen Deye model's window; Gobel safety "
"certifications (not published); EPC warranty on a mixed-vendor DC bus; yield "
"against PVGIS before committing"],
["Solar PPA (option)", "Instead of buying the PV and battery, an EPC owns and finances them and "
"the plant buys the power: ~12.3M THB less capital at the midpoint with "
"its contingency share, one of the four levers in section 8. The PPA "
"price is not quoted yet, and the BOI solar measure (section 7) rewards "
"the plant's own solar investment, so its tax value probably goes with "
"the array (to confirm with the BOI consultant)"],
"against PVGIS before committing" + pick("; the PPA offer itself, price and "
"terms", "")],
pick(["Solar PPA (this plan)", "An installer owns and finances the PV and the battery, and the "
"plant buys the power at a price still to quote (the calculator carries 3.0 THB/kWh, an "
"estimate, ~0.03M USD a year on the energy line). That keeps the PV EPC (USD 227k to "
"318k) and the battery (USD 42k to 62k) out of the capital round: ~10.7M THB less at the "
"midpoint, one of the six levers in section 8. The BOI solar measure (section 7) rewards "
"the plant's own solar investment, so its tax value very likely goes with the array (to "
"confirm with the BOI consultant). The PPA offer is asked against the specification "
"above"],
["Owned (this plan)", "The plant buys the array and the battery: rooftop PV EPC USD 227k "
"to 318k (7.5M to 10.5M THB) and the battery USD 42k to 62k (1.4M to 2.0M THB), "
"estimates, section 8. Owning them is what the BOI solar measure rewards (section 7). A "
"solar PPA (an installer owns and finances them, the plant buys the power at a price "
"still to quote) would take ~10.7M THB out of the capital round at the midpoint, but "
"very likely gives up that measure"]),
]),
H3("Steam: the open engineering choice"),
P("The boilers' fuel is still open; the modular bank works with either. There is no natural gas "
"pipeline in Northern Thailand, so gas means a bulk LPG tank on site with hazardous-storage "
"separation and licensing, and diesel means a fuel tank with price exposure. The two routes "
"without a fossil tank, compared for the same heat (~1,120 to 1,280 MWh a year at about 1.0 "
"million records, the top of the launch plant's range; estimates):"),
"million records, " + pick("the top of the plant's range", "the low end of the five presses' "
"range") + "; estimates):"),
T(["", "Electric boiler bank (~98%)", "Biomass boiler bank (~80%)"], [
["Price of heat", "~3.9 THB/kWh, plus the demand charge", "~0.5 to 0.9 THB/kWh at 1.35 to 2 "
"THB/kg delivered (reported market prices, October 2026; no supplier quote yet)"],
["Running cost, mature two shifts", "~5.2M to 6.0M THB a year, including 0.8M to 1.0M of extra "
"demand charge for the five-press bank", "~0.6M to 1.2M THB a year of fuel, plus handling "
"and ash"],
["Boiler package, 2 × 500 kg/h", "4.5M to 7M THB (Thai suppliers); the investment's baseline",
["Boiler package, 2 × 500 kg/h", pick("~2.8M to 5.5M THB through the Chinese route, the "
"plan's price (4.5M to 7M from Thai suppliers)",
"4.5M to 7M THB (Thai suppliers); the plan's price"),
"~6M to 10M THB, plus the fuel store"],
["Grid", "Peak ~950 to 1,330 kW: PEA Schedule 4, 1,250 to 1,600 kVA", "Unchanged, ~800 to "
"1,000 kVA"],
@@ -378,7 +429,9 @@ def blocks():
"land a biomass stack would be a hard sell, which favours electric or LPG there (section 6.1)."),
P("**Fuel.** A biomass bank burns roughly 350 to 400 tonnes of air-dry wood a year at about 1.0 "
"million records (~540 to 620 t as fresh chips, which is what the store and the monsoon stock are "
"sized for). Lamphun alone produces more than 900,000 t of farm residues a year (Maejo "
"sized for)" + pick("", ", up to ~550 t air-dry at 1.5 million (fuel follows records pressed, "
"not presses)") +
". Lamphun alone produces more than 900,000 t of farm residues a year (Maejo "
"University), so supply is not the constraint; price is. Reported prices follow diesel, so the "
"fuel contract gets a diesel clause and sources within ~50 km. The local price-setter is Ratch "
"Pathana's biomass buying centre at Pa Sak, Mueang Lamphun, which feeds a 9.6 MW cogeneration "
@@ -387,9 +440,19 @@ def blocks():
"that is worth only ~0.1M to 0.25M THB a year, so its value is supply security and the story "
"('records pressed with steam from our own trees'), not the fuel bill. Next step: written quotes "
"from Pa Sak and two or three chip suppliers, priced by moisture, before the boiler decision."),
P("**Where the boilers come from.** Chinese makers with Thai references (ZOZEN, Sitong, Fangkuai, "
"Taiguo) could supply the two modules for roughly 2.8M to 5.5M THB installed against 4.5M to 7M "
"from Thai suppliers, about 1.6M THB less at the midpoint (estimates from listings, not quotes). "
P("**Where the boilers come from.** " + pick(
"The plan buys the two modules through the Chinese route: boiler bodies from a Chinese maker "
"with Thai references (ZOZEN, Sitong, Fangkuai, Taiguo), installed with the feed tank, pumps, "
"header, controls and piping by a Thai boiler contractor, for roughly 2.8M to 5.5M THB "
"installed against 4.5M to 7M from Thai suppliers, about 1.6M THB less at the midpoint. The "
"compressor is a Chinese brand bought through its Thai office (Kaishan and Denair have one), "
"so service stays local; with it the route saves ~1.9M THB at the midpoint (estimates from "
"listings, not quotes). ",
"The plan buys the two modules and the compressor from Thai suppliers (4.5M to 7M THB "
"installed for the boilers). Chinese makers with Thai references (ZOZEN, Sitong, Fangkuai, "
"Taiguo) could supply the boilers for roughly 2.8M to 5.5M THB installed, about 1.6M THB "
"less at the midpoint, and with a Chinese compressor brand bought through its Thai office "
"~1.9M less (estimates from listings, not quotes): a step if quotes land high. ") +
"The specification is a 1.25 MPa design to ASME Section I with the S stamp; most Chinese packaged "
"electric units are rated 0.4 to 0.8 MPa and cannot deliver 10 bar. An imported boiler must meet "
"TIS, ASME, JIS, EN or an equivalent standard and be verified by a certification body registered "
@@ -425,10 +488,12 @@ def blocks():
CALL("Efficiency in one paragraph, for the investor", "Steam and cooling are built once as a "
"backbone and filled with identical modules as presses arrive; heat is recovered from the "
"flue gas, the condensate and the press returns before more is generated; the roof carries PV "
"worth a quarter to a third of mature electricity use, with a battery for ride-through; no "
"worth a quarter to a third of mature electricity use" + pick(" (through a solar PPA)", "") +
", with a battery for ride-through; no "
"process water is discharged; a fifth of the plastic is reclaimed; and biomass steam, if "
"chosen, costs a quarter to a tenth of electric steam. The same choices push the energy line "
"toward its low end, hedge Thai tariff rises, and convert into BOI tax value (section 7). They "
"toward its low end, hedge Thai tariff rises, and convert into BOI tax value" + pick(
" through the Smart and Sustainable Industry measure", "") + " (section 7). They "
"also make the plant's sustainability story true rather than claimed, which matters to the "
"labels it sells to."),
@@ -458,8 +523,8 @@ def blocks():
["Neighbours", "Agricultural", "Industrial", "A pharmaceutical facility under construction on "
"the same land"],
], widths_mm=[28, 44, 44, 54], font_pt=8.5),
P("**Galvanics now raises the bar for every site.** With the electroplating line in the launch "
"plant, a plot has to permit record pressing with a steam boiler **and** electroplating from day "
P("**Galvanics now raises the bar for every site.** With the electroplating line in the plan, a "
"plot has to permit record pressing with a steam boiler **and** electroplating from day "
"one, not in a later phase. That favours the industrial estate (licensing through the estate, "
"shared effluent treatment) and makes zoning the first check everywhere else."),
P("**Payap University** approached the project and is interested in leasing land next to a "
@@ -543,25 +608,77 @@ def blocks():
["Packaging and finished-goods warehouse", "~300 to 500 m²"],
["Utility rooms (boiler, compressor, chiller, electrical)", "~100 to 150 m²"],
["Offices, QC and listening room, archive, IT, entrance", "~150 to 200 m²"],
["Maintenance workshop and machine bay (crane-served)", "~100 to 150 m²"],
["Visitor corridor (glazed, ground level)", "~110 to 130 m²"],
["Maintenance workshop and machine bay (" + pick("crane-ready", "crane-served") + ")",
"~100 to 150 m²"],
[pick("Visitor corridor (glazed, ground level; built later, its strip kept free)",
"Visitor corridor (glazed, ground level)"), "~110 to 130 m²"],
["Circulation, walls, miscellaneous", "~150 to 250 m²"],
["**Total under roof**", "**~1,400 to 2,000 m²**, against 1,500 m² built"],
], widths_mm=[110, 60],
caption="Estimates. The boiler and chillers have since moved to the detached utility yard, which "
"frees floor the workshop and corridor take; water treatment is proposed in its own "
"building next to galvanics; cassette and CD-R duplication (~40 to 80 m² and ~20 to "
"40 m²) are not in the table yet. At the lower half of the table everything fits in "
"40 m²" + pick(", a later step in this plan", "") + ") are not in the table yet. " + pick(
"", "The press rows size one Duplex system and the Classic; the second Duplex "
"system needs its own bay on top (~110 m² at the calculator's floor figure, "
"estimate). ") +
"At the lower half of the table everything fits in "
"1,500 m²; at the upper half, finished goods move to a second building."),
IMG("production-hall-layout-sketch.png", 170, "Figure 3. Rough layout sketch of the 60 × 25 m hall "
"(October 2026): machine door and workshop at the ramp end, then mastering, galvanics, stamper "
"prep, material area and lab, the press hall, inspection, QC and packaging along the glazed "
"visitor corridor, with the 5 t crane runway over the production compartment up to the "
"warehouse fire wall. It still draws two Classic positions (the launch plant installs one) and "
"visitor corridor" + pick(" (built later in this plan)", "") + ", with the 5 t crane runway "
"over the production compartment up to the warehouse fire wall. " + pick(
"It still draws two Classic positions (the plan installs one)",
"It still draws one Duplex system and two Classic positions (the plan installs two Duplex "
"systems and one Classic)") + " and "
"puts reception and the cutting room under the crane's travel, a conflict the Payap scenario "
"model resolves with a separate office building. All positions are estimates."),
P("Figure 4 shows the same plant as the calculator draws it for " + label() + ": the ground floor of a "
"whole site with the press hall cut open, the machines this plan installs and the free positions it "
"keeps for growth."),
IMG(pick("renders/calculator/plan-a-iso-gf.png", "renders/calculator/plan-b-iso-gf.png"), 170,
"Figure 4. The plant at a glance in the plant and business plan calculator, " + pick(
"Plan A preset: Duplex system 1 and the Classic in a press hall laid out for five Duplex bays "
"and four Classic positions, boiler modules B-1/B-2 and chillers CH-1/CH-2 (the free yard "
"positions are marked), the frame crane-ready with the crane rented",
"Plan B preset: Duplex systems 1 and 2 and the Classic in a press hall laid out for five Duplex "
"bays and four Classic positions, boiler modules B-1/B-2 and chillers CH-1 to CH-3 (the free "
"yard positions are marked), the 5 t crane and the cassette room") +
". Schematic render (docs/fleet-calculator.html, also at cnxvinyl.lol/demos/fleet-calculator/) of a "
"generic site after the Payap scenario model and the utility yard of scale.md, not the Mueang Chi "
"parcel of Figure 2; positions and envelopes are estimates, not to scale where the vendors publish "
"no footprint."),
H3("Crane, workshop and visitor corridor"),
B([
B(pick([
"**A crane-ready frame, with the crane rented at first.** The frame, the runway and the machine "
"door are built for a 5 t overhead crane (single-girder, ~24 m span, inverter drives, radio "
"remote) over the whole production compartment, roughly 40 to 48 m of the 60 m, stopping at "
"the fire wall to the finished-goods warehouse. For the installations a mobile crane is hired, "
"and the crane itself is bought later if machine moves and maintenance lifts make it worth it. "
"The building is shaped for it from the start: a frame designed for crane loads, no "
"full-height cross walls in the crane zone (rooms there are lidded boxes, with removable "
"hatches where heavy kit goes in), and the cutting room kept outside it, away from the frame's "
"vibration. 5 t covers the heaviest known lift (a Newbilt HRP 12 press, 1,350 kg) with margin "
"until Newbilt states the Classic's weight; 3.2 t is the alternative price.",
"**A machine door** of ~4.5 × 5.0 m at the ramp end, opened a few times a year. Until a crane "
"is bought, the hired crane sets each machine on skates at the door threshold; with the crane, "
"a truck reverses up the ramp into the machine bay and the crane lifts the machine off the bed "
"inside.",
"**A maintenance workshop** of ~100 to 150 m² beside it, where a bought crane would park: a "
"service bay for one press-sized machine, benches, a hydraulic hose crimper, a spares store "
"tracked in ERPNext, and a hot-work corner, held at negative pressure so its dust never "
"reaches the presses. Newbilt service comes from Germany and Pheenix from Sweden; spares on "
"the shelf are the uptime lever.",
"**A glazed visitor corridor, built later.** The plan runs without public tours at first, but "
"the route is designed in: the strip along the car-park wall stays free and the stations "
"follow the process order, from the cutting-room window to packaging. Built, it is ~45 to 55 m "
"long and ~2.4 m clear, with its own filtered air at slight positive pressure and acoustic "
"glazing that brings the 80 to 90 dB(A) near the presses down to roughly 40 to 50 dB(A) "
"(estimates), so a guide talks without a headset and visitors need no PPE; a 1:12 accessible "
"ramp serves the entrance. Until it is built there are no public tours, and the tour route and "
"the Payap programmes start later.",
], [
"**A 5 t overhead crane** (single-girder, ~24 m span, inverter drives, radio remote) runs over "
"the whole production compartment, roughly 40 to 48 m of the 60 m, and stops at the fire wall "
"to the finished-goods warehouse. Machines are moved in, out and around without hiring a mobile "
@@ -584,13 +701,14 @@ def blocks():
"headset and visitors need no PPE; a 1:12 accessible ramp serves the entrance. Tours for "
"artists, labels, investors and schools can run several times a day without stopping "
"production.",
]),
])),
H3("Utility yard and water-treatment building"),
T(["Detached utility yard (decided October 2026)", "Size (estimate)"], [
["Boiler hall, four 500 kg/h module positions (B-1 and B-2 at launch)", "~162 m² (18 × 9 m), "
"6.0 m high"],
["Biomass fuel store", "42 m²"],
["Chiller compound, open and screened, four pads (CH-1 and CH-2 at launch)", "~135 m² (12.5 × "
["Chiller compound, open and screened, four pads (" + pick("CH-1 and CH-2", "CH-1 to CH-3") +
" at launch)", "~135 m² (12.5 × "
"10.8 m)"],
["Cooling pump and heat-exchanger room", "~40 m² (8 × 5 m)"],
["Flue stack", "14 m"],
@@ -626,10 +744,16 @@ def blocks():
"plot's narrowing southern end with a two-bay sawtooth roof carrying ~251 kWp and a 20 m yard "
"between the two for fire separation and shared loading; coverage stays at 39% of the deed area. "
"It is where finished goods move to free production floor, where pressing capacity can double, "
"or where a CD replication line would go if that option is chosen (section 4.9). Where the "
"second Duplex system stands on the Mueang Chi footprint is not drawn yet; the Payap scenario "
"model draws the five-press fleet; its press hall is now planned for Duplex systems (five Duplex "
"bays and four Classic positions), because the plant focuses on special pressings."),
"or where a CD replication line would go if that option is chosen (section 4.10). **The press "
"hall** is planned for Duplex systems, because the plant focuses on special pressings and "
"specials run only on the Duplex: five Duplex bays and four Classic positions (~73/27 by floor, "
"estimate). " + pick(
"This plan installs one Duplex system and one Classic; growth adds Duplex systems first, into "
"bays whose floor, utility positions and ring-main tees are kept from the start. Where the "
"second Duplex system would stand on the Mueang Chi footprint is not drawn yet; ",
"This plan installs two Duplex systems and one Classic at launch; growth adds Duplex systems "
"first. Where the second Duplex system stands on the Mueang Chi footprint is not drawn yet; ") +
"the Payap scenario model draws the five-press fleet."),
H3("What the construction RFQ asks"),
P("The budget-level construction RFQ, with quantities from the parametric model, asks contractors "
"for: the shell rate per m² at the insulated-panel specification (not a bare shed); heavy-duty "
@@ -641,21 +765,29 @@ def blocks():
"PV, air conditioning, boilers, chillers and tanks, sprinklers, fit-out and the PEA transformer, "
"and asks whether permit drawings for the building permit and the factory licence are included."),
H3("What the building costs, and what is not known"),
T(["Block (launch plant)", "USD", "THB", "Basis"], [
T(["Block", "USD", "THB", "Basis"], [
["Building ~1,500 m² plus civil and site works", "650k to 1,100k", "21.4M to 36.3M",
"estimate at 12,000 to 20,000 THB/m² for Thai pre-engineered steel to the insulated-panel "
"specification, plus ~20% site works"],
["Overhead crane, runway, frame premium, machine door", "97k to 227k", "3.2M to 7.5M", "estimate"],
pick(["Crane-ready frame, runway and machine door; mobile crane rented for the installations",
"39k to 91k", "1.3M to 3.0M", "estimate: 40% of the crane block (USD 97k to 227k); the "
"crane is bought later if needed"],
["Overhead crane, runway, frame premium, machine door", "97k to 227k", "3.2M to 7.5M",
"estimate"]),
["Maintenance workshop and machine bay fit-out", "30k to 76k", "1.0M to 2.5M", "estimate; a "
"workshop lathe and CNC mill not priced"],
["Visitor corridor and accessible entrance", "67k to 148k", "2.2M to 4.9M", "estimate; "
"building it later is a lever worth ~4.1M THB"],
pick(["Visitor corridor and accessible entrance", "built later", "built later", "USD 67k to "
"148k (2.2M to 4.9M THB) when built, estimate; not in the plan price"],
["Visitor corridor and accessible entrance", "67k to 148k", "2.2M to 4.9M", "estimate; "
"building it later would take ~3.6M THB out at the midpoint"]),
["Utility yard for four boiler and four chiller modules", "73k to 122k", "2.4M to 4.0M",
"estimate at the building rate"],
["Water-treatment building next to galvanics", "52k to 87k", "1.7M to 2.9M", "estimate at the "
"building rate"],
["**Together**", "**~0.97M to 1.76M**", "**~32M to 58M**", "sum of the blocks, before the 15% "
"contingency (section 8)"],
pick(["**Together**", "**~0.84M to 1.48M**", "**~28M to 49M**", "sum of the blocks; the plan "
"carries no contingency (section 8)"],
["**Together**", "**~0.97M to 1.76M**", "**~32M to 58M**", "sum of the blocks; the plan "
"carries no contingency (section 8)"]),
], widths_mm=[50, 26, 26, 68], font_pt=8.5),
P("The single largest unknown is the ground. The Mueang Chi parcel is likely soft former paddy, and "
"a piled slab can add several hundred to 1,000+ THB/m² across the building, 4,387 m² of paving "
@@ -663,9 +795,13 @@ def blocks():
"before any real number, and the building RFQ with a soil test is one of the four requests that "
"settle the budget. Also open: the crane's hook height under the 7.0 m eave; the archive's "
"mobile shelving (to quote); the valved branches and feeders for the empty utility positions; "
"and the fire-water volume, which the hydraulic design and the warehouse racking height set. "
"Renting a crane for the installations while the frame stays crane-ready would save ~3.7M THB, "
"but that is a scope cut toward the 180M THB case, not part of the plan."),
"and the fire-water volume, which the hydraulic design and the warehouse racking height set. " +
pick("Renting a crane for the installations while the frame, runway and machine door stay "
"crane-ready takes ~3.2M THB out at the midpoint, one of the six levers; the 5 t crane itself "
"is USD 30k to 76k supplied and installed (estimate) when it is bought.",
"Renting a mobile crane for the installations while the frame, runway and machine door stay "
"crane-ready would take ~3.2M THB out at the midpoint (estimate): a step if quotes land "
"high, not part of the plan.")),
H2("6.3 Safety, security and the irreplaceable"),
P("Worker safety is a founding priority on equal footing with the environmental commitments. The "
@@ -686,7 +822,8 @@ def blocks():
"THB a head a year for insurance, ~2,500 for the check-up plus ~1,500 for risk-factor tests, and "
"workwear ~USD 9k a year at ~20 staff."),
P("Physical security is zoned: production, galvanics, chemical storage, the metal archive, IT, "
"shipping and the visitor corridor each get badge or biometric access with logs; CCTV at "
"shipping and " + pick("(once built) ", "") + "the visitor corridor each get badge or biometric "
"access with logs; CCTV at "
"entrances, perimeter, dock, production, chemicals and archive under a PDPA-compliant retention "
"policy. Two things are irreplaceable and get their own protection: **the metal archive** (a "
"destroyed father means recutting and re-plating a release; fire-rated room, climate control in "
@@ -709,7 +846,9 @@ def blocks():
"pressing is basic plastic consumer-goods manufacturing (incentive Group B): no corporate income "
"tax holiday on the core activity, but the full non-tax package and machinery duty exemption. "
"The tax value is engineered on top through measures where this project happens to be strong, so "
"the application is pitched on solar, automation and technology content, not on pressing plastic "
"the application is pitched on " + pick("automation, technology content and energy efficiency",
"solar, automation and technology content") +
", not on pressing plastic "
"discs. The research behind this dates from July 2026, BOI revises its measures roughly every "
"year, and the exact activity sub-code needs confirmation by a BOI-registered consultant before "
"filing."),
@@ -718,7 +857,9 @@ def blocks():
"(Germany, Sweden, the UK, Australia, Japan, China). Machinery imported duty-free is also "
"exempt from VAT at import (Revenue Department answer on BOI's FAQ, checked October 2026). The "
"investment blocks assume promotion: without it, ~5% duty on ~2.3M USD of imported machinery "
"(~0.11M USD) plus ~0.17M USD of import VAT, reclaimed only later (estimates)."],
"(~0.11M USD) plus ~0.17M USD of import VAT, reclaimed only later (estimates for the " +
pick("full equipment list; this plan imports less at first",
"three-press equipment list; the second Duplex system adds to both") + ")."],
["100% foreign ownership and land privileges", "Overrides Foreign Business Act restrictions "
"for the promoted activity. The land-ownership privilege is unused under the lease strategy."],
["Visas and work permits via the One Stop Service", "Foreign commissioning engineers and the "
@@ -728,7 +869,12 @@ def blocks():
["Solar and battery measure (Announcement 2/2568, April 2025)", "CIT exemption based on the "
"solar investment; PV modules, inverters, battery and battery inverters, and mounting are "
"eligible, capped at THB 12M, 30M or 40M of investment per MW depending on investment type. "
"It rewards a plant-owned array, which matters if the solar PPA lever is used (section 5.4)."],
"It rewards a plant-owned array. " + pick(
"This plan takes the PV and the battery through a solar PPA, so the installer owns them "
"and the plant very likely gives up this measure (to confirm with the BOI consultant; "
"section 5.4).",
"This plan buys the ~247 kWp array and the 271 kWh battery, so their cost is the base of "
"the exemption (section 5.4).")],
["Smart and Sustainable Industry measure (Announcement 15/2565, refreshed July 2025)",
"Rewards automation, smart machinery and energy efficiency, typically 3 years of CIT exemption "
"capped around 50% of the qualifying upgrade spend. The automatic Classic, inline inspection, "
@@ -744,7 +890,9 @@ def blocks():
"machinery and raw materials lives, from the first capex invoice."),
P("**Process:** file via the e-Investment system and present at an analyst meeting. BOI quotes "
"about 40 working days to a decision for projects under THB 200M and 60 to 90 working days for "
"larger tiers; at ~161M to 292M THB the launch plant sits around that line, so the consultant "
"larger tiers; at " + pick("~127M to 226M THB with the ramp-up reserve (~177M at the midpoint)",
"~162M to 286M THB with the ramp-up reserve (~224M at the midpoint)") +
" the plan sits around that line, so the consultant "
"confirms which applies. In practice it is roughly 4 to 6 months end to end to the certificate; "
"the company is incorporated under it; machinery is imported within a window commonly 30 months "
"from issuance; full operation is due by about 36 months. The Northern Economic Corridor "
@@ -754,7 +902,7 @@ def blocks():
H2("7.2 Factory licence, galvanics and boilers"),
P("BOI promotion does not replace the factory licence (Ror.Ngor. 4), hazardous-substance "
"registration for the plating chemistry, wastewater permitting or the boiler rules. **Galvanics "
"is now in the launch plant, so the electroplating line, its chemistry and its zero-discharge "
"is in the plant from launch, so the electroplating line, its chemistry and its zero-discharge "
"effluent system are in the first factory licence application**, not a later amendment. The "
"earlier plan to keep galvanics out of the first licence to protect the schedule no longer "
"applies. Effluent is the most likely regulatory friction point regardless of BOI, and it now "
@@ -772,8 +920,9 @@ def blocks():
"engineer; the construction RFQ asks whether contractors include them (shell prices usually do "
"not), and stormwater attenuation may be a permit condition.",
]),
P("**Boilers (DIW rules).** The Ministerial Regulation on boilers B.E. 2549 and the matching "
"notification on boiler safety of the same year apply to every module, Thai or imported: a design "
P("**Boilers (DIW rules).** The Ministerial Regulation on boilers B.E. 2549 and the Ministry of "
"Industry notification on boiler safety of the same year apply to every module, Thai or "
"imported: a design "
"to TIS or an international standard (ASME, JIS, EN or equivalent) checked and certified by a "
"DIW-registered certification body or licensed engineer; for an imported boiler, verification by "
"a registered certification body and the manufacturer's data report, design and inspection "
@@ -781,11 +930,18 @@ def blocks():
"reported to DIW within 30 days; **a licensed boiler controller on site**; and **inspection at "
"least once a year**. The relief for small once-through units does not apply at ~10.5 bar (our "
"reading), and the labour-side regulation of 2021 adds licensed-engineer installation and "
"testing and a feedwater standard. A Chinese boiler built to the Chinese GB code would rest on "
"'or equivalent' with no precedent found, hence the ASME specification. DIW has announced a "
"testing and a feedwater standard. " + pick(
"**This plan's two boiler bodies come from a Chinese maker, so they take the imported-boiler "
"route of the notification:** verification by a registered certification body with the full "
"dossier, and an ASME Section I design at 1.25 MPa with the S stamp, because a boiler built "
"to the Chinese GB code would rest on 'or equivalent' with no precedent found. ",
"The plan's modules come from Thai suppliers to the same ASME specification; a Chinese "
"boiler built to the Chinese GB code would rest on 'or equivalent' with no precedent found. ") +
"DIW has announced a "
"revision of the boiler, pressure-vessel and refrigeration rules, so they are rechecked before "
"the RFQ, and a certification body is engaged before any boiler order."),
P("**Other permits and duties:** the same 2021 labour regulation covers the overhead crane (a "
P("**Other permits and duties:** the same 2021 labour regulation covers the overhead crane" +
pick(" once one is bought", "") + " (a "
"crane-industry summary puts cranes above 3 t on an engineer inspection every three months; to "
"confirm against the text before the capacity is chosen); hazardous-substance registration and "
"locked, inventoried storage for silver nitrate and nickel salts; the occupational health "
@@ -797,9 +953,13 @@ def blocks():
"operation) start at the certificate, and the margin on them is consumed by one scenario: "
"filing early and then finding the site does not work. Verify the chosen plot's zoning, "
"including plating, first.",
"**Scope.** Cassette and CD-R duplication go into the application from the start. CD "
"replication would need new activity codes, which cannot be added casually afterwards, so the "
"investor's decision on CD (section 4.9) is needed before the filing date.",
"**Scope.** " + pick(
"Cassette and CD-R duplication come later in this plan; whether they still go into the "
"first application (their machines then due inside its import window) or into a later "
"amendment is a question for the consultant. ",
"Cassette and CD-R duplication go into the application from the start. ") +
"CD replication would need new activity codes, which cannot be added casually afterwards, so the "
"investor's decision on CD (section 4.10) is needed before the filing date.",
"**Sequencing.** The plan's rule is that no machinery purchase order precedes the certificate, "
"because duty exemption is not retroactive. But the exemption attaches at importation, not at "
"contract signature. If equipment can be ordered with a deposit while the application is in "