Files
magico.prototype/prototype/invoice/app-invoice-recurring-add.php
T

497 lines
29 KiB
PHP

<?php
$enablePrototypeComments = true;
include '../../header-invoice.php';
?>
<div class="container-fluid flex-grow-1 container-p-y">
<!-- Header & Form Buttons -->
<div class="d-flex flex-column flex-md-row justify-content-between align-items-start align-items-md-center mb-4 gap-3">
<div class="d-flex flex-column justify-content-center">
<h4 class="mb-1 text-body"><i class="bx bx-repeat me-2 text-primary"></i>Nowy Szablon Faktury Cyklicznej</h4>
<p class="text-muted mb-0">Skonfiguruj reguły automatycznego generowania i wystawiania dokumentów abonamentowych</p>
</div>
<div class="d-flex align-content-center flex-wrap gap-2">
<a href="app-invoice-recurring-list.php" class="btn btn-label-secondary">Anuluj</a>
<button type="submit" form="recurringForm" class="btn btn-primary"><i class="bx bx-save me-1"></i> Zapisz szablon cyklu</button>
</div>
</div>
<form id="recurringForm" onsubmit="return false">
<!-- Top Section: Status & Cycle Rules -->
<div class="row mb-4">
<!-- Card 1: Harmonogram i Reguły Cyklu -->
<div class="col-lg-6 mb-4 mb-lg-0">
<div class="card mb-4">
<div class="card-header border-bottom py-3 d-flex justify-content-between align-items-center bg-label-primary">
<h6 class="card-title m-0 text-primary"><i class="bx bx-calendar-repeat me-2"></i>Harmonogram i Reguły Cyklu</h6>
<!-- Global Master Switch ON/OFF -->
<div class="d-flex align-items-center gap-2 me-4">
<span class="fw-bold small text-body">Status cyklu:</span>
<div class="form-check form-switch m-0 d-flex align-items-center">
<input class="form-check-input mt-0 me-3" type="checkbox" id="masterStatusToggle" checked style="width: 2.5em; height: 1.3em; cursor: pointer;">
<label class="form-check-label mb-0 ms-1" for="masterStatusToggle" style="cursor: pointer;">
<span class="badge bg-label-success" id="statusLabelText">AKTYWNY (ON)</span>
</label>
</div>
</div>
</div>
<div class="card-body pt-3">
<div class="mb-3">
<label class="form-label fw-bold">Nazwa własna cyklu / Szablonu</label>
<input type="text" class="form-control" placeholder="np. Abonament IT - Usługi Chmurowe (ABC Logistics)" value="Abonament IT i Wsparcie Techniczne">
<small class="text-muted">Nazwa widoczna w rejestrze cykli dla ułatwienia identyfikacji.</small>
</div>
<!-- Przebudowany Konfigurator Cyklu -->
<div class="card shadow-none border bg-lighter mb-3">
<div class="card-body p-3">
<h6 class="fw-bold mb-3 text-primary"><i class="bx bx-time-five me-1"></i>Konfiguracja Powtarzania</h6>
<!-- Data rozpoczęcia & Cykl rozliczeń -->
<div class="row g-2 mb-3">
<div class="col-md-6">
<label class="form-label fw-bold">Data rozpoczęcia</label>
<input type="text" class="form-control date-picker" id="startDateInput" value="2026-08-01">
<small class="text-muted">Dzień wystawienia pierwszej faktury.</small>
</div>
<div class="col-md-6">
<label class="form-label fw-bold">Cykl rozliczeń</label>
<select class="form-select" id="cycleUnitSelect">
<option value="miesiac" selected>Miesiąc</option>
<option value="rok">Rok</option>
<option value="dzien">Dzień</option>
</select>
<small class="text-muted">Jednostka czasu dla powtarzania.</small>
</div>
</div>
<!-- Interwał & Obowiązuje do -->
<div class="row g-2 mb-3">
<div class="col-md-6">
<label class="form-label fw-bold">Interwał (Co ile cykli)</label>
<div class="input-group">
<span class="input-group-text">Co</span>
<input type="number" class="form-control" value="1" min="1" id="intervalInput">
<span class="input-group-text" id="intervalUnitText">miesiąc</span>
</div>
<small class="text-muted">np. "1" = co miesiąc, "3" = kwartalnie, "12" = co rok.</small>
</div>
<div class="col-md-6">
<label class="form-label fw-bold">Obowiązuje do</label>
<input type="text" class="form-control date-picker" id="endDateInput" placeholder="RRRR-MM-DD (Bezterminowo)">
<small class="text-muted">Data, po której system automatycznie wyłączy cykl.</small>
</div>
</div>
<!-- Informacyjna ramka dynamicznego opisu -->
<div class="alert alert-primary mb-0 p-2 d-flex align-items-center" role="alert">
<i class="bx bx-info-circle fs-4 me-2"></i>
<span class="small" id="summaryDescription">
Faktura będzie generowana <strong>co 1 miesiąc</strong>, rozpoczynając od dnia <strong>01.08.2026 r.</strong> bezterminowo.
</span>
</div>
</div>
</div>
<hr class="my-3">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="emailAutoSend" checked>
<label class="form-check-label fw-bold" for="emailAutoSend">Automatyczna wysyłka e-mail do kontrahenta</label>
<div class="text-muted small">Wyślij e-mail z podpiętą fakturą w PDF zaraz po automatycznym wystawieniu (zgodnie z <b>globalnym szablonem e-mail</b> zdefiniowanym w Ustawieniach Systemowych).</div>
</div>
</div>
</div>
</div>
<!-- Card 2: Kontrahent - Nabywca i Odbiorca -->
<div class="col-lg-6">
<div class="card mb-4">
<div class="card-header border-bottom py-3 d-flex justify-content-between align-items-center">
<h6 class="card-title m-0"><i class="bx bx-user-check me-2 text-primary"></i>Kontrahent (Nabywca i Odbiorca)</h6>
</div>
<div class="card-body pt-3">
<!-- Nabywca -->
<div class="mb-3">
<label class="form-label fw-bold">Nabywca (Główny kontrahent / Płatnik)</label>
<div class="card shadow-none border bg-lighter">
<div class="card-body p-3 d-flex justify-content-between align-items-center">
<div>
<h6 class="mb-1 text-primary fw-bold">ABC Logistics Sp. z o.o.</h6>
<p class="mb-0 small text-muted">NIP: PL 865 223 11 90 • ul. Warszawska 45, 00-001 Warszawa</p>
<p class="mb-0 small text-muted">E-mail do faktur: ksiegowosc@abclogistics.pl</p>
</div>
<button type="button" class="btn btn-outline-primary btn-sm"><i class="bx bx-refresh me-1"></i> Zmień</button>
</div>
</div>
</div>
<!-- Switches for Recipient and Extra -->
<div class="d-flex flex-column gap-2 mb-3">
<label class="form-check form-switch m-0">
<input class="form-check-input" type="checkbox" id="recipientToggle">
<span class="form-check-label fw-bold">Wskaż innego Odbiorcę / Miejsce dostawy</span>
</label>
</div>
<!-- Odbiorca Container (Domyślnie ukryty) -->
<div class="card shadow-none border mb-3 bg-white d-none" id="recipientBox">
<div class="card-header py-2 bg-label-secondary d-flex justify-content-between align-items-center">
<span class="small fw-bold"><i class="bx bx-buildings me-1"></i>Dane Odbiorcy (np. Szkoła, Oddział, Filia)</span>
<button type="button" class="btn btn-xs btn-outline-secondary">Wybierz z listy</button>
</div>
<div class="card-body p-3">
<div class="mb-2">
<label class="form-label small text-muted mb-1">Nazwa Odbiorcy</label>
<input type="text" class="form-control form-control-sm" value="ABC Logistics - Oddział Magazynowy Stalowa Wola">
</div>
<div class="row g-2">
<div class="col-8">
<label class="form-label small text-muted mb-1">Adres Odbiorcy</label>
<input type="text" class="form-control form-control-sm" value="ul. Przemysłowa 12, 37-450 Stalowa Wola">
</div>
<div class="col-4">
<label class="form-label small text-muted mb-1">NIP Odbiorcy (opcja)</label>
<input type="text" class="form-control form-control-sm" placeholder="Opcjonalny NIP">
</div>
</div>
</div>
</div>
<div class="row g-2">
<div class="col-6">
<label class="form-label small text-uppercase fw-bold text-muted">Miejsce wystawienia</label>
<input type="text" class="form-control" value="Stalowa Wola">
</div>
<div class="col-6">
<label class="form-label small text-uppercase fw-bold text-muted">Osoba wystawiająca</label>
<input type="text" class="form-control" value="Bartłomiej Banaczyk">
</div>
</div>
</div>
</div>
<!-- Kontakt i powiadomienia -->
<div class="card mb-4">
<div class="card-body">
<h6 class="card-title text-primary mb-3">Kontakt i powiadomienia</h6>
<div class="mb-3">
<label class="form-label small text-uppercase text-muted fw-bold">Email kontaktowy</label>
<input type="email" class="form-control" value="ksiegowosc@abclogistics.pl">
</div>
<div class="mb-3">
<label class="form-label small text-uppercase text-muted fw-bold">Wysyłka faktur e-mail</label>
<div class="form-check form-switch mb-2">
<input class="form-check-input" type="checkbox" id="autoEmail" checked>
<label class="form-check-label" for="autoEmail">Automatyczna wysyłka wg profilu:</label>
</div>
<select class="form-select form-select-sm">
<option value="1">Profil: Standardowy (Termin 30 dni)</option>
<option value="2">Profil: Szybki (Termin 3 dni)</option>
<option value="3">Profil: Tylko przypomnienia po terminie</option>
</select>
</div>
<div class="mb-3">
<label class="form-label small text-uppercase text-muted fw-bold">Numer SMS</label>
<input type="text" class="form-control" placeholder="+48 ...">
</div>
<div class="mb-0">
<label class="form-label small text-uppercase text-muted fw-bold">Powiadomienia SMS</label>
<select class="form-select">
<option value="" selected>Wybierz opcję</option>
<option value="1">Wyślij powiadomienie SMS po wygenerowaniu</option>
<option value="0">Brak powiadomień</option>
</select>
</div>
</div>
</div>
<!-- Ostatni dokument -->
<div class="card mb-4 mb-lg-0">
<div class="card-body">
<h6 class="card-title text-primary mb-3">Ostatni dokument</h6>
<p class="text-muted mb-0 small">Brak dokumentów</p>
</div>
</div>
</div>
</div>
<!-- Section 2: Document Settings & Variables -->
<div class="card mb-4">
<div class="card-header border-bottom py-3">
<h6 class="card-title m-0"><i class="bx bx-slider-alt me-2 text-primary"></i>Ustawienia Dokumentów Generowanych</h6>
</div>
<div class="card-body pt-3">
<div class="row g-3">
<div class="col-md-3">
<label class="form-label fw-bold">Rodzaj dokumentu</label>
<select class="form-select border-primary text-primary fw-bold">
<option value="faktura" selected>Faktura VAT</option>
<option value="proforma">Proforma</option>
</select>
</div>
<div class="col-md-3">
<label class="form-label fw-bold">Waluta & Język</label>
<div class="input-group">
<select class="form-select">
<option value="PLN" selected>PLN (zł)</option>
<option value="EUR">EUR (€)</option>
<option value="USD">USD ($)</option>
</select>
<select class="form-select">
<option value="PL" selected>PL</option>
<option value="EN">EN</option>
</select>
</div>
</div>
<div class="col-md-3">
<label class="form-label fw-bold">Forma płatności</label>
<select class="form-select">
<option value="przelew" selected>Przelew bankowy</option>
<option value="gotowka">Gotówka</option>
<option value="split">Split Payment (MPP)</option>
</select>
</div>
<div class="col-md-3">
<label class="form-label fw-bold">Termin płatności</label>
<div class="input-group">
<input type="number" class="form-control" value="14">
<span class="input-group-text">dni</span>
</div>
</div>
</div>
<div class="row g-3 mt-1">
<div class="col-md-3">
<label class="form-label fw-bold">Konto bankowe</label>
<select class="form-select">
<option value="1">Main PLN: 89 1050 ... 4491</option>
<option value="2">EUR IBAN: PL 12 1050 ... 9901</option>
</select>
</div>
<div class="col-md-4">
<label class="form-label fw-bold">Data sprzedaży</label>
<select class="form-select">
<option value="issue_date" selected>Zgodna z datą wystawienia</option>
<option value="last_day_prev_month">Ostatni dzień poprzedniego miesiąca</option>
<option value="first_day_curr_month">Pierwszy dzień bieżącego miesiąca</option>
</select>
</div>
<div class="col-md-5">
<label class="form-label fw-bold">Komentarz / Uwagi na fakturze (dla klienta)</label>
<input type="text" class="form-control" value="Opłata abonamentowa za miesiąc {MIESIAC} {ROK}. Dziękujemy za współpracę!">
<div class="mt-1">
<span class="badge bg-label-secondary me-1" style="cursor:pointer;">+ {MIESIAC}</span>
<span class="badge bg-label-secondary me-1" style="cursor:pointer;">+ {ROK}</span>
<span class="badge bg-label-secondary me-1" style="cursor:pointer;">+ {POPRZEDNI_MIESIAC}</span>
<span class="badge bg-label-secondary" style="cursor:pointer;">+ {KWARTAL}</span>
</div>
</div>
</div>
</div>
</div>
<!-- Section 3: Items Configurator with Dynamic Tags -->
<div class="card mb-4">
<div class="card-header bg-label-primary py-2 d-flex justify-content-between align-items-center">
<span class="fw-bold text-primary"><i class="bx bx-list-plus me-2"></i>Pozycje na fakturze cyklicznej</span>
<div class="d-flex align-items-center gap-3">
<div class="d-flex align-items-center">
<label class="text-muted small me-2 text-nowrap">Licz od:</label>
<select class="form-select form-select-sm">
<option value="netto" selected>Cen netto</option>
<option value="brutto">Cen brutto</option>
</select>
</div>
<button type="button" class="btn btn-primary btn-sm"><i class="bx bx-plus me-1"></i> Dodaj pozycję</button>
</div>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-bordered m-0">
<thead class="table-light">
<tr>
<th style="width: 35%;">Nazwa towaru / usługi (oraz zmienne okresu)</th>
<th style="width: 10%;">Ilość</th>
<th style="width: 10%;">J.m.</th>
<th style="width: 12%;">Cena netto</th>
<th style="width: 10%;">VAT</th>
<th style="width: 13%;">Wartość brutto</th>
<th style="width: 5%;" class="text-center">Usuń</th>
</tr>
</thead>
<tbody>
<!-- Item row 1 -->
<tr>
<td>
<input type="text" class="form-control mb-1 fw-medium" value="Abonament za opiekę serwerową IT - okres {MIESIAC} {ROK}">
</td>
<td><input type="number" class="form-control" value="1"></td>
<td>
<select class="form-select">
<option value="usluga" selected>usł.</option>
<option value="szt">szt.</option>
<option value="msc">m-c</option>
</select>
</td>
<td><input type="text" class="form-control" value="1 200,00"></td>
<td>
<select class="form-select">
<option value="23" selected>23%</option>
<option value="8">8%</option>
<option value="0">0%</option>
<option value="zw">zw.</option>
</select>
</td>
<td><input type="text" class="form-control fw-bold" value="1 476,00" readonly></td>
<td class="text-center align-middle">
<button type="button" class="btn btn-icon btn-sm btn-label-danger"><i class="bx bx-trash"></i></button>
</td>
</tr>
<!-- Item row 2 -->
<tr>
<td>
<input type="text" class="form-control mb-1 fw-medium" value="Hosting Chmurowy Magico Cloud (Kwartalnie)">
</td>
<td><input type="number" class="form-control" value="1"></td>
<td>
<select class="form-select">
<option value="usluga" selected>usł.</option>
<option value="szt">szt.</option>
</select>
</td>
<td><input type="text" class="form-control" value="300,00"></td>
<td>
<select class="form-select">
<option value="23" selected>23%</option>
</select>
</td>
<td><input type="text" class="form-control fw-bold" value="369,00" readonly></td>
<td class="text-center align-middle">
<button type="button" class="btn btn-icon btn-sm btn-label-danger"><i class="bx bx-trash"></i></button>
</td>
</tr>
</tbody>
</table>
</div>
<!-- Dynamic Tag Guide below table -->
<div class="p-3 border-top bg-lighter">
<div class="d-flex align-items-center gap-2">
<small class="text-muted fw-bold">Dostępne zmienne dla pozycji (kliknij aby skopiować):</small>
<span class="badge bg-label-primary px-2 py-1" style="cursor:pointer;">{MIESIAC}</span>
<span class="badge bg-label-primary px-2 py-1" style="cursor:pointer;">{ROK}</span>
<span class="badge bg-label-primary px-2 py-1" style="cursor:pointer;">{POPRZEDNI_MIESIAC}</span>
<span class="badge bg-label-primary px-2 py-1" style="cursor:pointer;">{KWARTAL}</span>
</div>
</div>
</div>
<div class="card-footer bg-lighter d-flex justify-content-end py-3 border-top">
<div class="d-flex flex-column align-items-end me-3">
<span class="text-muted small">Suma netto: <strong>1 500,00 PLN</strong></span>
<span class="text-muted small">Suma VAT (23%): <strong>345,00 PLN</strong></span>
<h5 class="mb-0 text-primary mt-1">Razem brutto: <strong>1 845,00 PLN</strong></h5>
</div>
</div>
</div>
<!-- Submit Bottom Bar -->
<div class="d-flex justify-content-end gap-2 mb-4">
<a href="app-invoice-recurring-list.php" class="btn btn-label-secondary">Anuluj</a>
<button type="submit" class="btn btn-primary"><i class="bx bx-save me-1"></i> Zapisz szablon cyklu</button>
</div>
</form>
</div>
<?php include '../../footer.php'; ?>
<script>
document.addEventListener('DOMContentLoaded', function () {
const toggle = document.getElementById('masterStatusToggle');
const label = document.getElementById('statusLabelText');
const unitSelect = document.getElementById('cycleUnitSelect');
const intervalText = document.getElementById('intervalUnitText');
if (toggle && label) {
toggle.addEventListener('change', function () {
if (this.checked) {
label.textContent = 'AKTYWNY (ON)';
label.className = 'badge bg-label-success';
} else {
label.textContent = 'WYŁĄCZONY (OFF)';
label.className = 'badge bg-label-danger';
}
});
}
const intervalInput = document.getElementById('intervalInput');
const summaryDesc = document.getElementById('summaryDescription');
const startDateInput = document.getElementById('startDateInput');
const endDateInput = document.getElementById('endDateInput');
function updateUnitsAndSummary() {
if (!unitSelect || !intervalInput || !intervalText) return;
const val = unitSelect.value;
const num = parseInt(intervalInput.value) || 1;
let unitLabel = '';
let unitGenitive = '';
if (val === 'miesiac') {
if (num === 1) unitLabel = 'miesiąc';
else if (num >= 2 && num <= 4) unitLabel = 'miesiące';
else unitLabel = 'miesięcy';
unitGenitive = unitLabel;
} else if (val === 'rok') {
if (num === 1) unitLabel = 'rok';
else if (num >= 2 && num <= 4) unitLabel = 'lata';
else unitLabel = 'lat';
unitGenitive = unitLabel;
} else if (val === 'dzien') {
if (num === 1) unitLabel = 'dzień';
else unitLabel = 'dni';
unitGenitive = unitLabel;
}
intervalText.textContent = unitLabel;
if (summaryDesc) {
const startDate = startDateInput ? startDateInput.value || 'dzisiaj' : 'dzisiaj';
const endDate = endDateInput && endDateInput.value ? ` do dnia <strong>${endDateInput.value}</strong>` : ' bezterminowo';
summaryDesc.innerHTML = `Faktura będzie generowana <strong>co ${num} ${unitGenitive}</strong>, rozpoczynając od dnia <strong>${startDate}</strong>${endDate}.`;
}
}
if (unitSelect) unitSelect.addEventListener('change', updateUnitsAndSummary);
if (intervalInput) intervalInput.addEventListener('input', updateUnitsAndSummary);
if (startDateInput) startDateInput.addEventListener('change', updateUnitsAndSummary);
if (endDateInput) endDateInput.addEventListener('change', updateUnitsAndSummary);
const recipientToggle = document.getElementById('recipientToggle');
const recipientBox = document.getElementById('recipientBox');
if (recipientToggle && recipientBox) {
recipientToggle.addEventListener('change', function () {
if (this.checked) {
recipientBox.classList.remove('d-none');
} else {
recipientBox.classList.add('d-none');
}
});
}
});
</script>
</body>
</html>