OpenNIT

Quelltext des aktuellen Standes

Fassung 1.1.1

create.php

17 KB
<?php
$this->layout('layouts/main', [
    'page_title' => 'Neuer Vertrag',
    'current_route' => 'contracts',
    'full_width' => true,
    'breadcrumbs' => [],
    'extra_css'   => ['/assets/css/company-search.css'],
    'extra_js'    => ['/assets/js/company-search.js'],
]);

// Der Vorschlag, eine unbekannte Firma anzulegen, setzt das Adressbuch und
// das Recht voraus, es zu pflegen.
$kannFirmaAnlegen = ($modules['contacts'] ?? false) && $this->hasCapability('manage_contacts');
?>

<div class="cf-wrap">

    <!-- Content Header -->
    <div class="content-header">
        <div>
            <h1><?= $this->te('Neuer Vertrag') ?></h1>
            <ol class="breadcrumb">
                <li class="breadcrumb-item"><a href="/"><?= $this->te('Home') ?></a></li>
                <li class="breadcrumb-item"><a href="/contracts"><?= $this->te('Verträge') ?></a></li>
                <li class="breadcrumb-item active"><?= $this->te('Neuer Vertrag') ?></li>
            </ol>
        </div>
    </div>

    <!-- FORM: zwei Spalten -->
    <form action="/contracts" method="POST" class="cf-layout" id="contractForm">
        <input type="hidden" name="_csrf" value="<?= $this->csrf() ?>">

        <!-- ─── LINKE SPALTE ──────────────────────────────────── -->
        <div class="cf-main">

            <section class="cf-card">
                <h2 class="cf-section-head">
                    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
                    <?= $this->te('Stammdaten') ?>
                </h2>
                <div class="cf-card-body">
                    <div class="cf-row-2">
                        <div class="cf-field">
                            <label for="company_id"><?= $this->te('Firma') ?> <span class="cf-req">*</span></label>
                            <select id="company_id" name="company_id" required <?= $kannFirmaAnlegen ? 'data-create-company' : '' ?>>
                                <option value=""><?= $this->te('Firma ausw&auml;hlen&hellip;') ?></option>
                                <?php foreach ($companies as $c): ?>
                                    <option value="<?= $c['id'] ?>" <?= ($preselected_company ?? 0) == $c['id'] ? 'selected' : '' ?>>
                                        <?= $this->e($c['name']) ?><?php if (!empty($c['customer_number'])): ?> · <?= $this->e($c['customer_number']) ?><?php endif; ?>
                                    </option>
                                <?php endforeach; ?>
                            </select>
                        </div>
                        <div class="cf-field">
                            <label for="contract_number"><?= $this->te('Vertragsnummer') ?></label>
                            <input type="text" id="contract_number" name="contract_number" maxlength="100" placeholder="z.B. V-2026-001">
                        </div>
                    </div>
                    <div class="cf-row-2">
                        <div class="cf-field">
                            <label for="category_id"><?= $this->te('Kategorie') ?></label>
                            <select id="category_id" name="category_id">
                                <option value=""><?= $this->te('Keine Kategorie') ?></option>
                                <?php foreach ($categories ?? [] as $cat): ?>
                                    <option value="<?= $cat['id'] ?>">
                                        <?= $this->e($cat['name']) ?>
                                    </option>
                                <?php endforeach; ?>
                            </select>
                        </div>
                        <div class="cf-field">&nbsp;</div>
                    </div>
                    <div class="cf-field">
                        <label for="title"><?= $this->te('Bezeichnung') ?> <span class="cf-req">*</span></label>
                        <input type="text" id="title" name="title" required maxlength="255" placeholder="<?= $this->te('z.B. Wartungsvertrag Server') ?>">
                    </div>
                    <div class="cf-field">
                        <label for="description"><?= $this->te('Beschreibung / Leistungsumfang') ?></label>
                        <textarea id="description" name="description" rows="4" placeholder="<?= $this->te('Leistungsbeschreibung, was ist im Vertrag enthalten&hellip;') ?>"></textarea>
                    </div>
                </div>
            </section>

            <section class="cf-card">
                <h2 class="cf-section-head">
                    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>
                    <?= $this->te('Laufzeit &amp; K&uuml;ndigung') ?>
                </h2>
                <div class="cf-card-body">
                    <div class="cf-row-2">
                        <div class="cf-field">
                            <label for="start_date"><?= $this->te('Vertragsbeginn') ?></label>
                            <input type="date" id="start_date" name="start_date">
                        </div>
                        <div class="cf-field">
                            <label for="end_date"><?= $this->te('Vertragsende') ?></label>
                            <input type="date" id="end_date" name="end_date">
                        </div>
                    </div>
                    <div class="cf-row-2">
                        <div class="cf-field">
                            <label for="cancellation_period_months"><?= $this->te('K&uuml;ndigungsfrist (Monate)') ?></label>
                            <input type="number" id="cancellation_period_months" name="cancellation_period_months" min="0" max="60" placeholder="z.B. 3">
                            <span class="cf-hint"><?= $this->te('Erinnerung 1 Monat vor Fristbeginn') ?></span>
                        </div>
                        <div class="cf-field">
                            <label>&nbsp;</label>
                            <label class="cf-toggle">
                                <input type="checkbox" name="auto_renew" value="1">
                                <span class="cf-toggle-track"></span>
                                <span class="cf-toggle-label">
                                    <strong><?= $this->te('Automatische Verl&auml;ngerung') ?></strong>
                                    <small><?= $this->te('Vertrag verl&auml;ngert sich automatisch') ?></small>
                                </span>
                            </label>
                        </div>
                    </div>
                    <div class="cf-row-2">
                        <div class="cf-field">
                            <label for="renewal_period_months"><?= $this->te('Verl&auml;ngerung um (Monate)') ?></label>
                            <input type="number" id="renewal_period_months" name="renewal_period_months" min="1" max="120" placeholder="<?= $this->te('Standard: 12') ?>">
                            <span class="cf-hint"><?= $this->te('Nur bei automatischer Verl&auml;ngerung &ndash; um wie viel sich das Enddatum verschiebt, wenn nicht gek&uuml;ndigt wird.') ?></span>
                        </div>
                        <div class="cf-field"><label>&nbsp;</label></div>
                    </div>
                </div>
            </section>

            <section class="cf-card">
                <h2 class="cf-section-head">
                    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
                    <?= $this->te('Verantwortung &amp; Notizen') ?>
                </h2>
                <div class="cf-card-body">
                    <div class="cf-row-2">
                        <div class="cf-field">
                            <label for="status"><?= $this->te('Status') ?></label>
                            <select id="status" name="status" onchange="cfToggleCancellationDate(this.value)">
                                <option value="active"><?= $this->te('Aktiv') ?></option>
                                <option value="future"><?= $this->te('Zuk&uuml;nftig') ?></option>
                                <option value="cancelled"><?= $this->te('Gek&uuml;ndigt') ?></option>
                            </select>
                            <small style="color:var(--gray-500);"><?= $this->te('Bei Startdatum in der Zukunft wird &quot;Aktiv&quot; automatisch auf &quot;Zuk&uuml;nftig&quot; gesetzt.') ?></small>
                        </div>
                        <div class="cf-field">
                            <label for="responsible_user_id"><?= $this->te('Verantwortlich') ?></label>
                            <select id="responsible_user_id" name="responsible_user_id">
                                <option value=""><?= $this->te('Nicht zugewiesen') ?></option>
                                <?php foreach ($users as $u): ?>
                                    <option value="<?= $u['id'] ?>"><?= $this->e($u['display_name']) ?></option>
                                <?php endforeach; ?>
                            </select>
                        </div>
                    </div>
                    <div class="cf-field" id="cancellation-date-field" style="display:none;">
                        <label for="cancellation_date"><?= $this->te('K&uuml;ndigungsdatum') ?> <span style="color:var(--red-600);">*</span></label>
                        <input type="date" id="cancellation_date" name="cancellation_date">
                        <span class="cf-hint"><?= $this->te('Datum ab dem der Vertrag offiziell endet (leer = heute)') ?></span>
                    </div>
                    <div class="cf-field">
                        <label for="notify_scope"><?= $this->te('Fristerinnerung senden an') ?></label>
                        <select id="notify_scope" name="notify_scope">
                            <option value="all"><?= $this->te('Alle mit Vertragszugriff') ?></option>
                            <option value="responsible"><?= $this->te('Nur Verantwortliche/r') ?></option>
                        </select>
                        <span class="cf-hint"><?= $this->te('Wer wird bei Kündigungsfrist/Vertragsende benachrichtigt? „Nur Verantwortliche/r" fällt auf „alle" zurück, wenn niemand zugewiesen ist.') ?></span>
                    </div>
                    <div class="cf-field">
                        <label for="notes"><?= $this->te('Interne Notizen') ?></label>
                        <textarea id="notes" name="notes" rows="3" placeholder="<?= $this->te('Ansprechpartner beim Anbieter, besondere Konditionen&hellip;') ?>"></textarea>
                    </div>
                </div>
            </section>

        </div><!-- /cf-main -->

        <!-- ─── RECHTE SPALTE (Sidebar) ───────────────────────── -->
        <aside class="cf-sidebar">

            <section class="cf-card">
                <h2 class="cf-section-head">
                    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><line x1="12" y1="1" x2="12" y2="23"/><path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/></svg>
                    <?= $this->te('Kosten') ?>
                </h2>
                <div class="cf-card-body">
                    <div class="cf-row-2">
                        <div class="cf-field">
                            <label for="cost_amount"><?= $this->te('Betrag Brutto ({cur})', ['cur' => $this->currency()]) ?></label>
                            <input type="number" id="cost_amount" name="cost_amount" step="0.01" min="0" placeholder="0,00">
                        </div>
                        <div class="cf-field">
                            <label for="cost_amount_net"><?= $this->te('Betrag Netto ({cur})', ['cur' => $this->currency()]) ?></label>
                            <input type="number" id="cost_amount_net" step="0.01" min="0" placeholder="0,00">
                            <span class="cf-hint"><?= $this->te('Rechnet Brutto &uuml;ber den MwSt-Satz hoch') ?></span>
                        </div>
                    </div>
                    <div class="cf-row-2">
                        <div class="cf-field">
                            <label for="tax_rate"><?= $this->te('MwSt-Satz (%)') ?></label>
                            <input type="number" id="tax_rate" name="tax_rate" step="0.01" min="0" max="100" placeholder="z.B. 19">
                            <span class="cf-hint"><?= $this->te('Leer lassen = keine MwSt') ?></span>
                        </div>
                        <div class="cf-field">
                            <label for="cost_interval"><?= $this->te('Intervall') ?></label>
                            <select id="cost_interval" name="cost_interval">
                                <option value="monthly"><?= $this->te('Monatlich') ?></option>
                                <option value="quarterly"><?= $this->te('Quartalsweise') ?></option>
                                <option value="yearly"><?= $this->te('J&auml;hrlich') ?></option>
                                <option value="one_time"><?= $this->te('Einmalig') ?></option>
                            </select>
                        </div>
                    </div>
                    <div class="cf-field">
                        <label for="first_payment_date"><?= $this->te('Erste Zahlung') ?></label>
                        <input type="date" id="first_payment_date" name="first_payment_date">
                        <span class="cf-hint"><?= $this->te('F&uuml;r F&auml;lligkeitsberechnung') ?></span>
                    </div>
                </div>
            </section>

            <!-- Live-Vorschau (erscheint wenn Betrag eingegeben) -->
            <section class="cf-card cf-preview-card" id="costPreviewCard" style="display:none;">
                <h2 class="cf-section-head cf-head-accent">
                    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>
                    <?= $this->te('Kostenvorschau') ?>
                </h2>
                <div class="cf-card-body">
                    <div class="cf-preview-grid">
                        <div class="cf-tile cf-tile-blue">
                            <span><?= $this->te('Monatl. Brutto') ?></span>
                            <strong id="prev-monthly-gross">–</strong>
                        </div>
                        <div class="cf-tile cf-tile-green">
                            <span><?= $this->te('Monatl. Netto') ?></span>
                            <strong id="prev-monthly-net">–</strong>
                        </div>
                        <div class="cf-tile cf-tile-indigo">
                            <span><?= $this->te('J&auml;hrl. Brutto') ?></span>
                            <strong id="prev-yearly-gross">–</strong>
                        </div>
                        <div class="cf-tile cf-tile-teal">
                            <span><?= $this->te('J&auml;hrl. Netto') ?></span>
                            <strong id="prev-yearly-net">–</strong>
                        </div>
                    </div>
                    <div id="prev-next-payment" class="cf-due" style="display:none;">
                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="13" height="13"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>
                        <?= $this->te('N&auml;chste F&auml;lligkeit:') ?> <strong id="prev-next-payment-text"></strong>
                    </div>
                </div>
            </section>

            <div class="cf-actions">
                <button type="submit" class="cf-btn cf-btn-primary">
                    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16"><polyline points="20 6 9 17 4 12"/></svg>
                    <?= $this->te('Vertrag erstellen') ?>
                </button>
                <a href="/contracts" class="cf-btn cf-btn-cancel"><?= $this->te('Abbrechen') ?></a>
            </div>

        </aside>
    </form>
</div>

<style>
<?php include __DIR__ . '/_contract_form.css.php'; ?>
</style>
<script>
<?php include __DIR__ . '/_contract_form.js.php'; ?>
function cfToggleCancellationDate(status) {
    var field = document.getElementById('cancellation-date-field');
    var input = document.getElementById('cancellation_date');
    if (!field) return;
    if (status === 'cancelled') {
        field.style.display = '';
        if (input) input.required = true;
    } else {
        field.style.display = 'none';
        if (input) { input.required = false; input.value = ''; }
    }
}
</script>

<?php if ($kannFirmaAnlegen): ?>
<?= $this->render('partials/_company_quick_create') ?>
<?php endif; ?>