diff --git a/README.md b/README.md index 3cea990..cfafcfc 100644 --- a/README.md +++ b/README.md @@ -184,7 +184,8 @@ The detail lives in dedicated documents: feeding it, each station counted from the galvanics cycle times; plus the money a year: revenue (standard, specials, title services), PVC, labels, sleeves, jackets, cartons, lacquers, plating chemistry, - electricity and steam, loaded labour, overheads, EBITDA, depreciation + electricity and steam, labour from base salaries with social security, + on-costs and health care for all staff, overheads, EBITDA, depreciation and payback, with the revenue model's adverse, central and favourable cases and USD, THB or EUR; every assumption is editable, with its source, and a scenario can be shared by link diff --git a/docs/finance/revenue-model.md b/docs/finance/revenue-model.md index 408d991..1df3828 100644 --- a/docs/finance/revenue-model.md +++ b/docs/finance/revenue-model.md @@ -509,8 +509,18 @@ security, overtime, bonus and PPE: That is 3.7M–5.4M THB/yr (113k–163k USD), or **0.08–0.16 USD per record** over 1.0–1.5M records. Mastering and cutting engineers are excluded — they are title-services labour, not per-record, and admin, sales and -logistics sit in overheads below. A cutting engineer costs about -**50,000 THB a month** (team figure, October 2026). +logistics sit in overheads below. A cutting engineer earns about +**50,000 THB a month** base salary (team figure, October 2026). + +**On top of the ×1.3 (October 2026):** the company gives every member of +staff, office included, group health insurance and a yearly check-up, +plus the occupational checks the law requires for risk-factor work (see +[worker safety](../worker-safety.md)): about 17,500 THB a head a year at +planning prices, ~20 people at the start fleet, so ~0.35M THB a year. The +×1.3 itself is roughly the employer's social security (5 % up to a 17,500 +THB ceiling since January 2026) plus ~25 % for overtime, bonus and PPE. +The [press fleet calculator](../fleet-calculator.html) costs labour from +base salaries in that way. ## Margin per record diff --git a/docs/fleet-calculator.html b/docs/fleet-calculator.html index 9f5445a..8150abc 100644 --- a/docs/fleet-calculator.html +++ b/docs/fleet-calculator.html @@ -334,8 +334,13 @@ document.documentElement.setAttribute("data-theme",t);})(); the plant. Lacquer blanks (70 EUR each) and the cutting engineer (50,000 THB a month) are team figures; shipping cartons have no figure on file and are an estimate. Missing as the revenue model lists: indirect labour, freight, inventory, effluent, commission, styli, extra galvanics units' capex.

-

Not scaled here: admin, sales and logistics (in the overheads line); cover for leave - and sickness.

+

Labour. Base salaries per role (revenue-model.md, its loaded rates divided by 1.3; the cutting + engineer a team figure), plus the employer's 5 % social security up to the 17,500 THB ceiling, 25 % + for overtime, bonus and PPE, and the company's health care for every member of staff, office + included: group health insurance, a yearly check-up, and the risk-factor tests Thai law requires + for the press floor, galvanics and maintenance (worker-safety.md).

+

Not scaled here: admin, sales and logistics wages (in the overheads line); cover for + leave and sickness.

