DB a Factory pro databázi.
parent
5c5b5b81d8
commit
ea6ada8ce6
|
|
@ -0,0 +1,69 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Model\Database;
|
||||||
|
|
||||||
|
use Nette\Database\Connection;
|
||||||
|
use Nette\Database\Explorer;
|
||||||
|
use Nette\Database\Structure;
|
||||||
|
use Nette\Caching\Storages\MemoryStorage;
|
||||||
|
use Nette\Security\User;
|
||||||
|
|
||||||
|
class KufrikConnectionFactory
|
||||||
|
{
|
||||||
|
private User $user;
|
||||||
|
private array $baseConfig;
|
||||||
|
|
||||||
|
public function __construct(array $baseConfig, User $user)
|
||||||
|
{
|
||||||
|
$this->baseConfig = $baseConfig;
|
||||||
|
$this->user = $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createConnection(): Connection
|
||||||
|
{
|
||||||
|
if (!$this->user->isLoggedIn()) {
|
||||||
|
throw new \LogicException('Uživatel není přihlášen.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$identity = $this->user->getIdentity();
|
||||||
|
|
||||||
|
// 1. Dynamické načtení z identity (každý uživatel může mít jiný server i DB!)
|
||||||
|
$host = $identity->db_host ?? $this->baseConfig['host'];
|
||||||
|
$databaseName = $identity->db_name ?? $this->baseConfig['default_db'];
|
||||||
|
$firmaId = $identity->firma_id ?? null;
|
||||||
|
|
||||||
|
if (!$firmaId) {
|
||||||
|
throw new \LogicException('Uživatel nemá zvolenou žádnou aktivní firmu.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Sestavení DSN pro konkrétní SQL Server a DB
|
||||||
|
$dsn = "sqlsrv:Server={$host};Database={$databaseName}";
|
||||||
|
|
||||||
|
// Přihlašovací údaje k SQL serveru (buď společné ze souboru, nebo dynamické)
|
||||||
|
$connection = new Connection(
|
||||||
|
$dsn,
|
||||||
|
$this->baseConfig['username'],
|
||||||
|
$this->baseConfig['password'],
|
||||||
|
[
|
||||||
|
'lazy' => false,
|
||||||
|
'driverOptions' => [
|
||||||
|
\PDO::SQLSRV_ATTR_ENCODING => \PDO::SQLSRV_ENCODING_UTF8,
|
||||||
|
]
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// 3. Nastavení RLS kontextu pro firmu
|
||||||
|
$connection->query('EXEC sp_set_session_context @key = N\'FirmaId\', @value = ?', $firmaId);
|
||||||
|
|
||||||
|
return $connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createExplorer(): Explorer
|
||||||
|
{
|
||||||
|
$connection = $this->createConnection();
|
||||||
|
$storage = new MemoryStorage();
|
||||||
|
$structure = new Structure($connection, $storage);
|
||||||
|
|
||||||
|
return new Explorer($connection, $structure);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Model\Security;
|
||||||
|
|
||||||
|
use Nette\Security\IAuthenticator;
|
||||||
|
use Nette\Security\SimpleIdentity;
|
||||||
|
use Nette\Security\AuthenticationException;
|
||||||
|
use Nette\Security\Passwords;
|
||||||
|
use Nette\Database\Connection;
|
||||||
|
|
||||||
|
class Authenticator implements IAuthenticator
|
||||||
|
{
|
||||||
|
private Connection $masterDb;
|
||||||
|
private Passwords $passwords;
|
||||||
|
|
||||||
|
public function __construct(Connection $masterDb, Passwords $passwords)
|
||||||
|
{
|
||||||
|
$this->masterDb = $masterDb;
|
||||||
|
$this->passwords = $passwords;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function authenticate(string $user, string $password): SimpleIdentity
|
||||||
|
{
|
||||||
|
// 1. Dotaz do centrální Master DB
|
||||||
|
$row = $this->masterDb->fetch(
|
||||||
|
'SELECT ID, EMAIL, HESLO_HASH, JMENO, PRIJMENI, DATABASE_HOST, DATABASE_NAME, DEFAULT_FIRMA_ID
|
||||||
|
FROM dbo.UZIVATEL
|
||||||
|
WHERE EMAIL = ? AND AKTIVNI = 1',
|
||||||
|
$user
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!$row || !$this->passwords->verify($password, $row->HESLO_HASH)) {
|
||||||
|
throw new AuthenticationException('Nespravný e-mail nebo heslo.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Všechny potřebné parametry pro KufrikConnectionFactory zabalíme do Nette Identity
|
||||||
|
return new SimpleIdentity(
|
||||||
|
$row->ID,
|
||||||
|
null, // role (volitelně)
|
||||||
|
[
|
||||||
|
'email' => $row->EMAIL,
|
||||||
|
'jmeno' => $row->JMENO . ' ' . $row->PRIJMENI,
|
||||||
|
// Kufrik parametry:
|
||||||
|
'db_host' => $row->DATABASE_HOST ?? '127.0.0.1', // Umožňuje i RŮZNÉ SERVERY!
|
||||||
|
'db_name' => $row->DATABASE_NAME ?? 'Fakturace_MainDB',
|
||||||
|
'firma_id' => $row->DEFAULT_FIRMA_ID,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,136 +1,60 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\UI\Sign;
|
namespace App\UI\Sign;
|
||||||
|
|
||||||
use App\Core\MujAutentifikator;
|
use Nette\Application\UI\Presenter;
|
||||||
use App\Model\FormData\LoginFormData;
|
|
||||||
use App\Model\Login\ServerCredentials;
|
|
||||||
use Nette;
|
|
||||||
use Nette\Application\UI\Form;
|
use Nette\Application\UI\Form;
|
||||||
use Nette\Application\Attributes\Persistent;
|
use Nette\Security\AuthenticationException;
|
||||||
|
|
||||||
final class SignPresenter extends Nette\Application\UI\Presenter
|
class SignPresenter extends Presenter
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Stores the previous page hash to redirect back after successful login.
|
* Vytvoření přihlašovacího formuláře
|
||||||
*/
|
*/
|
||||||
#[Persistent]
|
protected function createComponentSignInForm(): Form
|
||||||
public string $backlink = '';
|
{
|
||||||
|
$form = new Form();
|
||||||
|
|
||||||
public function __construct(
|
$form->addEmail('email', 'E-mail:')
|
||||||
) {
|
->setRequired('Zadejte prosím váš e-mail.')
|
||||||
}
|
->setHtmlAttribute('placeholder', 'jan@novak.cz');
|
||||||
|
|
||||||
protected function createComponentSignInForm(): Form
|
$form->addPassword('password', 'Heslo:')
|
||||||
{
|
->setRequired('Zadejte prosím heslo.');
|
||||||
$form = new Form();
|
|
||||||
$form->addText('server', 'Server:')
|
|
||||||
->setRequired('Prosím vyplňte server.')
|
|
||||||
->setValue(@$_COOKIE['server']);
|
|
||||||
|
|
||||||
$form->addText('username', 'Uživatelské jméno:')
|
$form->addSubmit('send', 'Přihlásit se');
|
||||||
->setRequired('Prosím vyplňte své uživatelské jméno.')
|
|
||||||
->setValue(@$_COOKIE['user']);
|
|
||||||
|
|
||||||
$form->addPassword('password', 'Heslo:');
|
$form->onSuccess[] = [$this, 'signInFormSucceeded'];
|
||||||
// setRequired nepoužívat!! kvůli soft logoutu!!!
|
|
||||||
//->setRequired('Prosím vyplňte své heslo.');
|
|
||||||
|
|
||||||
$form->addSubmit('send', 'Přihlásit');
|
return $form;
|
||||||
//$form->addProtection(); //ochrana pomocí TOKENu
|
}
|
||||||
|
|
||||||
$form->onSuccess[] = $this->signInFormSucceeded(...);
|
/**
|
||||||
return $form;
|
* Zpracování formuláře po odeslání
|
||||||
}
|
*/
|
||||||
|
public function signInFormSucceeded(Form $form, \stdClass $data): void
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
// Zavolá náš Authenticator spojený s Master DB
|
||||||
|
$this->getUser()->login($data->email, $data->password);
|
||||||
|
|
||||||
private function signInFormSucceeded(Form $form, LoginFormData $data): void //moje vlastní třída LoginFormData
|
$this->flashMessage('Přihlášení proběhlo úspěšně.', 'success');
|
||||||
{
|
|
||||||
try {
|
|
||||||
// kontrola serverů:
|
|
||||||
if (!Funkce::is_cloud_ip($data->server)) {
|
|
||||||
error_log("QR Login - neplatny server.", 0); //log je ve var/log/apache2/error.log (fail2ban)
|
|
||||||
$form->addError('Neznámý server.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sestav Credentials:
|
// Přesměrování do hlavní části aplikace (např. HomePresenter)
|
||||||
$credentials = new ServerCredentials($data->server);
|
$this->redirect('Home:');
|
||||||
|
|
||||||
$autentifikator = new MujAutentifikator($credentials, $this->session); // naše vlastní autentifikace!
|
} catch (AuthenticationException $e) {
|
||||||
$this->getUser()->setAuthenticator($autentifikator); // musíme ji registrovat!
|
$form->addError('Nespravný e-mail nebo heslo.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$blacklist_check = $this->blackList->blacklist_check($data->server);
|
/**
|
||||||
bdump($blacklist_check);
|
* Akce pro odhlášení
|
||||||
if (is_null($blacklist_check)) {
|
*/
|
||||||
//nic, jako by prošel
|
public function actionOut(): void
|
||||||
} else {
|
{
|
||||||
// $blacklist_check->vysledek Returns 1, pokud není blacklistu. Když se tam nachází, tak 0.
|
$this->getUser()->logout(true); // smaže i identitu
|
||||||
// $blacklist_check->expire_date Kdy končí.
|
$this->flashMessage('Byli jste úspěšně odhlášeni.', 'info');
|
||||||
// $blacklist_check->expired_text Co jim zahlásíš.
|
$this->redirect('in');
|
||||||
if ($blacklist_check->vysledek == 0) {
|
}
|
||||||
setcookie("salt", "", time() - 3600); // smažeme v tomto případě kukínu ...
|
|
||||||
if (empty($blacklist_check->expired_text))
|
|
||||||
throw new BlackListException("Licence pro použití PečAppky vypršela, nebo nám dlužíte peníze.");
|
|
||||||
else
|
|
||||||
throw new BlackListException($blacklist_check->expired_text); // custom text z blacklist DB
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// uložené heslo?
|
|
||||||
if (empty($data->password) and isset($_COOKIE['salt'])) {
|
|
||||||
$password = Funkce::decrypt_password($_COOKIE['salt']);
|
|
||||||
} else {
|
|
||||||
$password = $data->password;
|
|
||||||
}
|
|
||||||
// validace přihlášení je v třídě MujAutentifikator->authenticate(...)
|
|
||||||
$this->getUser()->login($data->username, $password);
|
|
||||||
|
|
||||||
// kam potom?
|
|
||||||
$this->restoreRequest($this->backlink); // vrátit se na požadovanou stránku
|
|
||||||
$this->redirect(':Ctecka:'); // jinak přejdi sem
|
|
||||||
} catch (Nette\Database\ConnectionException) {
|
|
||||||
error_log("QR Login - neplatne prihlaseni.", 0); //log je ve var/log/apache2/error.log (fail2ban)
|
|
||||||
$form->addError('Neplatné přihlášení.');
|
|
||||||
} catch (Nette\Security\AuthenticationException $e) {
|
|
||||||
error_log("QR Login - neplatne prihlaseni.", 0); //log je ve var/log/apache2/error.log (fail2ban)
|
|
||||||
$form->addError($e->getMessage());
|
|
||||||
} catch (BlackListException $e2) {
|
|
||||||
$form->addError($e2->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function renderIn(): void
|
|
||||||
{
|
|
||||||
// ukázat či neukázat pole pro heslo?
|
|
||||||
$this->template->salt = isset($_COOKIE['salt']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Normalní logout.
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function actionOut(): void
|
|
||||||
{
|
|
||||||
$this->getUser()->logout();
|
|
||||||
$this->flashMessage('Odhlášení bylo úspěšné.');
|
|
||||||
$this->redirect('Sign:in');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tvrdý logout.
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function actionHardOut(): void
|
|
||||||
{
|
|
||||||
$this->getUser()->logout();
|
|
||||||
setcookie("salt", "", time() - 3600); // smažeme v tomto případě kukínu ...
|
|
||||||
|
|
||||||
// smažeme vybranou DB ze session:
|
|
||||||
if ($this->session->hasSection(Konstanty::sectionDatabase)) {
|
|
||||||
$section = $this->session->getSection(Konstanty::sectionDatabase);
|
|
||||||
$section->remove(Konstanty::sessionCurrentDatabase);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->flashMessage('Odhlášení bylo úspěšné.');
|
|
||||||
$this->redirect('Sign:in');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,10 @@
|
||||||
parameters:
|
parameters:
|
||||||
|
# Přihlašovací údaje ke klientským DB serverům
|
||||||
|
mssql:
|
||||||
|
host: "localhost" # Výchozí záložní host
|
||||||
|
username: "kufrik"
|
||||||
|
password: "giteaKufrik_2026!"
|
||||||
|
default_db: "kufrik"
|
||||||
|
|
||||||
|
|
||||||
application:
|
application:
|
||||||
|
|
@ -9,10 +15,10 @@ application:
|
||||||
|
|
||||||
|
|
||||||
database:
|
database:
|
||||||
dsn: 'sqlsrv:server=kmetix.cz;Database=kufrik;LoginTimeout=6;'
|
dsn: 'sqlsrv:server=localhost;Database=kufrik;LoginTimeout=3;'
|
||||||
user: 'kufrik'
|
user: 'kufrik'
|
||||||
password: 'giteaKufrik_2024'
|
password: 'giteaKufrik_2026!'
|
||||||
|
autowired: false # Vypnuto, abychom jako výchozí Explorer používali kufrikExplorer
|
||||||
|
|
||||||
latte:
|
latte:
|
||||||
strictTypes: yes
|
strictTypes: yes
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,20 @@ services:
|
||||||
|
|
||||||
security.passwords: Nette\Security\Passwords(::PASSWORD_BCRYPT, [cost: 12])
|
security.passwords: Nette\Security\Passwords(::PASSWORD_BCRYPT, [cost: 12])
|
||||||
|
|
||||||
|
# Authenticator si vyžádá připojení k Master DB
|
||||||
|
- App\Model\Security\Authenticator(@database.default.connection)
|
||||||
|
|
||||||
|
# Konfigurace pro klientskou KufrikConnectionFactory
|
||||||
|
kufrikConnectionFactory:
|
||||||
|
factory: App\Model\Database\KufrikConnectionFactory
|
||||||
|
arguments:
|
||||||
|
baseConfig: %mssql%
|
||||||
|
|
||||||
|
# Hlavní databázový Explorer pro aplikaci
|
||||||
|
kufrikExplorer:
|
||||||
|
type: Nette\Database\Explorer
|
||||||
|
factory: @App\Model\Database\KufrikConnectionFactory::createExplorer()
|
||||||
|
|
||||||
search:
|
search:
|
||||||
- in: %appDir%
|
- in: %appDir%
|
||||||
classes:
|
classes:
|
||||||
|
|
|
||||||
409
sql/KufrikDB.sql
409
sql/KufrikDB.sql
|
|
@ -1,206 +1,239 @@
|
||||||
CREATE DATABASE [kufrik]
|
use master
|
||||||
CONTAINMENT = NONE
|
|
||||||
ON PRIMARY
|
|
||||||
( NAME = N'kufrik', FILENAME = N'/var/opt/mssql/data/kufrik.mdf' , SIZE = 8192KB , FILEGROWTH = 65536KB )
|
|
||||||
LOG ON
|
|
||||||
( NAME = N'kufrik_log', FILENAME = N'/var/opt/mssql/data/kufrik_log.ldf' , SIZE = 8192KB , FILEGROWTH = 65536KB )
|
|
||||||
GO
|
GO
|
||||||
ALTER DATABASE [kufrik] SET COMPATIBILITY_LEVEL = 150
|
|
||||||
|
DROP TABLE [kufrik]
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE DATABASE [kufrik]
|
||||||
|
-- CONTAINMENT = NONE
|
||||||
|
-- ON PRIMARY
|
||||||
|
--( NAME = N'kufrik', FILENAME = N'/var/opt/mssql/data/kufrik.mdf' , SIZE = 8192KB , FILEGROWTH = 65536KB )
|
||||||
|
-- LOG ON
|
||||||
|
--( NAME = N'kufrik_log', FILENAME = N'/var/opt/mssql/data/kufrik_log.ldf' , SIZE = 8192KB , FILEGROWTH = 65536KB )
|
||||||
|
GO
|
||||||
|
ALTER DATABASE [kufrik] SET COMPATIBILITY_LEVEL = 160
|
||||||
|
GO
|
||||||
|
|
||||||
|
--Pokud je AUTO_CLOSE zapnuté (ON), databáze se po odpojení posledního uživatele kompletně uzavře a uvolní paměť. Při dalším požadavku se pak musí znovu otevírat, což způsobuje výrazné zpoždění (latenci) prvního dotazu a zbytečnou zátěž na disk a CPU.
|
||||||
|
ALTER DATABASE [kufrik] SET AUTO_CLOSE OFF WITH NO_WAIT;
|
||||||
GO
|
GO
|
||||||
|
|
||||||
--user:
|
--user:
|
||||||
USE [master]
|
USE [master]
|
||||||
GO
|
GO
|
||||||
CREATE LOGIN [kufrik] WITH PASSWORD=N'giteaKufrik_2024', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
|
CREATE LOGIN [kufrik] WITH PASSWORD=N'giteaKufrik_2026!', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
|
||||||
GO
|
|
||||||
use [master];
|
|
||||||
GO
|
GO
|
||||||
USE [kufrik]
|
USE [kufrik]
|
||||||
GO
|
GO
|
||||||
CREATE USER [kufrik] FOR LOGIN [kufrik]
|
CREATE USER [kufrik] FOR LOGIN [kufrik]
|
||||||
GO
|
GO
|
||||||
USE [kufrik]
|
|
||||||
GO
|
|
||||||
ALTER USER [kufrik] WITH DEFAULT_SCHEMA=[dbo]
|
ALTER USER [kufrik] WITH DEFAULT_SCHEMA=[dbo]
|
||||||
GO
|
GO
|
||||||
USE [kufrik]
|
|
||||||
GO
|
|
||||||
ALTER ROLE [db_owner] ADD MEMBER [kufrik]
|
ALTER ROLE [db_owner] ADD MEMBER [kufrik]
|
||||||
GO
|
GO
|
||||||
|
|
||||||
USE [kufrik]
|
-- 1. PŘIHLAŠOVACÍ ÚČET (Fyzická osoba)
|
||||||
GO
|
CREATE TABLE [dbo].[UZIVATEL] (
|
||||||
/****** Object: Table [dbo].[FAKTURA] Script Date: 31.07.2026 9:05:46 ******/
|
[ID] [int] IDENTITY(1,1) NOT NULL,
|
||||||
SET ANSI_NULLS ON
|
[EMAIL] [nvarchar](100) NOT NULL,
|
||||||
GO
|
[HESLO_HASH] [nvarchar](255) NOT NULL,
|
||||||
SET QUOTED_IDENTIFIER ON
|
[JMENO] [nvarchar](100) NULL,
|
||||||
GO
|
[PRIJMENI] [nvarchar](100) NULL,
|
||||||
CREATE TABLE [dbo].[FAKTURA](
|
[TELEFON] [nvarchar](20) NULL,
|
||||||
[ID] [int] IDENTITY(15,1) NOT NULL,
|
[POSLEDNI_PRIHLASENI] [datetime2](7) NULL,
|
||||||
[DATUM_VYSTAVENI] [datetime] NOT NULL,
|
[AKTIVNI] [bit] NOT NULL DEFAULT 1,
|
||||||
[DATUM_SPLATNOSTI] [datetime] NOT NULL,
|
CONSTRAINT [PK_UZIVATEL] PRIMARY KEY CLUSTERED ([ID] ASC),
|
||||||
[ZAKAZNIK] [int] NOT NULL,
|
CONSTRAINT [UQ_UZIVATEL_EMAIL] UNIQUE ([EMAIL])
|
||||||
[CISLO] [nvarchar](20) NOT NULL,
|
);
|
||||||
[D_PRAJM] [nvarchar](511) NULL,
|
|
||||||
[D_ULICE] [nvarchar](50) NULL,
|
ALTER TABLE [dbo].[UZIVATEL] ADD
|
||||||
[D_MESTO] [nvarchar](50) NULL,
|
-- Identifikátor nebo název cílové databáze
|
||||||
[D_PSC] [nvarchar](50) NULL,
|
[DATABASE_NAME] [nvarchar](128) NULL,
|
||||||
[D_IC] [nvarchar](8) NULL,
|
-- Volitelně celý connection string (nebo klíč do konfigurace aplikace)
|
||||||
[D_DIC] [nvarchar](10) NULL,
|
[CONNECTION_STRING_KEY] [nvarchar](100) NULL;
|
||||||
[D_BANKA] [nvarchar](100) NULL,
|
|
||||||
[D_TELEFON] [nvarchar](15) NULL,
|
|
||||||
[D_EMAIL] [nvarchar](100) NULL,
|
|
||||||
[D_WEB] [nvarchar](100) NULL,
|
|
||||||
[O_PRAJM] [nvarchar](511) NULL,
|
|
||||||
[O_ULICE] [nvarchar](50) NULL,
|
|
||||||
[O_MESTO] [nvarchar](50) NULL,
|
|
||||||
[O_PSC] [nvarchar](5) NULL,
|
|
||||||
[O_IC] [nvarchar](8) NULL,
|
|
||||||
[O_DIC] [nvarchar](10) NULL,
|
|
||||||
[FORMA_UHRADY] [tinyint] NOT NULL,
|
|
||||||
[CISLO_ABS] [int] NOT NULL,
|
|
||||||
[CINNOSTI] [ntext] NULL,
|
|
||||||
CONSTRAINT [PK_FAKTURA] PRIMARY KEY CLUSTERED
|
|
||||||
(
|
|
||||||
[ID] ASC
|
|
||||||
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
|
|
||||||
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
|
|
||||||
GO
|
|
||||||
/****** Object: Table [dbo].[KONFIGURACE] Script Date: 31.07.2026 9:05:46 ******/
|
|
||||||
SET ANSI_NULLS ON
|
|
||||||
GO
|
|
||||||
SET QUOTED_IDENTIFIER ON
|
|
||||||
GO
|
|
||||||
CREATE TABLE [dbo].[KONFIGURACE](
|
|
||||||
[ID] [int] IDENTITY(2,1) NOT NULL,
|
|
||||||
[DATA] [ntext] NULL,
|
|
||||||
CONSTRAINT [PK_KONFIGURACE] PRIMARY KEY CLUSTERED
|
|
||||||
(
|
|
||||||
[ID] ASC
|
|
||||||
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
|
|
||||||
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
|
|
||||||
GO
|
|
||||||
/****** Object: Table [dbo].[PLATBA] Script Date: 31.07.2026 9:05:46 ******/
|
|
||||||
SET ANSI_NULLS ON
|
|
||||||
GO
|
|
||||||
SET QUOTED_IDENTIFIER ON
|
|
||||||
GO
|
|
||||||
CREATE TABLE [dbo].[PLATBA](
|
|
||||||
[ID] [int] IDENTITY(11,1) NOT NULL,
|
|
||||||
[FAKTURA] [int] NOT NULL,
|
|
||||||
[CASTKA] [money] NOT NULL,
|
|
||||||
[DATUM] [datetime] NOT NULL,
|
|
||||||
[POZNAMKA] [ntext] NULL,
|
|
||||||
CONSTRAINT [PK_PLATBA] PRIMARY KEY CLUSTERED
|
|
||||||
(
|
|
||||||
[ID] ASC
|
|
||||||
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
|
|
||||||
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
|
|
||||||
GO
|
|
||||||
/****** Object: Table [dbo].[POLOZKA] Script Date: 31.07.2026 9:05:46 ******/
|
|
||||||
SET ANSI_NULLS ON
|
|
||||||
GO
|
|
||||||
SET QUOTED_IDENTIFIER ON
|
|
||||||
GO
|
|
||||||
CREATE TABLE [dbo].[POLOZKA](
|
|
||||||
[ID] [int] IDENTITY(24,1) NOT NULL,
|
|
||||||
[FAKTURA] [int] NOT NULL,
|
|
||||||
[NAZEV] [nvarchar](255) NOT NULL,
|
|
||||||
[POCET] [float] NOT NULL,
|
|
||||||
[CENA_JEDNOTKA] [money] NOT NULL,
|
|
||||||
[SLEVA] [real] NULL,
|
|
||||||
[CENA] [money] NOT NULL,
|
|
||||||
[JEDNOTKA] [nvarchar](5) NULL,
|
|
||||||
CONSTRAINT [PK_POLOZKA] PRIMARY KEY CLUSTERED
|
|
||||||
(
|
|
||||||
[ID] ASC
|
|
||||||
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
|
|
||||||
) ON [PRIMARY]
|
|
||||||
GO
|
|
||||||
/****** Object: Table [dbo].[UZIVATEL] Script Date: 31.07.2026 9:05:46 ******/
|
|
||||||
SET ANSI_NULLS ON
|
|
||||||
GO
|
|
||||||
SET QUOTED_IDENTIFIER ON
|
|
||||||
GO
|
|
||||||
CREATE TABLE [dbo].[UZIVATEL](
|
|
||||||
[ID] [int] IDENTITY(2,1) NOT NULL,
|
|
||||||
[JMENO] [nvarchar](255) NULL,
|
|
||||||
[PRIJMENI] [nvarchar](255) NOT NULL,
|
|
||||||
[ULICE] [nvarchar](50) NULL,
|
|
||||||
[MESTO] [nvarchar](50) NULL,
|
|
||||||
[PSC] [nvarchar](5) NULL,
|
|
||||||
[IC] [nvarchar](8) NULL,
|
|
||||||
[DIC] [nvarchar](10) NULL,
|
|
||||||
[TELEFON] [nvarchar](15) NULL,
|
|
||||||
[EMAIL] [nvarchar](100) NULL,
|
|
||||||
[BANKA] [nvarchar](100) NULL,
|
|
||||||
[WEB] [nvarchar](100) NULL,
|
|
||||||
CONSTRAINT [PK_UZIVATEL] PRIMARY KEY CLUSTERED
|
|
||||||
(
|
|
||||||
[ID] ASC
|
|
||||||
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
|
|
||||||
) ON [PRIMARY]
|
|
||||||
GO
|
|
||||||
/****** Object: Table [dbo].[VERZE] Script Date: 31.07.2026 9:05:46 ******/
|
|
||||||
SET ANSI_NULLS ON
|
|
||||||
GO
|
|
||||||
SET QUOTED_IDENTIFIER ON
|
|
||||||
GO
|
|
||||||
CREATE TABLE [dbo].[VERZE](
|
|
||||||
[ID] [int] IDENTITY(15,1) NOT NULL,
|
|
||||||
[VERZE] [smallint] NOT NULL,
|
|
||||||
[DATUM] [datetime] NOT NULL,
|
|
||||||
CONSTRAINT [PK_VERZE] PRIMARY KEY CLUSTERED
|
|
||||||
(
|
|
||||||
[ID] ASC
|
|
||||||
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY],
|
|
||||||
CONSTRAINT [UQ__VERZE__ID] UNIQUE NONCLUSTERED
|
|
||||||
(
|
|
||||||
[ID] ASC
|
|
||||||
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY],
|
|
||||||
CONSTRAINT [UQ__VERZE__VERZE] UNIQUE NONCLUSTERED
|
|
||||||
(
|
|
||||||
[VERZE] ASC
|
|
||||||
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
|
|
||||||
) ON [PRIMARY]
|
|
||||||
GO
|
|
||||||
/****** Object: Table [dbo].[ZAKAZNIK] Script Date: 31.07.2026 9:05:46 ******/
|
|
||||||
SET ANSI_NULLS ON
|
|
||||||
GO
|
|
||||||
SET QUOTED_IDENTIFIER ON
|
|
||||||
GO
|
|
||||||
CREATE TABLE [dbo].[ZAKAZNIK](
|
|
||||||
[ID] [int] IDENTITY(2,1) NOT NULL,
|
|
||||||
[JMENO] [nvarchar](255) NULL,
|
|
||||||
[PRIJMENI] [nvarchar](255) NOT NULL,
|
|
||||||
[ULICE] [nvarchar](50) NULL,
|
|
||||||
[MESTO] [nvarchar](50) NULL,
|
|
||||||
[PSC] [nvarchar](5) NULL,
|
|
||||||
[IC] [nvarchar](8) NULL,
|
|
||||||
[DIC] [nvarchar](10) NULL,
|
|
||||||
[TELEFON] [nvarchar](15) NULL,
|
|
||||||
[EMAIL] [nvarchar](100) NULL,
|
|
||||||
CONSTRAINT [PK_ZAKAZNIK] PRIMARY KEY CLUSTERED
|
|
||||||
(
|
|
||||||
[ID] ASC
|
|
||||||
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
|
|
||||||
) ON [PRIMARY]
|
|
||||||
GO
|
|
||||||
ALTER TABLE [dbo].[FAKTURA] ADD DEFAULT ((1)) FOR [FORMA_UHRADY]
|
|
||||||
GO
|
|
||||||
ALTER TABLE [dbo].[FAKTURA] WITH CHECK ADD CONSTRAINT [FK_ZAKAZNIK] FOREIGN KEY([ZAKAZNIK])
|
|
||||||
REFERENCES [dbo].[ZAKAZNIK] ([ID])
|
|
||||||
GO
|
|
||||||
ALTER TABLE [dbo].[FAKTURA] CHECK CONSTRAINT [FK_ZAKAZNIK]
|
|
||||||
GO
|
|
||||||
ALTER TABLE [dbo].[PLATBA] WITH CHECK ADD CONSTRAINT [FK_PLATBA_FAKTURA] FOREIGN KEY([FAKTURA])
|
|
||||||
REFERENCES [dbo].[FAKTURA] ([ID])
|
|
||||||
GO
|
|
||||||
ALTER TABLE [dbo].[PLATBA] CHECK CONSTRAINT [FK_PLATBA_FAKTURA]
|
|
||||||
GO
|
|
||||||
ALTER TABLE [dbo].[POLOZKA] WITH CHECK ADD CONSTRAINT [FK_PLOZKA_FAKTURA] FOREIGN KEY([FAKTURA])
|
|
||||||
REFERENCES [dbo].[FAKTURA] ([ID])
|
|
||||||
GO
|
|
||||||
ALTER TABLE [dbo].[POLOZKA] CHECK CONSTRAINT [FK_PLOZKA_FAKTURA]
|
|
||||||
GO
|
GO
|
||||||
|
|
||||||
|
-- 2. FIRMA / OSVČ (Fakturační jednotka = TENANT)
|
||||||
|
CREATE TABLE [dbo].[FIRMA] (
|
||||||
|
[ID] [int] IDENTITY(1,1) NOT NULL,
|
||||||
|
[NAZEV] [nvarchar](255) NOT NULL, -- Jméno a příjmení OSVČ nebo název s.r.o.
|
||||||
|
[IC] [nvarchar](8) NULL,
|
||||||
|
[DIC] [nvarchar](12) NULL,
|
||||||
|
[PLATCE_DPH] [bit] NOT NULL DEFAULT 1,
|
||||||
|
|
||||||
|
-- Sídlo
|
||||||
|
[ULICE] [nvarchar](100) NULL,
|
||||||
|
[MESTO] [nvarchar](100) NULL,
|
||||||
|
[PSC] [nvarchar](10) NULL,
|
||||||
|
[ZEME_KOD] [nvarchar](2) NOT NULL DEFAULT 'CZ',
|
||||||
|
|
||||||
|
-- Banka pro fakturaci
|
||||||
|
[CISLO_UCTU] [nvarchar](30) NULL,
|
||||||
|
[BANKA_KOD] [nvarchar](10) NULL,
|
||||||
|
[IBAN] [nvarchar](34) NULL,
|
||||||
|
[BIC] [nvarchar](11) NULL,
|
||||||
|
|
||||||
|
[DATUM_VYTVORENI] [datetime2](7) NOT NULL DEFAULT SYSDATETIME(),
|
||||||
|
CONSTRAINT [PK_FIRMA] PRIMARY KEY CLUSTERED ([ID] ASC)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 3. VAZBA UŽIVATEL <-> FIRMA (Práva k firmám)
|
||||||
|
CREATE TABLE [dbo].[UZIVATEL_FIRMA] (
|
||||||
|
[UZIVATEL_ID] [int] NOT NULL,
|
||||||
|
[FIRMA_ID] [int] NOT NULL,
|
||||||
|
[ROLE] [nvarchar](20) NOT NULL DEFAULT 'OWNER', -- 'OWNER', 'ACCOUNTANT', 'READONLY'
|
||||||
|
CONSTRAINT [PK_UZIVATEL_FIRMA] PRIMARY KEY CLUSTERED ([UZIVATEL_ID], [FIRMA_ID]),
|
||||||
|
CONSTRAINT [FK_UF_UZIVATEL] FOREIGN KEY ([UZIVATEL_ID]) REFERENCES [dbo].[UZIVATEL] ([ID]),
|
||||||
|
CONSTRAINT [FK_UF_FIRMA] FOREIGN KEY ([FIRMA_ID]) REFERENCES [dbo].[FIRMA] ([ID])
|
||||||
|
);
|
||||||
|
|
||||||
|
-- ==========================================
|
||||||
|
-- 1. ZÁKAZNÍCI / ODBĚRATELÉ (vázaní na Firmu)
|
||||||
|
-- ==========================================
|
||||||
|
CREATE TABLE [dbo].[ZAKAZNIK](
|
||||||
|
[ID] [int] IDENTITY(2,1) NOT NULL,
|
||||||
|
[FIRMA_ID] [int] NOT NULL, -- Izolace dat (Tenant)
|
||||||
|
[JMENO] [nvarchar](255) NULL,
|
||||||
|
[PRIJMENI] [nvarchar](255) NOT NULL,
|
||||||
|
[ULICE] [nvarchar](50) NULL,
|
||||||
|
[MESTO] [nvarchar](50) NULL,
|
||||||
|
[PSC] [nvarchar](5) NULL,
|
||||||
|
[IC] [nvarchar](8) NULL,
|
||||||
|
[DIC] [nvarchar](10) NULL,
|
||||||
|
[TELEFON] [nvarchar](15) NULL,
|
||||||
|
[EMAIL] [nvarchar](100) NULL,
|
||||||
|
[AKTIVNI] [bit] NOT NULL CONSTRAINT [DF_ZAKAZNIK_AKTIVNI] DEFAULT ((1)),
|
||||||
|
|
||||||
|
CONSTRAINT [PK_ZAKAZNIK] PRIMARY KEY CLUSTERED ([ID] ASC),
|
||||||
|
CONSTRAINT [FK_ZAKAZNIK_FIRMA] FOREIGN KEY ([FIRMA_ID]) REFERENCES [dbo].[FIRMA] ([ID])
|
||||||
|
);
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE NONCLUSTERED INDEX [IX_ZAKAZNIK_FIRMA_ID] ON [dbo].[ZAKAZNIK]([FIRMA_ID] ASC);
|
||||||
|
GO
|
||||||
|
|
||||||
|
-- ==========================================
|
||||||
|
-- 2. HLAVIČKA FAKTURY
|
||||||
|
-- ==========================================
|
||||||
|
CREATE TABLE [dbo].[FAKTURA](
|
||||||
|
[ID] [int] IDENTITY(15,1) NOT NULL,
|
||||||
|
[FIRMA_ID] [int] NOT NULL, -- Izolace dat (Tenant)
|
||||||
|
[ZAKAZNIK] [int] NULL, -- Vazba na adresář (volitelná, pro historii)
|
||||||
|
|
||||||
|
[CISLO] [nvarchar](20) NOT NULL,
|
||||||
|
[CISLO_ABS] [int] NOT NULL, -- Sekvenční pořadové číslo v roce
|
||||||
|
[FORMA_UHRADY] [tinyint] NOT NULL CONSTRAINT [DF_FAKTURA_FORMA_UHRADY] DEFAULT ((1)),
|
||||||
|
|
||||||
|
[DATUM_VYSTAVENI] [date] NOT NULL,
|
||||||
|
[DATUM_SPLATNOSTI] [date] NOT NULL,
|
||||||
|
[DATUM_DUZP] [date] NULL, -- Doplněno pro DPH plnění
|
||||||
|
|
||||||
|
-- Snapshot Dodavatele (OSVČ / Firma v čase vystavení)
|
||||||
|
[D_PRAJM] [nvarchar](511) NULL,
|
||||||
|
[D_ULICE] [nvarchar](50) NULL,
|
||||||
|
[D_MESTO] [nvarchar](50) NULL,
|
||||||
|
[D_PSC] [nvarchar](50) NULL,
|
||||||
|
[D_IC] [nvarchar](8) NULL,
|
||||||
|
[D_DIC] [nvarchar](10) NULL,
|
||||||
|
[D_BANKA] [nvarchar](100) NULL,
|
||||||
|
[D_TELEFON] [nvarchar](15) NULL,
|
||||||
|
[D_EMAIL] [nvarchar](100) NULL,
|
||||||
|
[D_WEB] [nvarchar](100) NULL,
|
||||||
|
|
||||||
|
-- Snapshot Odběratele (Zákazník v čase vystavení)
|
||||||
|
[O_PRAJM] [nvarchar](511) NULL,
|
||||||
|
[O_ULICE] [nvarchar](50) NULL,
|
||||||
|
[O_MESTO] [nvarchar](50) NULL,
|
||||||
|
[O_PSC] [nvarchar](5) NULL,
|
||||||
|
[O_IC] [nvarchar](8) NULL,
|
||||||
|
[O_DIC] [nvarchar](10) NULL,
|
||||||
|
|
||||||
|
[CINNOSTI] [nvarchar](max) NULL, -- Nahrazeno ntext -> nvarchar(max)
|
||||||
|
[STAV] [nvarchar](20) NOT NULL CONSTRAINT [DF_FAKTURA_STAV] DEFAULT ('ISSUED'),
|
||||||
|
|
||||||
|
CONSTRAINT [PK_FAKTURA] PRIMARY KEY CLUSTERED ([ID] ASC),
|
||||||
|
CONSTRAINT [FK_FAKTURA_FIRMA] FOREIGN KEY ([FIRMA_ID]) REFERENCES [dbo].[FIRMA] ([ID]),
|
||||||
|
CONSTRAINT [FK_FAKTURA_ZAKAZNIK] FOREIGN KEY ([ZAKAZNIK]) REFERENCES [dbo].[ZAKAZNIK] ([ID]),
|
||||||
|
|
||||||
|
-- Číslo faktury je unikátní vždy jen v rámci jedné firmy
|
||||||
|
CONSTRAINT [UQ_FAKTURA_FIRMA_CISLO] UNIQUE ([FIRMA_ID], [CISLO])
|
||||||
|
);
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE NONCLUSTERED INDEX [IX_FAKTURA_FIRMA_DATUM] ON [dbo].[FAKTURA]([FIRMA_ID] ASC, [DATUM_VYSTAVENI] DESC);
|
||||||
|
GO
|
||||||
|
|
||||||
|
-- ==========================================
|
||||||
|
-- 3. POLOŽKY FAKTURY
|
||||||
|
-- ==========================================
|
||||||
|
CREATE TABLE [dbo].[POLOZKA](
|
||||||
|
[ID] [int] IDENTITY(24,1) NOT NULL,
|
||||||
|
[FAKTURA] [int] NOT NULL,
|
||||||
|
[FIRMA_ID] [int] NOT NULL, -- Duplikováno pro rychlé filtry a RLS
|
||||||
|
|
||||||
|
[NAZEV] [nvarchar](255) NOT NULL,
|
||||||
|
[POCET] [float] NOT NULL DEFAULT 1,
|
||||||
|
[JEDNOTKA] [nvarchar](10) NULL DEFAULT 'ks',
|
||||||
|
[CENA_JEDNOTKA] [money] NOT NULL,
|
||||||
|
[SLEVA] [real] NULL DEFAULT 0,
|
||||||
|
[CENA] [money] NOT NULL, -- Celková cena položky po slevě
|
||||||
|
|
||||||
|
CONSTRAINT [PK_POLOZKA] PRIMARY KEY CLUSTERED ([ID] ASC),
|
||||||
|
CONSTRAINT [FK_POLOZKA_FAKTURA] FOREIGN KEY ([FAKTURA]) REFERENCES [dbo].[FAKTURA] ([ID]) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT [FK_POLOZKA_FIRMA] FOREIGN KEY ([FIRMA_ID]) REFERENCES [dbo].[FIRMA] ([ID])
|
||||||
|
);
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE NONCLUSTERED INDEX [IX_POLOZKA_FAKTURA] ON [dbo].[POLOZKA]([FAKTURA] ASC);
|
||||||
|
GO
|
||||||
|
|
||||||
|
-- ==========================================
|
||||||
|
-- 4. ÚHRADY / PLATBY FAKTUR
|
||||||
|
-- ==========================================
|
||||||
|
CREATE TABLE [dbo].[PLATBA](
|
||||||
|
[ID] [int] IDENTITY(11,1) NOT NULL,
|
||||||
|
[FAKTURA] [int] NOT NULL,
|
||||||
|
[CASTKA] [money] NOT NULL,
|
||||||
|
[DATUM] [datetime2](7) NOT NULL DEFAULT SYSDATETIME(),
|
||||||
|
[POZNAMKA] [nvarchar](max) NULL, -- Nahrazeno ntext -> nvarchar(max)
|
||||||
|
|
||||||
|
CONSTRAINT [PK_PLATBA] PRIMARY KEY CLUSTERED ([ID] ASC),
|
||||||
|
CONSTRAINT [FK_PLATBA_FAKTURA] FOREIGN KEY ([FAKTURA]) REFERENCES [dbo].[FAKTURA] ([ID]) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
GO
|
||||||
|
|
||||||
|
CREATE NONCLUSTERED INDEX [IX_PLATBA_FAKTURA] ON [dbo].[PLATBA]([FAKTURA] ASC);
|
||||||
|
GO
|
||||||
|
|
||||||
|
|
||||||
|
-- ==========================================
|
||||||
|
-- 5. SECURITY
|
||||||
|
-- ==========================================
|
||||||
|
|
||||||
|
-- 1. Vytvoření schématu pro bezpečnostní objekty
|
||||||
|
CREATE SCHEMA Security;
|
||||||
|
GO
|
||||||
|
|
||||||
|
-- 2. Predikátová funkce pro kontrolu FirmaId
|
||||||
|
CREATE FUNCTION Security.fn_SecurityPredicate(@FirmaId INT)
|
||||||
|
RETURNS TABLE
|
||||||
|
WITH SCHEMABINDING
|
||||||
|
AS
|
||||||
|
RETURN SELECT 1 AS fn_SecurityPredicate_result
|
||||||
|
WHERE
|
||||||
|
-- Vyhodnotí se jako pravda pouze pokud se FIRMA_ID řádku shoduje se SESSION_CONTEXTu
|
||||||
|
@FirmaId = CAST(SESSION_CONTEXT(N'FirmaId') AS INT);
|
||||||
|
GO
|
||||||
|
|
||||||
|
-- 3. Vytvoření Security Policy pro tabulky
|
||||||
|
CREATE SECURITY POLICY Security.FirmaSecurityPolicy
|
||||||
|
ADD FILTER PREDICATE Security.fn_SecurityPredicate(FIRMA_ID) ON dbo.FAKTURA,
|
||||||
|
ADD BLOCK PREDICATE Security.fn_SecurityPredicate(FIRMA_ID) ON dbo.FAKTURA,
|
||||||
|
|
||||||
|
ADD FILTER PREDICATE Security.fn_SecurityPredicate(FIRMA_ID) ON dbo.ZAKAZNIK,
|
||||||
|
ADD BLOCK PREDICATE Security.fn_SecurityPredicate(FIRMA_ID) ON dbo.ZAKAZNIK,
|
||||||
|
|
||||||
|
ADD FILTER PREDICATE Security.fn_SecurityPredicate(FIRMA_ID) ON dbo.POLOZKA,
|
||||||
|
ADD BLOCK PREDICATE Security.fn_SecurityPredicate(FIRMA_ID) ON dbo.POLOZKA
|
||||||
|
WITH (STATE = ON);
|
||||||
|
GO
|
||||||
Loading…
Reference in New Issue