// donor-act.jsx — Акт за шаблоном донора (PIN / Екоклуб). // Формується з виконаних задач проєкту (коментар = рядок акта, нотатка = опис), // + скріншоти у «Описовому звіті». Виконавець — ФОП, Замовник — ГО, без ПДВ. // Завантажувати ПІСЛЯ invoice-template.jsx (потрібен window.moneyInWords) і image-slot.js. (function () { const MONTHS_GEN = ["січня", "лютого", "березня", "квітня", "травня", "червня", "липня", "серпня", "вересня", "жовтня", "листопада", "грудня"]; const fullDateUA = (iso) => { if (!iso) return null; const d = new Date(iso + "T00:00:00"); if (isNaN(d)) return iso; return `«${String(d.getDate()).padStart(2, "0")}» ${MONTHS_GEN[d.getMonth()]} ${d.getFullYear()} р.`; }; const ddmm = (iso) => { if (!iso) return ""; const d = new Date(iso + "T00:00:00"); if (isNaN(d)) return iso; return `${String(d.getDate()).padStart(2, "0")}.${String(d.getMonth() + 1).padStart(2, "0")}`; }; const money2 = (n) => Number(n || 0).toLocaleString("uk-UA", { minimumFractionDigits: 2, maximumFractionDigits: 2 }); // ════════════ БІЛДЕР АКТА ════════════ function DonorActBuilder({ project, onClose, onOpenDoc }) { const seed = project.actSeed || {}; const SYS = window.SYS_DATE || "2026-05-29"; const [hdr, setHdr] = React.useState({ no: seed.no || "1", date: seed.date || SYS, place: seed.place || "Рівне", contractNo: seed.contractNo || project.number || "", contractDate: seed.contractDate || (project.contract && project.contract.date) || project.start || "", amount: seed.amount != null ? String(seed.amount) : "", }); const up = (k, v) => setHdr(p => ({ ...p, [k]: v })); // Послуги — з виконаних задач проєкту const doneTasks = (project.tasks || []).filter(t => t.status === "done"); const [items, setItems] = React.useState( doneTasks.map(t => ({ id: t.id, include: true, text: t.title, date: t.actDate || "", desc: t.note || "" })) ); const setItem = (id, patch) => setItems(prev => prev.map(it => it.id === id ? { ...it, ...patch } : it)); const addItem = () => setItems(prev => [...prev, { id: "ai-" + Math.random().toString(36).slice(2, 6), include: true, text: "", date: "", desc: "" }]); const removeItem = (id) => setItems(prev => prev.filter(it => it.id !== id)); React.useEffect(() => { const onKey = (e) => e.key === "Escape" && onClose(); window.addEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey); }, [onClose]); const chosen = items.filter(it => it.include && it.text.trim()); const build = () => { const partner = window.getNgoPartner(project.partner); onOpenDoc({ no: hdr.no, dateISO: hdr.date, place: hdr.place, contractNo: hdr.contractNo, contractDateISO: hdr.contractDate, amount: Number(hdr.amount) || 0, execEntity: project.execEntity, partner, services: chosen.map(it => ({ id: it.id, text: it.text.trim(), date: it.date, desc: it.desc.trim(), slotId: "actshot-" + project.id + "-" + it.id })), }); }; return (
Акт за шаблоном донора · {window.getDonor(project.donor)?.name}
Послуги тягнуться з виконаних задач — відредагуйте за потреби
up("no", e.target.value)} />
up("date", e.target.value)} />
up("contractNo", e.target.value)} />
up("contractDate", e.target.value)} />
up("place", e.target.value)} />
up("amount", e.target.value)} placeholder="напр. 12466.20" />
Перелік послуг ({chosen.length})
{items.map(it => (
setItem(it.id, { text: e.target.value })} placeholder="Опис послуги (рядок акта)" style={{ flex: 1 }} /> setItem(it.id, { date: e.target.value })} style={{ width: 150 }} title="Дата послуги" />
setItem(it.id, { desc: e.target.value })} placeholder="Опис для звіту (під скріншот)" style={{ width: "100%", marginTop: 6, fontSize: 12.5 }} />
))}
У друкованій формі буде Акт + Реквізити сторін + Описовий звіт, де під кожною послугою — місце для скріншота (перетягніть зображення). Виконавець — {window.COMPANY_FOP?.shortName}, Замовник — {window.getNgoPartner(project.partner)?.name}, без ПДВ.
); } window.DonorActBuilder = DonorActBuilder; // ════════════ ДРУКОВАНА ФОРМА ════════════ function DonorActPrintDoc({ model, onClose }) { React.useEffect(() => { const onKey = (e) => e.key === "Escape" && onClose(); window.addEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey); }, [onClose]); if (!model) return null; const fop = window.COMPANY_FOP || {}; const r = (model.partner && model.partner.requisites) || {}; const cust = model.partner || {}; const words = model.amount > 0 ? window.moneyInWords(model.amount) : ""; const doPrint = () => window.print(); return (
Акт наданих послуг № {model.no} · шаблон донора
{/* ── СТОРІНКА 1: АКТ ── */}

