Kopírování faktur a detaily.

master
Kowalski 2026-11-01 14:28:30 +01:00
parent 38e169bfcf
commit 690624f915
9 changed files with 467 additions and 60 deletions

25
Kufřík DEPLOY.bat Normal file
View File

@ -0,0 +1,25 @@
@echo off
title Deploying Kufrik to Production...
cd /d "%~dp0"
echo ========================================
echo Spoustim deployment na produkcni server...
echo ========================================
echo.
php vendor/bin/dep deploy production
if %ERRORLEVEL% EQU 0 (
echo.
echo ========================================
echo Hotovo! Deployment probehl uspesne.
echo ========================================
) else (
echo.
echo ========================================
echo CHYBA: Deployment selhal!
echo ========================================
)
echo.
pause

View File

@ -244,78 +244,140 @@ class FakturaFacade
}
/**
* Uložení / Aktualizace hlavičky faktury + vytvoření snapshotů D_* a O_*
* Snapshot dodavatele z aktuálních údajů firmy (výchozí hodnoty nové faktury).
*
* @return array<string, string|null>
*/
public function getDodavatelDefaults(int $firmaId): array
{
$firma = $this->kufrikExplorer->table('FIRMA')->get($firmaId);
if (!$firma) {
return [];
}
return [
'D_PRAJM' => $firma->NAZEV ?? null,
'D_ULICE' => $firma->ULICE ?? null,
'D_MESTO' => $firma->MESTO ?? null,
'D_PSC' => $firma->PSC ?? null,
'D_IC' => $firma->IC ?? null,
'D_DIC' => $firma->DIC ?? null,
'D_BANKA' => self::formatFirmaUcet($firma),
'D_TELEFON' => $firma->TELEFON ?? null,
'D_EMAIL' => $firma->EMAIL ?? null,
'D_WEB' => self::firmaWeb($firma),
];
}
/**
* Uložení / Aktualizace hlavičky faktury + snapshotů D_* a O_*
*/
public function saveFaktura(array $data, ?int $id = null, int $firmaId): int
{
$snapshot = $this->resolveSnapshot($data, $firmaId, $id === null);
if ($id) {
// PŘI EDITACI: Mění se pouze měnitelné údaje (splatnost, DUZP, stav, činnosti)
$values = [
'DATUM_SPLATNOSTI' => $data['DATUM_SPLATNOSTI'],
'DATUM_DUZP' => !empty($data['DATUM_DUZP']) ? $data['DATUM_DUZP'] : null,
'FORMA_UHRADY' => (int) ($data['FORMA_UHRADY'] ?? 1),
'CINNOSTI' => !empty($data['CINNOSTI']) ? $data['CINNOSTI'] : null,
];
] + $snapshot;
$this->kufrikExplorer->table('FAKTURA')->where('ID', $id)->update($values);
return $id;
}
} else {
// PŘI NOVÉ FAKTUŘE: Ukládáme vše (včetně DATUM_VYSTAVENI, CISLO, ZAKAZNIK a snapshotů)
$firma = $this->kufrikExplorer->table('FIRMA')->where('ID', $firmaId)->fetch();
$zakaznikId = !empty($data['ZAKAZNIK_ID']) ? (int) $data['ZAKAZNIK_ID'] : null;
$zakaznik = $zakaznikId ? $this->kufrikExplorer->table('ZAKAZNIK')->where('ID', $zakaznikId)->fetch() : null;
$zakaznikId = !empty($data['ZAKAZNIK_ID']) ? (int) $data['ZAKAZNIK_ID'] : null;
if (!$zakaznikId) {
throw new \InvalidArgumentException('Faktura musí mít odběratele.');
}
if (!$zakaznikId || !$zakaznik) {
throw new \InvalidArgumentException('Faktura musí mít odběratele.');
$values = [
'FIRMA_ID' => $firmaId,
'ZAKAZNIK' => $zakaznikId,
'CISLO' => $data['CISLO'],
'CISLO_ABS' => $this->resolveCisloAbs($data, $firmaId),
'FORMA_UHRADY' => (int) ($data['FORMA_UHRADY'] ?? 1),
'DATUM_VYSTAVENI' => $data['DATUM_VYSTAVENI'],
'DATUM_SPLATNOSTI' => $data['DATUM_SPLATNOSTI'],
'DATUM_DUZP' => !empty($data['DATUM_DUZP']) ? $data['DATUM_DUZP'] : null,
'STAV' => $data['STAV'] ?? 'ISSUED',
'CINNOSTI' => !empty($data['CINNOSTI']) ? $data['CINNOSTI'] : null,
] + $snapshot;
$row = $this->kufrikExplorer->table('FAKTURA')->insert($values);
return $row->ID;
}
/**
* Snapshot z formuláře; u nové faktury doplní chybějící údaje z firmy / zákazníka.
*
* @return array<string, string|null>
*/
private function resolveSnapshot(array $data, int $firmaId, bool $isNew): array
{
$fromForm = [
'D_PRAJM' => self::nullIfEmpty($data['D_PRAJM'] ?? null),
'D_ULICE' => self::nullIfEmpty($data['D_ULICE'] ?? null),
'D_MESTO' => self::nullIfEmpty($data['D_MESTO'] ?? null),
'D_PSC' => self::nullIfEmpty($data['D_PSC'] ?? null),
'D_IC' => self::nullIfEmpty($data['D_IC'] ?? null),
'D_DIC' => self::nullIfEmpty($data['D_DIC'] ?? null),
'D_BANKA' => self::nullIfEmpty($data['D_BANKA'] ?? null),
'D_TELEFON' => self::nullIfEmpty($data['D_TELEFON'] ?? null),
'D_EMAIL' => self::nullIfEmpty($data['D_EMAIL'] ?? null),
'D_WEB' => self::nullIfEmpty($data['D_WEB'] ?? null),
'O_PRAJM' => self::nullIfEmpty($data['O_PRAJM'] ?? null),
'O_ULICE' => self::nullIfEmpty($data['O_ULICE'] ?? null),
'O_MESTO' => self::nullIfEmpty($data['O_MESTO'] ?? null),
'O_PSC' => self::nullIfEmpty($data['O_PSC'] ?? null),
'O_IC' => self::nullIfEmpty($data['O_IC'] ?? null),
'O_DIC' => self::nullIfEmpty($data['O_DIC'] ?? null),
];
if (!$isNew) {
return $fromForm;
}
$defaults = $this->getDodavatelDefaults($firmaId);
foreach ($defaults as $key => $value) {
if ($fromForm[$key] === null || $fromForm[$key] === '') {
$fromForm[$key] = $value;
}
}
$oPrajm = $zakaznik ? trim(($zakaznik->PRIJMENI ?? '') . ' ' . ($zakaznik->JMENO ?? '')) : null;
$dBanka = null;
if ($firma) {
if (isset($firma->UCET, $firma->KOD_BANKY) && $firma->UCET) {
$dBanka = $firma->UCET . '/' . $firma->KOD_BANKY;
} elseif (isset($firma->BANKA)) {
$dBanka = $firma->BANKA;
}
}
$values = [
'FIRMA_ID' => $firmaId,
'ZAKAZNIK' => $zakaznikId,
'CISLO' => $data['CISLO'],
'CISLO_ABS' => $this->resolveCisloAbs($data, $firmaId),
'FORMA_UHRADY' => (int) ($data['FORMA_UHRADY'] ?? 1),
'DATUM_VYSTAVENI' => $data['DATUM_VYSTAVENI'],
'DATUM_SPLATNOSTI' => $data['DATUM_SPLATNOSTI'],
'DATUM_DUZP' => !empty($data['DATUM_DUZP']) ? $data['DATUM_DUZP'] : null,
'STAV' => $data['STAV'] ?? 'ISSUED',
'CINNOSTI' => !empty($data['CINNOSTI']) ? $data['CINNOSTI'] : null,
// SNAPSHOT DODAVATELE
'D_PRAJM' => $firma->NAZEV ?? null,
'D_ULICE' => $firma->ULICE ?? null,
'D_MESTO' => $firma->MESTO ?? null,
'D_PSC' => $firma->PSC ?? null,
'D_IC' => $firma->IC ?? null,
'D_DIC' => $firma->DIC ?? null,
'D_BANKA' => $dBanka,
'D_TELEFON' => $firma->TELEFON ?? null,
'D_EMAIL' => $firma->EMAIL ?? null,
'D_WEB' => $firma->WEB ?? null,
// SNAPSHOT ODBĚRATELE
'O_PRAJM' => $oPrajm,
$zakaznikId = !empty($data['ZAKAZNIK_ID']) ? (int) $data['ZAKAZNIK_ID'] : null;
$zakaznik = $zakaznikId
? $this->kufrikExplorer->table('ZAKAZNIK')->where('ID', $zakaznikId)->fetch()
: null;
if ($zakaznik) {
$oDefaults = [
'O_PRAJM' => trim(($zakaznik->PRIJMENI ?? '') . ' ' . ($zakaznik->JMENO ?? '')) ?: null,
'O_ULICE' => $zakaznik->ULICE ?? null,
'O_MESTO' => $zakaznik->MESTO ?? null,
'O_PSC' => $zakaznik->PSC ?? null,
'O_IC' => $zakaznik->IC ?? null,
'O_DIC' => $zakaznik->DIC ?? null,
];
$row = $this->kufrikExplorer->table('FAKTURA')->insert($values);
return $row->ID;
foreach ($oDefaults as $key => $value) {
if ($fromForm[$key] === null || $fromForm[$key] === '') {
$fromForm[$key] = $value;
}
}
}
return $fromForm;
}
private static function nullIfEmpty(mixed $value): ?string
{
if ($value === null) {
return null;
}
$text = trim((string) $value);
return $text !== '' ? $text : null;
}
/**
@ -568,6 +630,23 @@ class FakturaFacade
'DATUM_DUZP' => $datumVystaveni,
'STAV' => self::STAV_VYSTAVENO,
'CINNOSTI' => $zdroj->CINNOSTI,
// Zachovat upravené údaje dodavatele / odběratele ze zdroje
'D_PRAJM' => $zdroj->D_PRAJM,
'D_ULICE' => $zdroj->D_ULICE,
'D_MESTO' => $zdroj->D_MESTO,
'D_PSC' => $zdroj->D_PSC,
'D_IC' => $zdroj->D_IC,
'D_DIC' => $zdroj->D_DIC,
'D_BANKA' => $zdroj->D_BANKA,
'D_TELEFON' => $zdroj->D_TELEFON,
'D_EMAIL' => $zdroj->D_EMAIL,
'D_WEB' => $zdroj->D_WEB,
'O_PRAJM' => $zdroj->O_PRAJM,
'O_ULICE' => $zdroj->O_ULICE,
'O_MESTO' => $zdroj->O_MESTO,
'O_PSC' => $zdroj->O_PSC,
'O_IC' => $zdroj->O_IC,
'O_DIC' => $zdroj->O_DIC,
], null, $firmaId);
$polozky = [];
@ -585,4 +664,34 @@ class FakturaFacade
return $novaId;
}
/**
* Číslo účtu dodavatele ve formátu „účet/kód banky“.
*/
private static function formatFirmaUcet(?object $firma): ?string
{
if (!$firma) {
return null;
}
$ucet = trim((string) ($firma->CISLO_UCTU ?? ''));
$kod = trim((string) ($firma->BANKA_KOD ?? ''));
if ($ucet !== '') {
return $kod !== '' ? $ucet . '/' . $kod : $ucet;
}
return null;
}
private static function firmaWeb(?object $firma): ?string
{
if (!$firma) {
return null;
}
$web = trim((string) ($firma->WEB ?? ''));
return $web !== '' ? $web : null;
}
}

View File

@ -65,6 +65,7 @@ class SdfKufrikImporter
$nastaveniImported = $this->importNastaveni($explorer, $data['konfigurace'], $firmaId);
$zakaznikMap = $this->importZakaznici($explorer, $data['zakaznik'], $firmaId);
$fakturaResult = $this->importFaktury($explorer, $data, $firmaId, $zakaznikMap);
$this->doplnFirmaWebZFaktur($explorer, $firmaId);
$explorer->getConnection()->commit();
} catch (\Throwable $e) {
$explorer->getConnection()->rollBack();
@ -121,6 +122,7 @@ class SdfKufrikImporter
'PLATCE_DPH' => 0,
'TELEFON' => $this->clip($uzivatel['TELEFON'] ?? null, 20),
'EMAIL' => $this->clip($uzivatel['EMAIL'] ?? null, 100),
'WEB' => $this->clip($uzivatel['WEB'] ?? $uzivatel['D_WEB'] ?? null, 100),
'ULICE' => $this->clip($uzivatel['ULICE'] ?? null, 100),
'MESTO' => $this->clip($uzivatel['MESTO'] ?? null, 100),
'PSC' => $this->clip($uzivatel['PSC'] ?? null, 10),
@ -145,6 +147,30 @@ class SdfKufrikImporter
return 'inserted';
}
/**
* Pokud firma nemá WEB, vezme ho z první faktury s vyplněným D_WEB.
*/
private function doplnFirmaWebZFaktur(Explorer $explorer, int $firmaId): void
{
$firma = $explorer->table('FIRMA')->get($firmaId);
if (!$firma || trim((string) ($firma->WEB ?? '')) !== '') {
return;
}
$web = $explorer->table('FAKTURA')
->where('FIRMA_ID', $firmaId)
->where('D_WEB NOT', null)
->where('D_WEB NOT', '')
->order('ID ASC')
->limit(1)
->fetchField('D_WEB');
$web = $this->clip($web, 100);
if ($web !== null) {
$explorer->table('FIRMA')->where('ID', $firmaId)->update(['WEB' => $web]);
}
}
/**
* Maska, období číslování a splatnost ze staré tabulky KONFIGURACE.
*

View File

@ -24,16 +24,17 @@ class FakturaEditPresenter extends BasePresenter
$this->id = null;
$this->setView('edit');
$firmaId = $this->getUser()->getIdentity()->firma_id;
$firmaId = (int) $this->getUser()->getIdentity()->firma_id;
$dalsi = $this->fakturaFacade->getNextCislo($firmaId);
$this['fakturaForm']->setDefaults([
'CISLO' => $dalsi['cislo'],
'CISLO_ABS' => $dalsi['cisloAbs'],
'FORMA_UHRADY' => 1,
'DATUM_SPLATNOSTI' => (new \DateTimeImmutable('today'))
->modify('+' . $dalsi['splatnostDny'] . ' days')
->format('Y-m-d'),
]);
] + $this->fakturaFacade->getDodavatelDefaults($firmaId));
}
public function actionEdit(int $id): void
@ -85,7 +86,17 @@ class FakturaEditPresenter extends BasePresenter
->setHtmlAttribute('tabindex', '-1');
}
public function renderNew(): void
{
$this->prepareEditTemplate();
}
public function renderEdit(?int $id = null): void
{
$this->prepareEditTemplate();
}
private function prepareEditTemplate(): void
{
$this->template->isEdit = (bool) $this->id;
@ -109,9 +120,14 @@ class FakturaEditPresenter extends BasePresenter
}
}
$jsonFlags = JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_THROW_ON_ERROR;
$this->template->katalogPolozekJson = json_encode(
$this->fakturaFacade->getKatalogPolozek(),
JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_THROW_ON_ERROR
$jsonFlags
);
$this->template->zakazniciDetailJson = json_encode(
$this->zakazniciDetailProJs(),
$jsonFlags
);
$this->template->polozky = $polozky;
$this->template->platby = $platby;
@ -187,9 +203,34 @@ class FakturaEditPresenter extends BasePresenter
->setDefaultValue((new \DateTimeImmutable('today'))->modify('+' . $splatnostDny . ' days')->format('Y-m-d'))
->setRequired('Zadejte datum splatnosti.');
$form->addSelect('FORMA_UHRADY', 'Forma úhrady:', [
1 => 'převodem',
2 => 'hotově',
])->setDefaultValue(1);
$form->addText('DATUM_DUZP', 'Datum UZP:')
->setHtmlType('date');
// Detailní informace — dodavatel
$form->addText('D_PRAJM', 'Dodavatel:')->setMaxLength(511);
$form->addText('D_ULICE', 'Ulice:')->setMaxLength(50);
$form->addText('D_PSC', 'PSČ:')->setMaxLength(50);
$form->addText('D_MESTO', 'Město:')->setMaxLength(50);
$form->addText('D_IC', 'IČ:')->setMaxLength(8);
$form->addText('D_DIC', 'DIČ:')->setMaxLength(10);
$form->addText('D_TELEFON', 'Telefon:')->setMaxLength(15);
$form->addText('D_EMAIL', 'E-mail:')->setMaxLength(100);
$form->addText('D_BANKA', 'Bankovní účet:')->setMaxLength(100);
$form->addText('D_WEB', 'Web:')->setMaxLength(100);
// Detailní informace — odběratel
$form->addText('O_PRAJM', 'Odběratel:')->setMaxLength(511);
$form->addText('O_ULICE', 'Ulice:')->setMaxLength(50);
$form->addText('O_PSC', 'PSČ:')->setMaxLength(5);
$form->addText('O_MESTO', 'Město:')->setMaxLength(50);
$form->addText('O_IC', 'IČ:')->setMaxLength(8);
$form->addText('O_DIC', 'DIČ:')->setMaxLength(10);
$form->addTextArea('CINNOSTI', 'Činnosti / Popis plnění:');
$form->addSubmit('save', 'Uložit fakturu')
@ -200,6 +241,44 @@ class FakturaEditPresenter extends BasePresenter
return $form;
}
/**
* @return array<string, array{nazev: string, ulice: ?string, psc: ?string, mesto: ?string, ic: ?string, dic: ?string}>
*/
private function zakazniciDetailProJs(): array
{
$map = [];
foreach ($this->zakaznikFacade->getFiltered('', 'aktivni') as $z) {
$map[(string) $z->ID] = [
'nazev' => trim(($z->PRIJMENI ?? '') . ' ' . ($z->JMENO ?? '')),
'ulice' => $z->ULICE,
'psc' => $z->PSC,
'mesto' => $z->MESTO,
'ic' => $z->IC,
'dic' => $z->DIC,
];
}
if ($this->id) {
$faktura = $this->fakturaFacade->getById($this->id);
$zakaznikId = $faktura ? (int) $faktura->ZAKAZNIK : 0;
if ($zakaznikId && !isset($map[(string) $zakaznikId])) {
$stavajici = $this->zakaznikFacade->getById($zakaznikId);
if ($stavajici) {
$map[(string) $zakaznikId] = [
'nazev' => trim(($stavajici->PRIJMENI ?? '') . ' ' . ($stavajici->JMENO ?? '')),
'ulice' => $stavajici->ULICE,
'psc' => $stavajici->PSC,
'mesto' => $stavajici->MESTO,
'ic' => $stavajici->IC,
'dic' => $stavajici->DIC,
];
}
}
}
return $map;
}
private function nazevZakaznika(object $zakaznik): string
{
$nazev = trim(($zakaznik->PRIJMENI ?? '') . ' ' . ($zakaznik->JMENO ?? ''));

View File

@ -24,21 +24,28 @@
</div>
</div>
<!-- Hlavička Faktury -->
<div class="col-md-6">
<label n:name="ZAKAZNIK_ID" class="form-label fw-bold">Odběratel *</label>
<select n:name="ZAKAZNIK_ID" class="form-select" data-suggest="zakaznik" {if $isEdit}data-locked="1"{/if}></select>
<!-- Základní informace -->
<div class="col-12">
<h5 class="mb-3"><i class="bi bi-info-circle me-2"></i>Základní informace</h5>
</div>
<div class="col-md-6">
<label n:name="CISLO" class="form-label fw-bold">Číslo faktury *</label>
<input n:name="CISLO" class="form-control">
<input n:name="CISLO_ABS">
</div>
<div class="col-md-6">
<label n:name="ZAKAZNIK_ID" class="form-label fw-bold">Zákazník *</label>
<select n:name="ZAKAZNIK_ID" class="form-select" data-suggest="zakaznik" {if $isEdit}data-locked="1"{/if}></select>
</div>
<div class="col-md-4">
<label n:name="DATUM_VYSTAVENI" class="form-label">Datum vystavení</label>
<input n:name="DATUM_VYSTAVENI" class="form-control">
</div>
<div class="col-md-4">
<label n:name="FORMA_UHRADY" class="form-label">Forma úhrady</label>
<select n:name="FORMA_UHRADY" class="form-select"></select>
</div>
<div class="col-md-4">
<label n:name="DATUM_SPLATNOSTI" class="form-label">Datum splatnosti</label>
<input n:name="DATUM_SPLATNOSTI" class="form-control">
@ -53,6 +60,105 @@
</div>
</div>
<!-- Detailní informace (rozbalovací) -->
<div class="col-12 mt-2">
<div class="border rounded">
<button class="btn btn-light w-100 text-start d-flex justify-content-between align-items-center px-3 py-2"
type="button"
data-bs-toggle="collapse"
data-bs-target="#detailniInformace"
aria-expanded="false"
aria-controls="detailniInformace">
<span class="fw-semibold"><i class="bi bi-person-vcard me-2"></i>Detailní informace</span>
<i class="bi bi-chevron-down"></i>
</button>
<div class="collapse" id="detailniInformace">
<div class="p-3 border-top">
<div class="row g-3">
<div class="col-md-6">
<h6 class="text-muted mb-3">Dodavatel</h6>
<div class="mb-2">
<label n:name="D_PRAJM" class="form-label small mb-1">Dodavatel</label>
<input n:name="D_PRAJM" class="form-control form-control-sm">
</div>
<div class="mb-2">
<label n:name="D_ULICE" class="form-label small mb-1">Ulice</label>
<input n:name="D_ULICE" class="form-control form-control-sm">
</div>
<div class="row g-2 mb-2">
<div class="col-4">
<label n:name="D_PSC" class="form-label small mb-1">PSČ</label>
<input n:name="D_PSC" class="form-control form-control-sm">
</div>
<div class="col-8">
<label n:name="D_MESTO" class="form-label small mb-1">Město</label>
<input n:name="D_MESTO" class="form-control form-control-sm">
</div>
</div>
<div class="row g-2 mb-2">
<div class="col-6">
<label n:name="D_IC" class="form-label small mb-1">IČ</label>
<input n:name="D_IC" class="form-control form-control-sm">
</div>
<div class="col-6">
<label n:name="D_DIC" class="form-label small mb-1">DIČ</label>
<input n:name="D_DIC" class="form-control form-control-sm">
</div>
</div>
<div class="mb-2">
<label n:name="D_TELEFON" class="form-label small mb-1">Telefon</label>
<input n:name="D_TELEFON" class="form-control form-control-sm">
</div>
<div class="mb-2">
<label n:name="D_EMAIL" class="form-label small mb-1">E-mail</label>
<input n:name="D_EMAIL" class="form-control form-control-sm">
</div>
<div class="mb-2">
<label n:name="D_BANKA" class="form-label small mb-1">Bankovní účet</label>
<input n:name="D_BANKA" class="form-control form-control-sm">
</div>
<div class="mb-0">
<label n:name="D_WEB" class="form-label small mb-1">Web</label>
<input n:name="D_WEB" class="form-control form-control-sm">
</div>
</div>
<div class="col-md-6">
<h6 class="text-muted mb-3">Odběratel</h6>
<div class="mb-2">
<label n:name="O_PRAJM" class="form-label small mb-1">Odběratel</label>
<input n:name="O_PRAJM" class="form-control form-control-sm">
</div>
<div class="mb-2">
<label n:name="O_ULICE" class="form-label small mb-1">Ulice</label>
<input n:name="O_ULICE" class="form-control form-control-sm">
</div>
<div class="row g-2 mb-2">
<div class="col-4">
<label n:name="O_PSC" class="form-label small mb-1">PSČ</label>
<input n:name="O_PSC" class="form-control form-control-sm">
</div>
<div class="col-8">
<label n:name="O_MESTO" class="form-label small mb-1">Město</label>
<input n:name="O_MESTO" class="form-control form-control-sm">
</div>
</div>
<div class="row g-2 mb-2">
<div class="col-6">
<label n:name="O_IC" class="form-label small mb-1">IČ</label>
<input n:name="O_IC" class="form-control form-control-sm">
</div>
<div class="col-6">
<label n:name="O_DIC" class="form-label small mb-1">DIČ</label>
<input n:name="O_DIC" class="form-control form-control-sm">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<hr class="my-4">
<!-- Položky Faktury -->
@ -209,6 +315,7 @@ document.getElementById('edit-platba-splatnost').addEventListener('click', funct
</script>
<script type="application/json" id="katalog-polozek">{$katalogPolozekJson|noescape}</script>
<script type="application/json" id="zakaznici-detail">{$zakazniciDetailJson|noescape}</script>
{syntax off}
<script>
@ -531,9 +638,39 @@ document.addEventListener('DOMContentLoaded', () => {
window.addEventListener('scroll', followInput, true);
}
let zakazniciDetail = {};
try {
zakazniciDetail = JSON.parse(document.getElementById('zakaznici-detail').textContent || '{}');
} catch (error) {
zakazniciDetail = {};
}
function fillOdberatel(zakaznikId) {
const detail = zakazniciDetail[String(zakaznikId)];
if (!detail) {
return;
}
const set = (name, value) => {
const el = document.querySelector('[name="' + name + '"]');
if (el) {
el.value = value || '';
}
};
set('O_PRAJM', detail.nazev);
set('O_ULICE', detail.ulice);
set('O_PSC', detail.psc);
set('O_MESTO', detail.mesto);
set('O_IC', detail.ic);
set('O_DIC', detail.dic);
}
function initZakaznikSuggest() {
const select = document.querySelector('select[data-suggest="zakaznik"]');
if (!select || select.dataset.locked === '1') {
if (!select) {
return;
}
if (select.dataset.locked === '1') {
return;
}
@ -574,6 +711,7 @@ document.addEventListener('DOMContentLoaded', () => {
emptyText: 'Žádný zákazník neodpovídá',
onPick(item) {
select.value = item.value;
fillOdberatel(item.value);
},
onClear() {
select.value = '';
@ -581,6 +719,19 @@ document.addEventListener('DOMContentLoaded', () => {
});
}
// Chevron v rozbalovacím panelu
const detailCollapse = document.getElementById('detailniInformace');
if (detailCollapse) {
const toggleBtn = document.querySelector('[data-bs-target="#detailniInformace"]');
const chevron = toggleBtn?.querySelector('.bi-chevron-down, .bi-chevron-up');
detailCollapse.addEventListener('show.bs.collapse', () => {
chevron?.classList.replace('bi-chevron-down', 'bi-chevron-up');
});
detailCollapse.addEventListener('hide.bs.collapse', () => {
chevron?.classList.replace('bi-chevron-up', 'bi-chevron-down');
});
}
let katalog = [];
try {
katalog = JSON.parse(document.getElementById('katalog-polozek').textContent || '[]');

View File

@ -47,6 +47,7 @@ class FirmaPresenter extends BasePresenter
'banka_kod' => $firma->BANKA_KOD,
'iban' => $firma->IBAN,
'bic' => $firma->BIC,
'web' => $firma->WEB ?? null,
]);
}
@ -67,6 +68,8 @@ class FirmaPresenter extends BasePresenter
// Kontakty
$form->addText('telefon', 'Telefon:');
$form->addEmail('email', 'E-mail:');
$form->addText('web', 'Web:')
->setMaxLength(100);
// Sídlo
$form->addText('ulice', 'Ulice a ČP:');
@ -100,6 +103,7 @@ class FirmaPresenter extends BasePresenter
'PLATCE_DPH' => 0,
'TELEFON' => $data->telefon,
'EMAIL' => $data->email,
'WEB' => $data->web !== '' ? $data->web : null,
'ULICE' => $data->ulice,
'MESTO' => $data->mesto,
'PSC' => $data->psc,

View File

@ -54,14 +54,18 @@
</div>
<div class="row mt-2">
<div class="col-md-6 form-group">
<div class="col-md-4 form-group">
<label n:name="telefon">Telefon</label>
<input n:name="telefon" class="form-control">
</div>
<div class="col-md-6 form-group">
<div class="col-md-4 form-group">
<label n:name="email">E-mail</label>
<input n:name="email" class="form-control">
</div>
<div class="col-md-4 form-group">
<label n:name="web">Web</label>
<input n:name="web" class="form-control" placeholder="www.example.cz">
</div>
</div>
<!-- BANKA -->

View File

@ -138,6 +138,7 @@ CREATE TABLE [dbo].[FIRMA] (
-- Kontaktní údaje
[TELEFON] [nvarchar](20) NULL,
[EMAIL] [nvarchar](100) NULL,
[WEB] [nvarchar](100) NULL,
-- Sídlo
[ULICE] [nvarchar](100) NULL,

8
sql/add_firma_web.sql Normal file
View File

@ -0,0 +1,8 @@
-- Web firmy pro snapshot D_WEB na fakturách.
-- Spouštět v každé klientské databázi (např. kufrik).
IF COL_LENGTH('dbo.FIRMA', 'WEB') IS NULL
BEGIN
ALTER TABLE dbo.FIRMA ADD [WEB] [nvarchar](100) NULL;
END
GO