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,42 +244,55 @@ 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
|
public function saveFaktura(array $data, ?int $id = null, int $firmaId): int
|
||||||
{
|
{
|
||||||
|
$snapshot = $this->resolveSnapshot($data, $firmaId, $id === null);
|
||||||
|
|
||||||
if ($id) {
|
if ($id) {
|
||||||
// PŘI EDITACI: Mění se pouze měnitelné údaje (splatnost, DUZP, stav, činnosti)
|
|
||||||
$values = [
|
$values = [
|
||||||
'DATUM_SPLATNOSTI' => $data['DATUM_SPLATNOSTI'],
|
'DATUM_SPLATNOSTI' => $data['DATUM_SPLATNOSTI'],
|
||||||
'DATUM_DUZP' => !empty($data['DATUM_DUZP']) ? $data['DATUM_DUZP'] : null,
|
'DATUM_DUZP' => !empty($data['DATUM_DUZP']) ? $data['DATUM_DUZP'] : null,
|
||||||
|
'FORMA_UHRADY' => (int) ($data['FORMA_UHRADY'] ?? 1),
|
||||||
'CINNOSTI' => !empty($data['CINNOSTI']) ? $data['CINNOSTI'] : null,
|
'CINNOSTI' => !empty($data['CINNOSTI']) ? $data['CINNOSTI'] : null,
|
||||||
];
|
] + $snapshot;
|
||||||
|
|
||||||
$this->kufrikExplorer->table('FAKTURA')->where('ID', $id)->update($values);
|
$this->kufrikExplorer->table('FAKTURA')->where('ID', $id)->update($values);
|
||||||
return $id;
|
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;
|
$zakaznikId = !empty($data['ZAKAZNIK_ID']) ? (int) $data['ZAKAZNIK_ID'] : null;
|
||||||
$zakaznik = $zakaznikId ? $this->kufrikExplorer->table('ZAKAZNIK')->where('ID', $zakaznikId)->fetch() : null;
|
if (!$zakaznikId) {
|
||||||
|
|
||||||
if (!$zakaznikId || !$zakaznik) {
|
|
||||||
throw new \InvalidArgumentException('Faktura musí mít odběratele.');
|
throw new \InvalidArgumentException('Faktura musí mít odběratele.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$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 = [
|
$values = [
|
||||||
'FIRMA_ID' => $firmaId,
|
'FIRMA_ID' => $firmaId,
|
||||||
'ZAKAZNIK' => $zakaznikId,
|
'ZAKAZNIK' => $zakaznikId,
|
||||||
|
|
@ -291,32 +304,81 @@ class FakturaFacade
|
||||||
'DATUM_DUZP' => !empty($data['DATUM_DUZP']) ? $data['DATUM_DUZP'] : null,
|
'DATUM_DUZP' => !empty($data['DATUM_DUZP']) ? $data['DATUM_DUZP'] : null,
|
||||||
'STAV' => $data['STAV'] ?? 'ISSUED',
|
'STAV' => $data['STAV'] ?? 'ISSUED',
|
||||||
'CINNOSTI' => !empty($data['CINNOSTI']) ? $data['CINNOSTI'] : null,
|
'CINNOSTI' => !empty($data['CINNOSTI']) ? $data['CINNOSTI'] : null,
|
||||||
|
] + $snapshot;
|
||||||
|
|
||||||
// SNAPSHOT DODAVATELE
|
$row = $this->kufrikExplorer->table('FAKTURA')->insert($values);
|
||||||
'D_PRAJM' => $firma->NAZEV ?? null,
|
return $row->ID;
|
||||||
'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,
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$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_ULICE' => $zakaznik->ULICE ?? null,
|
||||||
'O_MESTO' => $zakaznik->MESTO ?? null,
|
'O_MESTO' => $zakaznik->MESTO ?? null,
|
||||||
'O_PSC' => $zakaznik->PSC ?? null,
|
'O_PSC' => $zakaznik->PSC ?? null,
|
||||||
'O_IC' => $zakaznik->IC ?? null,
|
'O_IC' => $zakaznik->IC ?? null,
|
||||||
'O_DIC' => $zakaznik->DIC ?? null,
|
'O_DIC' => $zakaznik->DIC ?? null,
|
||||||
];
|
];
|
||||||
|
foreach ($oDefaults as $key => $value) {
|
||||||
$row = $this->kufrikExplorer->table('FAKTURA')->insert($values);
|
if ($fromForm[$key] === null || $fromForm[$key] === '') {
|
||||||
return $row->ID;
|
$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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uložení položek s automatickým výpočtem PORADI
|
* Uložení položek s automatickým výpočtem PORADI
|
||||||
|
|
@ -568,6 +630,23 @@ class FakturaFacade
|
||||||
'DATUM_DUZP' => $datumVystaveni,
|
'DATUM_DUZP' => $datumVystaveni,
|
||||||
'STAV' => self::STAV_VYSTAVENO,
|
'STAV' => self::STAV_VYSTAVENO,
|
||||||
'CINNOSTI' => $zdroj->CINNOSTI,
|
'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);
|
], null, $firmaId);
|
||||||
|
|
||||||
$polozky = [];
|
$polozky = [];
|
||||||
|
|
@ -585,4 +664,34 @@ class FakturaFacade
|
||||||
|
|
||||||
return $novaId;
|
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);
|
$nastaveniImported = $this->importNastaveni($explorer, $data['konfigurace'], $firmaId);
|
||||||
$zakaznikMap = $this->importZakaznici($explorer, $data['zakaznik'], $firmaId);
|
$zakaznikMap = $this->importZakaznici($explorer, $data['zakaznik'], $firmaId);
|
||||||
$fakturaResult = $this->importFaktury($explorer, $data, $firmaId, $zakaznikMap);
|
$fakturaResult = $this->importFaktury($explorer, $data, $firmaId, $zakaznikMap);
|
||||||
|
$this->doplnFirmaWebZFaktur($explorer, $firmaId);
|
||||||
$explorer->getConnection()->commit();
|
$explorer->getConnection()->commit();
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
$explorer->getConnection()->rollBack();
|
$explorer->getConnection()->rollBack();
|
||||||
|
|
@ -121,6 +122,7 @@ class SdfKufrikImporter
|
||||||
'PLATCE_DPH' => 0,
|
'PLATCE_DPH' => 0,
|
||||||
'TELEFON' => $this->clip($uzivatel['TELEFON'] ?? null, 20),
|
'TELEFON' => $this->clip($uzivatel['TELEFON'] ?? null, 20),
|
||||||
'EMAIL' => $this->clip($uzivatel['EMAIL'] ?? null, 100),
|
'EMAIL' => $this->clip($uzivatel['EMAIL'] ?? null, 100),
|
||||||
|
'WEB' => $this->clip($uzivatel['WEB'] ?? $uzivatel['D_WEB'] ?? null, 100),
|
||||||
'ULICE' => $this->clip($uzivatel['ULICE'] ?? null, 100),
|
'ULICE' => $this->clip($uzivatel['ULICE'] ?? null, 100),
|
||||||
'MESTO' => $this->clip($uzivatel['MESTO'] ?? null, 100),
|
'MESTO' => $this->clip($uzivatel['MESTO'] ?? null, 100),
|
||||||
'PSC' => $this->clip($uzivatel['PSC'] ?? null, 10),
|
'PSC' => $this->clip($uzivatel['PSC'] ?? null, 10),
|
||||||
|
|
@ -145,6 +147,30 @@ class SdfKufrikImporter
|
||||||
return 'inserted';
|
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.
|
* Maska, období číslování a splatnost ze staré tabulky KONFIGURACE.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -24,16 +24,17 @@ class FakturaEditPresenter extends BasePresenter
|
||||||
$this->id = null;
|
$this->id = null;
|
||||||
$this->setView('edit');
|
$this->setView('edit');
|
||||||
|
|
||||||
$firmaId = $this->getUser()->getIdentity()->firma_id;
|
$firmaId = (int) $this->getUser()->getIdentity()->firma_id;
|
||||||
$dalsi = $this->fakturaFacade->getNextCislo($firmaId);
|
$dalsi = $this->fakturaFacade->getNextCislo($firmaId);
|
||||||
|
|
||||||
$this['fakturaForm']->setDefaults([
|
$this['fakturaForm']->setDefaults([
|
||||||
'CISLO' => $dalsi['cislo'],
|
'CISLO' => $dalsi['cislo'],
|
||||||
'CISLO_ABS' => $dalsi['cisloAbs'],
|
'CISLO_ABS' => $dalsi['cisloAbs'],
|
||||||
|
'FORMA_UHRADY' => 1,
|
||||||
'DATUM_SPLATNOSTI' => (new \DateTimeImmutable('today'))
|
'DATUM_SPLATNOSTI' => (new \DateTimeImmutable('today'))
|
||||||
->modify('+' . $dalsi['splatnostDny'] . ' days')
|
->modify('+' . $dalsi['splatnostDny'] . ' days')
|
||||||
->format('Y-m-d'),
|
->format('Y-m-d'),
|
||||||
]);
|
] + $this->fakturaFacade->getDodavatelDefaults($firmaId));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function actionEdit(int $id): void
|
public function actionEdit(int $id): void
|
||||||
|
|
@ -85,7 +86,17 @@ class FakturaEditPresenter extends BasePresenter
|
||||||
->setHtmlAttribute('tabindex', '-1');
|
->setHtmlAttribute('tabindex', '-1');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function renderNew(): void
|
||||||
|
{
|
||||||
|
$this->prepareEditTemplate();
|
||||||
|
}
|
||||||
|
|
||||||
public function renderEdit(?int $id = null): void
|
public function renderEdit(?int $id = null): void
|
||||||
|
{
|
||||||
|
$this->prepareEditTemplate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function prepareEditTemplate(): void
|
||||||
{
|
{
|
||||||
$this->template->isEdit = (bool) $this->id;
|
$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->template->katalogPolozekJson = json_encode(
|
||||||
$this->fakturaFacade->getKatalogPolozek(),
|
$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->polozky = $polozky;
|
||||||
$this->template->platby = $platby;
|
$this->template->platby = $platby;
|
||||||
|
|
@ -187,9 +203,34 @@ class FakturaEditPresenter extends BasePresenter
|
||||||
->setDefaultValue((new \DateTimeImmutable('today'))->modify('+' . $splatnostDny . ' days')->format('Y-m-d'))
|
->setDefaultValue((new \DateTimeImmutable('today'))->modify('+' . $splatnostDny . ' days')->format('Y-m-d'))
|
||||||
->setRequired('Zadejte datum splatnosti.');
|
->setRequired('Zadejte datum splatnosti.');
|
||||||
|
|
||||||
|
$form->addSelect('FORMA_UHRADY', 'Forma úhrady:', [
|
||||||
|
1 => 'převodem',
|
||||||
|
2 => 'hotově',
|
||||||
|
])->setDefaultValue(1);
|
||||||
|
|
||||||
$form->addText('DATUM_DUZP', 'Datum UZP:')
|
$form->addText('DATUM_DUZP', 'Datum UZP:')
|
||||||
->setHtmlType('date');
|
->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->addTextArea('CINNOSTI', 'Činnosti / Popis plnění:');
|
||||||
|
|
||||||
$form->addSubmit('save', 'Uložit fakturu')
|
$form->addSubmit('save', 'Uložit fakturu')
|
||||||
|
|
@ -200,6 +241,44 @@ class FakturaEditPresenter extends BasePresenter
|
||||||
return $form;
|
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
|
private function nazevZakaznika(object $zakaznik): string
|
||||||
{
|
{
|
||||||
$nazev = trim(($zakaznik->PRIJMENI ?? '') . ' ' . ($zakaznik->JMENO ?? ''));
|
$nazev = trim(($zakaznik->PRIJMENI ?? '') . ' ' . ($zakaznik->JMENO ?? ''));
|
||||||
|
|
|
||||||
|
|
@ -24,21 +24,28 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Hlavička Faktury -->
|
<!-- Základní informace -->
|
||||||
<div class="col-md-6">
|
<div class="col-12">
|
||||||
<label n:name="ZAKAZNIK_ID" class="form-label fw-bold">Odběratel *</label>
|
<h5 class="mb-3"><i class="bi bi-info-circle me-2"></i>Základní informace</h5>
|
||||||
<select n:name="ZAKAZNIK_ID" class="form-select" data-suggest="zakaznik" {if $isEdit}data-locked="1"{/if}></select>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label n:name="CISLO" class="form-label fw-bold">Číslo faktury *</label>
|
<label n:name="CISLO" class="form-label fw-bold">Číslo faktury *</label>
|
||||||
<input n:name="CISLO" class="form-control">
|
<input n:name="CISLO" class="form-control">
|
||||||
<input n:name="CISLO_ABS">
|
<input n:name="CISLO_ABS">
|
||||||
</div>
|
</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">
|
<div class="col-md-4">
|
||||||
<label n:name="DATUM_VYSTAVENI" class="form-label">Datum vystavení</label>
|
<label n:name="DATUM_VYSTAVENI" class="form-label">Datum vystavení</label>
|
||||||
<input n:name="DATUM_VYSTAVENI" class="form-control">
|
<input n:name="DATUM_VYSTAVENI" class="form-control">
|
||||||
</div>
|
</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">
|
<div class="col-md-4">
|
||||||
<label n:name="DATUM_SPLATNOSTI" class="form-label">Datum splatnosti</label>
|
<label n:name="DATUM_SPLATNOSTI" class="form-label">Datum splatnosti</label>
|
||||||
<input n:name="DATUM_SPLATNOSTI" class="form-control">
|
<input n:name="DATUM_SPLATNOSTI" class="form-control">
|
||||||
|
|
@ -53,6 +60,105 @@
|
||||||
</div>
|
</div>
|
||||||
</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">
|
<hr class="my-4">
|
||||||
|
|
||||||
<!-- Položky Faktury -->
|
<!-- Položky Faktury -->
|
||||||
|
|
@ -209,6 +315,7 @@ document.getElementById('edit-platba-splatnost').addEventListener('click', funct
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="application/json" id="katalog-polozek">{$katalogPolozekJson|noescape}</script>
|
<script type="application/json" id="katalog-polozek">{$katalogPolozekJson|noescape}</script>
|
||||||
|
<script type="application/json" id="zakaznici-detail">{$zakazniciDetailJson|noescape}</script>
|
||||||
|
|
||||||
{syntax off}
|
{syntax off}
|
||||||
<script>
|
<script>
|
||||||
|
|
@ -531,9 +638,39 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||||
window.addEventListener('scroll', followInput, true);
|
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() {
|
function initZakaznikSuggest() {
|
||||||
const select = document.querySelector('select[data-suggest="zakaznik"]');
|
const select = document.querySelector('select[data-suggest="zakaznik"]');
|
||||||
if (!select || select.dataset.locked === '1') {
|
if (!select) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (select.dataset.locked === '1') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -574,6 +711,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||||
emptyText: 'Žádný zákazník neodpovídá',
|
emptyText: 'Žádný zákazník neodpovídá',
|
||||||
onPick(item) {
|
onPick(item) {
|
||||||
select.value = item.value;
|
select.value = item.value;
|
||||||
|
fillOdberatel(item.value);
|
||||||
},
|
},
|
||||||
onClear() {
|
onClear() {
|
||||||
select.value = '';
|
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 = [];
|
let katalog = [];
|
||||||
try {
|
try {
|
||||||
katalog = JSON.parse(document.getElementById('katalog-polozek').textContent || '[]');
|
katalog = JSON.parse(document.getElementById('katalog-polozek').textContent || '[]');
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ class FirmaPresenter extends BasePresenter
|
||||||
'banka_kod' => $firma->BANKA_KOD,
|
'banka_kod' => $firma->BANKA_KOD,
|
||||||
'iban' => $firma->IBAN,
|
'iban' => $firma->IBAN,
|
||||||
'bic' => $firma->BIC,
|
'bic' => $firma->BIC,
|
||||||
|
'web' => $firma->WEB ?? null,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -67,6 +68,8 @@ class FirmaPresenter extends BasePresenter
|
||||||
// Kontakty
|
// Kontakty
|
||||||
$form->addText('telefon', 'Telefon:');
|
$form->addText('telefon', 'Telefon:');
|
||||||
$form->addEmail('email', 'E-mail:');
|
$form->addEmail('email', 'E-mail:');
|
||||||
|
$form->addText('web', 'Web:')
|
||||||
|
->setMaxLength(100);
|
||||||
|
|
||||||
// Sídlo
|
// Sídlo
|
||||||
$form->addText('ulice', 'Ulice a ČP:');
|
$form->addText('ulice', 'Ulice a ČP:');
|
||||||
|
|
@ -100,6 +103,7 @@ class FirmaPresenter extends BasePresenter
|
||||||
'PLATCE_DPH' => 0,
|
'PLATCE_DPH' => 0,
|
||||||
'TELEFON' => $data->telefon,
|
'TELEFON' => $data->telefon,
|
||||||
'EMAIL' => $data->email,
|
'EMAIL' => $data->email,
|
||||||
|
'WEB' => $data->web !== '' ? $data->web : null,
|
||||||
'ULICE' => $data->ulice,
|
'ULICE' => $data->ulice,
|
||||||
'MESTO' => $data->mesto,
|
'MESTO' => $data->mesto,
|
||||||
'PSC' => $data->psc,
|
'PSC' => $data->psc,
|
||||||
|
|
|
||||||
|
|
@ -54,14 +54,18 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row mt-2">
|
<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>
|
<label n:name="telefon">Telefon</label>
|
||||||
<input n:name="telefon" class="form-control">
|
<input n:name="telefon" class="form-control">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 form-group">
|
<div class="col-md-4 form-group">
|
||||||
<label n:name="email">E-mail</label>
|
<label n:name="email">E-mail</label>
|
||||||
<input n:name="email" class="form-control">
|
<input n:name="email" class="form-control">
|
||||||
</div>
|
</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>
|
</div>
|
||||||
|
|
||||||
<!-- BANKA -->
|
<!-- BANKA -->
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,7 @@ CREATE TABLE [dbo].[FIRMA] (
|
||||||
-- Kontaktní údaje
|
-- Kontaktní údaje
|
||||||
[TELEFON] [nvarchar](20) NULL,
|
[TELEFON] [nvarchar](20) NULL,
|
||||||
[EMAIL] [nvarchar](100) NULL,
|
[EMAIL] [nvarchar](100) NULL,
|
||||||
|
[WEB] [nvarchar](100) NULL,
|
||||||
|
|
||||||
-- Sídlo
|
-- Sídlo
|
||||||
[ULICE] [nvarchar](100) NULL,
|
[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