Акт прийому-передачі наданих послуг №{model.no}

за Договором № {model.contractNo || "____"} від {fullDateUA(model.contractDateISO) || "«__» ________ 20__ р."}
м. {model.place}, Україна{fullDateUA(model.dateISO)}

Ми, що нижче підписалися, представник Замовника – {r.fullName || cust.name} в особі {(r.directorRole || "керівника").toLowerCase()} {r.director || "________"}, що діє на підставі {r.basis || "Статуту"} (далі – Замовник), з одного боку та фізична особа-підприємець {fop.directorFull} (далі – Виконавець), що діє на підставі запису про проведення державної реєстрації в Єдиному державному реєстрі юридичних осіб, фізичних осіб-підприємців та громадських формувань № {fop.edrRecord || "________"} від {fop.edrDate ? fullDateUA(fop.edrDate).replace(/[«»]/g, "").replace(" р.", " р.") : "________"} з іншого боку, разом «Сторони», уклали акт про те, що за умовами Договору № {model.contractNo || "____"} від {fullDateUA(model.contractDateISO) || "____"} Виконавцем були надані Замовнику послуги згідно умов договору:

    {model.services.map(s => (
  • {s.text}{s.date ? `, ${ddmm(s.date)}` : ""}
  • ))}

Детальний перелік та опис виконаних робіт наведено в Описовому звіті про надані послуги до Акту здачі-приймання наданих послуг № {model.no} від {fullDateUA(model.dateISO)} за Договором № {model.contractNo || "____"} від {fullDateUA(model.contractDateISO) || "____"}.

Вартість послуг за Актом виконаних робіт становить {money2(model.amount)} грн ({words}) без ПДВ.

Підписанням даного Акту Сторони засвідчують, що Виконавець надав послуги відповідно до умов Договору, а Замовник прийняв та оплатив. Сторони претензій одна до одної не мають.

{/* Реквізити сторін */}
Реквізити сторін:
Виконавець
Фізична особа-підприємець {fop.directorFull}
{fop.address}
ІПН: {fop.edrpou}
тел. {fop.phone}
IBAN {fop.iban}
в {fop.bank}, МФО {fop.mfo}
E-mail: {fop.email}
Фізична особа-підприємець
{fop.directorSign || "М.І. Підкапка"}
б.п.
Замовник
{r.fullName || cust.name}
{r.address}
{r.addressFact &&
Фактична адреса: {r.addressFact}
}
ЄДРПОУ: {r.edrpou || cust.edrpou}
IBAN: {r.iban}
в {r.bank}
E-mail: {r.email}
{r.directorRole || "Керівник"}
{r.directorShort || "________"}
м.п.
{/* ── СТОРІНКА 2+: ОПИСОВИЙ ЗВІТ ── */}

Описовий звіт про надані послуги

до Акту здачі-приймання наданих послуг № {model.no} від {fullDateUA(model.dateISO)}
за Договором № {model.contractNo || "____"} від {fullDateUA(model.contractDateISO) || "____"}

У рамках послуг за Актом здачі-приймання наданих послуг № {model.no} від {fullDateUA(model.dateISO)} мною, {fop.directorFull}, були надані наступні послуги:

{model.services.map((s, i) => (
• {s.text}{s.date ? `, ${ddmm(s.date)}.` : "."}
{s.desc &&
{s.desc}
}
))}
); } window.DonorActPrintDoc = DonorActPrintDoc; function DActStyles() { return ( ); } })();