327 lines
11 KiB
Transact-SQL
327 lines
11 KiB
Transact-SQL
use master
|
|
GO
|
|
|
|
-- ==========================================
|
|
-- MASTER databáze pro přihlašování a rozřazování
|
|
-- ==========================================
|
|
|
|
CREATE DATABASE [kufrik_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
|
|
ALTER DATABASE [kufrik_master] 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_master] SET AUTO_CLOSE OFF WITH NO_WAIT;
|
|
GO
|
|
|
|
-- user:
|
|
USE [master]
|
|
GO
|
|
CREATE LOGIN [kufrik] WITH PASSWORD=N'giteaKufrik_2026!', DEFAULT_DATABASE=[master], CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF
|
|
GO
|
|
USE [kufrik_master]
|
|
GO
|
|
CREATE USER [kufrik] FOR LOGIN [kufrik]
|
|
GO
|
|
ALTER USER [kufrik] WITH DEFAULT_SCHEMA=[dbo]
|
|
GO
|
|
ALTER ROLE [db_owner] ADD MEMBER [kufrik]
|
|
GO
|
|
|
|
-- TABULKA LOGIN
|
|
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[LOGIN]') AND type in (N'U'))
|
|
BEGIN
|
|
CREATE TABLE [dbo].[LOGIN] (
|
|
[ID] [int] IDENTITY(1,1) NOT NULL,
|
|
[EMAIL] [nvarchar](100) NOT NULL,
|
|
[HESLO_HASH] [nvarchar](255) NOT NULL,
|
|
[POSLEDNI_PRIHLASENI] [datetime2](7) NULL,
|
|
[AKTIVNI] [bit] NOT NULL CONSTRAINT [DF_LOGIN_AKTIVNI] DEFAULT 1,
|
|
[DATABASE] [nvarchar](128) NOT NULL,
|
|
[SERVER] [nvarchar](100) NOT NULL,
|
|
[FIRMA_ID] [int] NOT NULL, -- vazna na tabulku FIRMA v datové DB
|
|
|
|
CONSTRAINT [PK_LOGIN] PRIMARY KEY CLUSTERED ([ID] ASC),
|
|
CONSTRAINT [UQ_LOGIN_EMAIL] UNIQUE NONCLUSTERED ([EMAIL] ASC)
|
|
);
|
|
END
|
|
GO
|
|
|
|
SET IDENTITY_INSERT dbo.[LOGIN] ON;
|
|
INSERT INTO dbo.[LOGIN] (
|
|
[ID],
|
|
[EMAIL],
|
|
[HESLO_HASH],
|
|
[DATABASE],
|
|
[SERVER],
|
|
[FIRMA_ID]
|
|
)
|
|
VALUES (
|
|
1,
|
|
N'admin@kmetix.cz',
|
|
-- Heslo 'admin1234' (platný BCrypt hash pro Nette Passwords)
|
|
N'$2y$12$9SAWctZKp/JpYl7K.awSRehXOXVyRpu0ofReqvbm1jVjvdz41zH7a',
|
|
N'kufrik',
|
|
N'localhost',
|
|
1 -- Odkaz na FIRMA.ID = 1 v klientské databázi 'kufrik'
|
|
);
|
|
SET IDENTITY_INSERT dbo.[LOGIN] OFF;
|
|
GO
|
|
|
|
-- ==========================================
|
|
-- DATOVÁ databáze
|
|
-- ==========================================
|
|
|
|
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
|
|
|
|
--user (stejný i pro master DB):
|
|
USE [kufrik]
|
|
GO
|
|
CREATE USER [kufrik] FOR LOGIN [kufrik]
|
|
GO
|
|
ALTER USER [kufrik] WITH DEFAULT_SCHEMA=[dbo]
|
|
GO
|
|
ALTER ROLE [db_owner] ADD MEMBER [kufrik]
|
|
GO
|
|
|
|
-- ==========================================
|
|
-- 1. FIRMA HLAVNÍ TABULKA - vázaná na LOGIN z master_DB (taky bude tenant - izolace dat)
|
|
-- ==========================================
|
|
|
|
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 0,
|
|
|
|
-- Kontaktní údaje
|
|
[TELEFON] [nvarchar](20) NULL,
|
|
[EMAIL] [nvarchar](100) NULL,
|
|
|
|
-- Sídlo
|
|
[ULICE] [nvarchar](100) NULL,
|
|
[MESTO] [nvarchar](100) NULL,
|
|
[PSC] [nvarchar](10) NULL,
|
|
|
|
-- Banka pro fakturaci
|
|
[CISLO_UCTU] [nvarchar](30) NULL,
|
|
[BANKA_KOD] [nvarchar](10) NULL,
|
|
[IBAN] [nvarchar](34) NULL,
|
|
[BIC] [nvarchar](11) NULL,
|
|
|
|
CONSTRAINT [PK_FIRMA] PRIMARY KEY CLUSTERED ([ID] ASC)
|
|
);
|
|
|
|
-- ==========================================
|
|
-- 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
|
|
|
|
|
|
-- ==========================================
|
|
-- Cvičná data FIRMA
|
|
-- ==========================================
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM dbo.[FIRMA] WHERE [ID] = 1)
|
|
BEGIN
|
|
SET IDENTITY_INSERT dbo.[FIRMA] ON;
|
|
|
|
INSERT INTO dbo.[FIRMA] (
|
|
[ID],
|
|
[NAZEV],
|
|
[IC],
|
|
[DIC],
|
|
[PLATCE_DPH],
|
|
[TELEFON],
|
|
[EMAIL],
|
|
[ULICE],
|
|
[MESTO],
|
|
[PSC],
|
|
[CISLO_UCTU],
|
|
[BANKA_KOD],
|
|
[IBAN],
|
|
[BIC]
|
|
)
|
|
VALUES (
|
|
1,
|
|
N'Pavel Kowalski - Kmetix Systems',
|
|
N'12345678',
|
|
N'CZ12345678',
|
|
1,
|
|
N'+420123456789',
|
|
N'admin@kmetix.cz',
|
|
N'Nádražní 123',
|
|
N'Liberec',
|
|
N'46001',
|
|
N'123456789/0800',
|
|
N'0800',
|
|
N'CZ6508000000000123456789',
|
|
N'GIGACZPX'
|
|
);
|
|
|
|
SET IDENTITY_INSERT dbo.[FIRMA] OFF;
|
|
PRINT N'Cvičná firma ID 1 byla úspěšně vložena do klientské DB.';
|
|
END
|
|
GO |