Kopírování faktur a detaily.
parent
38e169bfcf
commit
690624f915
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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 ?? ''));
|
||||
|
|
|
|||
|
|
@ -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 || '[]');
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 -->
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
Loading…
Reference in New Issue