Sources in the CNX Vinyl planning repository: equipment/pressing-line.md, equipment/newbilt/ (Duplex site requirements V14, offer 240620-04, 2026 flyers), equipment/galvanics.md (cycle times per step; the stamper line counts each station from them, @@ -450,15 +455,24 @@ grp("Energy", [ ["heatPrice", "Steam heat from biomass", 0.7, "THB/kWh", "doc", "biomass.md: 0.5 to 0.9 at 1.35 to 2 THB/kg delivered"], ["steamKWh", "Heat per kg of steam", 0.68, "kWh/kg", "est", "Estimate: 10 bar saturated steam from ~80 °C feed water"], ]); -grp("Labour (THB a month a head, loaded ×1.3)", [ - ["wageOp", "Press and finishing operator", 19500, "THB", "doc", "revenue-model.md labour build-up"], - ["wageQC", "QC", 26000, "THB", "doc", "revenue-model.md"], - ["wageMaint", "Maintenance", 32500, "THB", "doc", "revenue-model.md"], - ["wageGalv", "Galvanics", 32500, "THB", "doc", "revenue-model.md"], - ["wageCut", "Cutting engineer", 50000, "THB", "user", "Team figure, October 2026 (revenue-model.md), taken as the full monthly cost"], +grp("Labour: base salaries, THB a month", [ + ["salOp", "Press and finishing operator", 15000, "THB", "doc", "revenue-model.md: ~19,500 loaded at ×1.3"], + ["salQC", "QC", 20000, "THB", "doc", "revenue-model.md: ~26,000 loaded"], + ["salMaint", "Maintenance", 25000, "THB", "doc", "revenue-model.md: ~32,500 loaded"], + ["salGalv", "Galvanics", 25000, "THB", "doc", "revenue-model.md: ~32,500 loaded"], + ["salCut", "Cutting engineer", 50000, "THB", "user", "Team figure, October 2026 (revenue-model.md)"], + ["officeHeads", "Admin, sales and logistics staff", 4, "people", "doc", "scale.md: 3 to 5; their wages sit in the overheads, they count here for health care"], ["qcPerShift", "QC inspectors per shift", 1, "", "est", "Estimate; scale.md: 1 to 2 QC"], ["pressPerTech", "Presses per maintenance technician (at least 2)", 8, "", "est", "Estimate; scale.md: 2 in maintenance for the start fleet"], ]); +grp("Labour: on-costs and health care", [ + ["ssRate", "Employer social security", 5, "% of salary", "doc", "Social Security Act, section 33: 5 % up to the wage ceiling (worker-safety.md)"], + ["ssCap", "Social security wage ceiling", 17500, "THB a month", "doc", "Raised from 15,000 on 1 January 2026, so at most 875 THB a month (worker-safety.md)"], + ["otherOn", "Overtime, bonus, PPE and other on-costs", 25, "% of salary", "doc", "With social security this is the revenue model's ×1.3 at 15,000 THB"], + ["healthIns", "Group health insurance (inpatient and outpatient)", 15000, "THB a head a year", "doc", "worker-safety.md: AXA SME plans 9,394 to 18,006 THB at 25 staff (CheckDi, October 2026); local plans 8,000 to 12,000"], + ["checkup", "Annual health check-up", 2500, "THB a head a year", "est", "Estimate for an age mix; Rajavej Chiang Mai 2026 programmes 1,290 to 5,990 THB by age (worker-safety.md)"], + ["occCheck", "Risk-factor tests (hearing, lungs, metals)", 1500, "THB a head a year", "est", "Estimate; required yearly for press floor, galvanics and maintenance (Ministerial Regulation B.E. 2547, worker-safety.md)"], +]); grp("Planned plant, for the checks", [ ["boiler", "Steam boiler", 400, "kg/h", "doc", "scale.md: sized for one Duplex system"], ["chiller", "Chiller", 250, "kW", "doc", "scale.md: sized for one Duplex system"], @@ -608,12 +622,20 @@ function econ(r, b) { add("energy", "Electricity", t2u((elecMWh - pvMWh) * 1000 * A.kwhPrice + demandKW * A.demandPrice * 12), `${f0(elecMWh - pvMWh)} MWh from the grid after ${f0(pvMWh)} MWh roof PV; ~${f0(demandKW)} kW demand`); add("energy", "Steam heat (biomass)", t2u(heatMWh * 1000 * A.heatPrice), `${f0(steamT)} t of steam, ${f0(heatMWh)} MWh of heat`); - const h = headsOf(r), wage = (n, w) => t2u(n * w * 12), ppl = n => n + (n === 1 ? " person" : " people"); - add("lab", "Press operators and finishing", wage(h.ops, A.wageOp), ppl(h.ops)); - add("lab", "QC", wage(h.qc, A.wageQC), ppl(h.qc)); - add("lab", "Maintenance", wage(h.maint, A.wageMaint), ppl(h.maint)); - add("lab", "Galvanics", wage(h.galv, A.wageGalv), ppl(h.galv)); - add("lab", "Cutting engineers", wage(h.cut, A.wageCut), ppl(h.cut)); + const h = headsOf(r), ppl = n => n + (n === 1 ? " person" : " people"); + let base = 0, ss = 0; + for (const [l, n, sal] of [["Press operators and finishing", h.ops, A.salOp], ["QC", h.qc, A.salQC], + ["Maintenance", h.maint, A.salMaint], ["Galvanics", h.galv, A.salGalv], ["Cutting engineers", h.cut, A.salCut]]) { + add("lab", l, t2u(n * sal * 12), `${ppl(n)} at ${f0(sal)} THB a month`); + base += n * sal * 12; ss += n * Math.min(sal, A.ssCap) * A.ssRate / 100 * 12; + } + add("lab", "Employer social security", t2u(ss), `${f1(A.ssRate)} % of salary up to ${f0(A.ssCap)} THB a month`); + add("lab", "Overtime, bonus, PPE", t2u(base * A.otherOn / 100), `${f1(A.otherOn)} % of base salaries`); + h.prod = h.ops + h.qc + h.maint + h.galv + h.cut; h.office = Math.max(0, Math.round(A.officeHeads)); + h.all = h.prod + h.office; h.exposed = h.ops + h.galv + h.maint; + add("lab", "Health insurance, all staff", t2u(h.all * A.healthIns), `${ppl(h.all)}, office included, at ${f0(A.healthIns)} THB a year`); + add("lab", "Health check-ups, all staff", t2u(h.all * A.checkup + h.exposed * A.occCheck), + `yearly for everyone, plus risk-factor tests for ${ppl(h.exposed)} on the press floor, in galvanics and maintenance`); const sum = gs => L.filter(l => gs.includes(l[0])).reduce((a, l) => a + l[2], 0); const direct = L.reduce((a, l) => a + l[2], 0), contrib = rev - direct, ebitda = contrib - A.overheads; const capex = A.capexBase + (r.D - 2) * A.capexD + (r.C - 1) * A.capexC, depr = capex / Math.max(1, A.deprYears); @@ -735,7 +757,7 @@ function render() { PR("Splatter and specials", e.revSpec, `${big(r.sp)} at ${unit(S.priceStd + S.premSpec)}`); PR("Title services", e.revTitle, `${f0(r.titles)} titles at ${money(S.titleFee)}`); PR("Revenue", e.rev, "", true); - const GRP = [["Materials, packaging, upkeep", ["mat", "pack", "maint"]], ["Stamper making", ["metal"]], ["Energy", ["energy"]], ["Labour, loaded wages", ["lab"]]]; + const GRP = [["Materials, packaging, upkeep", ["mat", "pack", "maint"]], ["Stamper making", ["metal"]], ["Energy", ["energy"]], ["Labour and health care", ["lab"]]]; for (const [t, gs] of GRP) { PG(t); e.L.filter(l => gs.includes(l[0])).forEach(l => PR(l[1], l[2], l[3])); } PG("Result"); PR("Direct cost", e.direct, "everything above", true); @@ -758,7 +780,9 @@ function render() { R("Maintenance technicians", e.heads.maint, `one per ${f0(A.pressPerTech)} presses, at least 2 (estimate)`); R("Galvanics operators (day work)", r.galv, `${f1(r.partsDay)} parts a day at about ${f0(A.galvRate)} per person (OMS)`); R("Cutting engineers (day work)", e.heads.cut, "one per lathe (estimate)"); - R("Production headcount", e.heads.ops + e.heads.qc + e.heads.maint + e.heads.galv + e.heads.cut, "admin, sales and logistics sit in overheads; add cover for leave"); + R("Production headcount", e.heads.prod, "add cover for leave"); + R("Admin, sales and logistics", e.heads.office, "wages in the overheads (scale.md 3 to 5)"); + R("All staff, with health insurance and yearly check-ups", e.heads.all, `risk-factor tests for ${e.heads.exposed} (press floor, galvanics, maintenance)`); G("Machines"); R("HRP 12 presses (Duplex)", 2 * r.D, ""); R("Classic automatic presses", r.C, "extruder built in; trimming not stated by Newbilt"); diff --git a/docs/worker-safety.md b/docs/worker-safety.md index 6cdb4d7..4ecf3ad 100644 --- a/docs/worker-safety.md +++ b/docs/worker-safety.md @@ -25,6 +25,41 @@ commitments: in [crane, workshop and tours](crane-workshop-tours.md). - **Visitors** never share the floor's hazards: tours run in a glazed corridor with its own air and no PPE requirement. +- **Health care for all staff (decided October 2026).** On top of the + statutory social security, the company provides every member of staff, + office included, with group health insurance (inpatient and outpatient) + and a yearly health check-up. Staff in risk-factor work also get the + occupational checks Thai law requires, which the general check-up does + not replace: + - **The legal minimum.** The Ministerial Regulation on health check-ups + of employees (B.E. 2547, 2004) covers work with hazardous chemicals, + heat, noise and similar risk factors: a check within 30 days of + starting such work, then at least once a year, by a physician trained + in occupational medicine, physical and mental, with the records kept + until two years after the job ends + ([summary](https://www.thailandlawoffice.com/legal-articles/266), + [text](https://natlex.ilo.org/dyn/natlex2/natlex2/files/download/96400/THA96400%20Eng.pdf)). + Here that is the press floor (steam heat, noise), galvanics (nickel + salts, silver nitrate, acids) and maintenance; hearing, lung function + and metal tests are the likely panel, for the occupational physician + to set. + - **Planning costs** (checked October 2026, no quote yet): group health + insurance about 8,000 to 12,000 THB a head a year for local plans + ([Thailand Starter Kit](https://thailandstarterkit.com/business/group-health-insurance)), + AXA's SME plans 9,394, 14,925 and 18,006 THB at 25 staff + ([CheckDi](https://checkdi.com/th/business-insurance/group-health?lg=th)); + the plan uses ~15,000. Check-ups at Rajavej Chiang Mai cost 1,290 THB + (age 18 to 30), 1,790 (31 to 40) and 3,290 to 5,990 (over 40) in 2026 + ([programmes](https://rajavejchiangmai.com/en/pagekage/health-checkup-program-2026)); + the plan uses ~2,500 a head plus ~1,500 for the risk-factor tests + (estimates). + - **Social security**, for reference: the employer pays 5 % of salary + up to a ceiling raised from 15,000 to 17,500 THB a month on 1 January + 2026, so at most 875 THB a month a head + ([Sprout](https://sprout.co.th/en/blogs/thailand-social-security-contribution-2026-section-33)). + + The [press fleet calculator](fleet-calculator.html) costs all of this per + head with the fleet's staffing. Safety infrastructure (training program, clean-room specification, decontamination workflow) will be planned alongside the equipment, not after