72 lines
3.1 KiB
TypeScript
72 lines
3.1 KiB
TypeScript
import { z } from 'zod'
|
||
import type { ResolutionTemplate } from './index.js'
|
||
import {
|
||
baseDocument,
|
||
escapeHtml,
|
||
formatDateDe,
|
||
formatEur,
|
||
renderMembers,
|
||
} from './shared.js'
|
||
|
||
const schema = z.object({
|
||
fiscalYear: z.string().min(4),
|
||
distributableProfit: z.coerce.number().nonnegative(),
|
||
distributedAmount: z.coerce.number().nonnegative(),
|
||
retainedAmount: z.coerce.number().nonnegative(),
|
||
paymentDate: z.string().min(8),
|
||
notes: z.string().optional(),
|
||
})
|
||
|
||
export const profitDistribution: ResolutionTemplate = {
|
||
key: 'profit_distribution',
|
||
titleDe: 'Beschluss zur Gewinnverwendung',
|
||
titleEn: 'Profit distribution',
|
||
descriptionDe:
|
||
'Gesellschafterbeschluss über die Verwendung des Jahresergebnisses gemäß § 29 GmbHG.',
|
||
schema,
|
||
fields: [
|
||
{ key: 'fiscalYear', labelDe: 'Geschäftsjahr', labelEn: 'Fiscal year', type: 'text', required: true },
|
||
{ key: 'distributableProfit', labelDe: 'Bilanzgewinn (EUR)', labelEn: 'Distributable profit (EUR)', type: 'currency', required: true },
|
||
{ key: 'distributedAmount', labelDe: 'Auszuschüttender Betrag (EUR)', labelEn: 'Amount to distribute (EUR)', type: 'currency', required: true },
|
||
{ key: 'retainedAmount', labelDe: 'Gewinnvortrag (EUR)', labelEn: 'Retained amount (EUR)', type: 'currency', required: true },
|
||
{ key: 'paymentDate', labelDe: 'Auszahlungsdatum', labelEn: 'Payment date', type: 'date', required: true },
|
||
{ key: 'notes', labelDe: 'Anmerkungen', labelEn: 'Notes', type: 'textarea' },
|
||
],
|
||
render: ({ values, company, members, createdBy, date }) => {
|
||
const v = schema.parse(values)
|
||
const body = `
|
||
<h1>Gesellschafterbeschluss</h1>
|
||
<div class="meta">
|
||
${escapeHtml(company.name)}${company.registryNo ? `, ${escapeHtml(company.registryNo)}` : ''}<br/>
|
||
${company.address ? escapeHtml(company.address) + '<br/>' : ''}
|
||
Beschlussdatum: ${escapeHtml(formatDateDe(date))}
|
||
</div>
|
||
<div class="section">
|
||
<h2>Gegenstand des Beschlusses</h2>
|
||
<p>Verwendung des Jahresergebnisses für das Geschäftsjahr
|
||
<strong>${escapeHtml(v.fiscalYear)}</strong> gemäß § 29 GmbHG.</p>
|
||
</div>
|
||
<div class="section">
|
||
<h2>Beschluss</h2>
|
||
<ul>
|
||
<li>Bilanzgewinn: <strong>${escapeHtml(formatEur(v.distributableProfit))}</strong></li>
|
||
<li>Auszuschüttender Betrag: <strong>${escapeHtml(formatEur(v.distributedAmount))}</strong></li>
|
||
<li>Gewinnvortrag: <strong>${escapeHtml(formatEur(v.retainedAmount))}</strong></li>
|
||
<li>Auszahlung am: <strong>${escapeHtml(formatDateDe(v.paymentDate))}</strong></li>
|
||
</ul>
|
||
<p>Die Ausschüttung erfolgt im Verhältnis der Geschäftsanteile.</p>
|
||
${v.notes ? `<p><em>${escapeHtml(v.notes)}</em></p>` : ''}
|
||
</div>
|
||
<div class="section">
|
||
<h2>Gesellschafter</h2>
|
||
${renderMembers(members)}
|
||
</div>
|
||
<div class="section signature">
|
||
<div class="line">${escapeHtml(createdBy.displayName)}<br/><small>${escapeHtml(createdBy.email)}</small></div>
|
||
<div class="line">Ort, Datum</div>
|
||
</div>
|
||
`
|
||
return baseDocument('Beschluss – Gewinnverwendung', body)
|
||
},
|
||
}
|