diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..0f14af3
Binary files /dev/null and b/.DS_Store differ
diff --git a/soneta-business-xml/SKILL.md b/soneta-business-xml/SKILL.md
new file mode 100644
index 0000000..6418548
--- /dev/null
+++ b/soneta-business-xml/SKILL.md
@@ -0,0 +1,305 @@
+---
+name: soneta-business-xml
+description: >
+ Generator plików business.xml dla platform Soneta (enova365, Soneta Enterprise).
+ Tworzy definicje obiektów biznesowych (tabel, kolumn, relacji, indeksów) zgodne
+ ze schematem XSD. Używaj gdy użytkownik prosi o stworzenie nowego modułu biznesowego,
+ zdefiniowanie obiektów lub encji do przechowywania w bazie danych, utworzenie relacji
+ między obiektami, lub generowanie plików business.xml dla enova365/Soneta Enterprise.
+---
+
+# Soneta Business XML Generator
+
+Skill do generowania plików `business.xml` dla platform firmy Soneta:
+- **enova365** - system ERP dla firm
+- **Soneta Enterprise** - platforma enterprise
+
+Pliki te definiują obiekty biznesowe (encje ORM), które platforma automatycznie mapuje na tabele w bazie danych i generuje klasy C#.
+
+## Struktura pliku business.xml
+
+```xml
+
+
+
+ ../..
+ Soneta.Core
+
+
+
+```
+
+## Atrybuty modułu
+
+| Atrybut | Wymagany | Opis |
+|---------|----------|------|
+| `name` | ✓ | Nazwa modułu (np. "Handel", "Kadry") |
+| `namespace` | ✓ | Namespace C# (np. "Soneta.Handel") |
+| `versionName` | ✓ | Zazwyczaj "soneta" |
+| `versionNumber` | | Numer wersji (int) |
+| `internal` | | true dla modułów wewnętrznych |
+
+## Atrybuty table
+
+| Atrybut | Wymagany | Opis |
+|---------|----------|------|
+| `name` | ✓ | Nazwa klasy C# (PascalCase, l.poj.) |
+| `tablename` | ✓ | Nazwa tabeli w bazie danych (PascalCase, l.mn.) |
+| `guided` | | `Root` = główna tabela programu (dokument, kartoteka) |
+| `config` | | `true` = tabela konfiguracyjna (tworzona podczas wdrożenia) |
+| `caption` | | Etykieta pojedynczego rekordu |
+| `tablecaption` | | Etykieta listy rekordów |
+
+### Rodzaje tabel
+
+**Tabele główne (`guided="Root"`):**
+- Główne obiekty biznesowe: dokumenty, kartoteki (towar, pracownik, kontrahent)
+- Dostępne z menu głównego programu
+- Stanowią bazę definicji obiektów biznesowych
+
+**Tabele eksportowalne (`guided="Exported"`):**
+- Jak `Root`, ale dodatkowo mogą być eksportowane do innych systemów
+- Najważniejsze tabele transakcyjne: DokumentHandlowy, Platnosc, DokEwidencja
+- Używaj dla dokumentów wymagających integracji z systemami zewnętrznymi
+
+**Tabele szczegółów (bez `guided`):**
+- Opisują szczegóły obiektów głównych: pozycje dokumentu, kody towaru, adresy
+- Muszą mieć dokładnie jedną relację z `relguided="inner"` wskazującą na obiekt główny
+
+**Tabele konfiguracyjne (`config="true"`):**
+- Określają sposób działania programu
+- Konfiguracja algorytmów, formularzy, wydruków, słowników
+- Dane tworzone podczas wdrożenia systemu
+- Przykłady: definicje dokumentów, jednostki miary, stawki VAT
+
+**Tabele operacyjne (bez `config`):**
+- Dane zbierane podczas codziennej pracy
+- Dokumenty, kartoteki, transakcje
+
+## Elementy wewnętrzne
+
+### 1. Import i using
+
+```xml
+../..
+Soneta.Core
+Soneta.CRM
+```
+
+- **import** - ścieżka do katalogu z innymi plikami business.xml, do których można referować (np. typy z innych modułów)
+- **using** - namespace C# dla obiektów używanych w tym business.xml (potrzebne gdy referujesz typy z innych modułów)
+
+### 2. Enum - definicja typu wyliczeniowego
+
+```xml
+
+
+```
+
+Enum musi być zdefiniowany w osobnym pliku C# - tutaj tylko deklaracja.
+
+### 3. Interface - relacje polimorficzne
+
+Interface może być implementowany przez wiele tabel. Deklaracja samego interfejsu (jego metody/właściwości) jest w kodzie C#. W business.xml deklarujemy tylko nazwę interfejsu, aby móc tworzyć **relacje interface'owe**.
+
+```xml
+
+
+```
+
+**Relacja interface'owa** - kolumna typu interface może wskazywać na obiekt z dowolnej tabeli implementującej ten interface. W bazie danych zapisywana jest para: `(nazwa_tabeli, ID)`.
+
+```xml
+
+
+```
+
+### 4. Subrow - typ złożony (value object)
+
+Subrow to zagnieżdżony obiekt bez własnej tabeli - przechowywany jako kolumny w tabeli rodzica.
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### 5. Table - główna definicja obiektu biznesowego
+
+Pełna dokumentacja: [references/table-reference.md](references/table-reference.md)
+
+```xml
+
+ IElementSlownika
+
+
+
+
+
+
+
+
+
+
+```
+
+## Typy danych kolumn
+
+### Typy proste
+
+| Typ | Opis | Dodatkowe atrybuty |
+|-----|------|-------------------|
+| `string` | Tekst (wczytywany z rekordem) | `length` - wymagane, lub `"max"` dla nieograniczonego |
+| `text` | Długi tekst (wczytywany na żądanie, osobne SQL) | nie może być kluczem |
+| `binary` | Dane binarne | nie może być kluczem |
+| `int` | Liczba całkowita | - |
+| `double` | Liczba zmiennoprzecinkowa | - |
+| `decimal` | Liczba z dokładnością do 2 miejsc (kwota bez waluty) | - |
+| `currency` | Kwota z walutą (para: kwota + waluta) | - |
+| `doublecy` | Liczba z walutą (para: liczba + waluta) | - |
+| `percent` | Procent | - |
+| `boolean` | Tak/Nie | - |
+| `date` | Data | - |
+| `time` | Czas | - |
+| `datetime` | Data i czas | - |
+| `FromTo` | Okres dat (para: from + to) | - |
+| `guid` | Unikalny identyfikator | - |
+
+### Typy relacyjne
+
+| Typ | Opis | Dodatkowe atrybuty |
+|-----|------|-------------------|
+| `NazwaTabeli` | Relacja do innej tabeli | `children`, `delete`, `relname`, `relguided` |
+| `NazwaInterface` | Relacja interface'owa (polimorficzna) | `children`, `delete`, `relname` |
+| `NazwaEnum` | Typ wyliczeniowy | - |
+| `NazwaSubrow` | Typ złożony (value object) | - |
+
+### Uwagi do typów
+
+- **`string` vs `text`**: Używaj `string` dla krótszych tekstów (wczytywane z rekordem). Używaj `text` dla długich opisów (wczytywane osobnym zapytaniem SQL).
+- **`string length="max"`**: Tekst bez ograniczenia rozmiaru, ale wczytywany razem z rekordem.
+- **`text` i `binary`**: Nie mogą być używane jako klucze (`keyprimary`, `keyunique`).
+
+## Workflow tworzenia business.xml
+
+1. **Analiza wymagań** - określ jakie obiekty i relacje są potrzebne
+2. **Zdefiniuj enumy** - typy wyliczeniowe używane w kolumnach
+3. **Zdefiniuj interfejsy** - dla relacji polimorficznych (gdy kolumna może wskazywać na różne typy obiektów)
+4. **Zdefiniuj subrow** - typy złożone (adresy, numery dokumentów)
+5. **Zdefiniuj tabele** - główne obiekty biznesowe
+6. **Dodaj relacje** - powiązania między tabelami (zwykłe i interface'owe)
+7. **Dodaj indeksy** - klucze dla wyszukiwania
+8. **Waliduj** - sprawdź zgodność ze schematem XSD
+
+## Szczegółowa dokumentacja
+
+- **[references/modules-catalog.md](references/modules-catalog.md)** - katalog 34 modułów Soneta, tabele i interfejsy do relacji
+- **[references/table-reference.md](references/table-reference.md)** - kompletna dokumentacja atrybutów table i col
+- **[references/relations-guide.md](references/relations-guide.md)** - tworzenie relacji między obiektami
+- **[references/examples.md](references/examples.md)** - przykłady z rzeczywistych modułów Soneta
+
+## Konwencje nazewnicze Soneta
+
+- **Nazwa tabeli (name)**: PascalCase, liczba pojedyncza (np. `Towar`, `DokumentHandlowy`)
+- **Nazwa w bazie (tablename)**: PascalCase, liczba mnoga (np. `Towary`, `DokHandlowe`)
+- **Nazwa kolumny**: PascalCase (np. `KodPocztowy`, `DataWystawienia`)
+- **Klucz**: `Wg` + nazwa kolumny (np. `WgKodu`, `WgNazwy`)
+- **Namespace**: `Soneta.NazwaModulu`
+
+### Język nazewnictwa
+
+- **Obiekty biznesowe** (domenowe) - język **polski**: `Towar`, `Faktura`, `Kontrahent`, `Pracownik`
+- **Obiekty systemowe** (techniczne) - język **angielski**: `Session`, `Config`, `Cache`, `Runtime`
+
+## Typowe wzorce
+
+### Słownik (tabela konfiguracyjna)
+
+Tabele `config="true"` zawierają dane konfiguracyjne tworzone podczas wdrożenia.
+
+```xml
+
+```
+
+### Dokument z pozycjami (master-detail)
+
+Tabela szczegółów (bez `guided`) musi mieć dokładnie jedną relację `relguided="inner"`.
+
+```xml
+
+
+
+
+
+```
+
+### Historia zmian (wersjonowanie)
+
+Typ `FromTo` przechowuje okres dat (from + to).
+
+```xml
+
+```
diff --git a/soneta-business-xml/assets/Business.xsd b/soneta-business-xml/assets/Business.xsd
new file mode 100644
index 0000000..0428d9e
--- /dev/null
+++ b/soneta-business-xml/assets/Business.xsd
@@ -0,0 +1,192 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/soneta-business-xml/references/examples.md b/soneta-business-xml/references/examples.md
new file mode 100644
index 0000000..67c758d
--- /dev/null
+++ b/soneta-business-xml/references/examples.md
@@ -0,0 +1,353 @@
+# Przykłady z modułów enova365
+
+## Spis treści
+
+1. [Prosty słownik (Jednostka)](#prosty-słownik)
+2. [Główna encja (Towar)](#główna-encja)
+3. [Master-Detail (Przecena z pozycjami)](#master-detail)
+4. [Konfiguracja z historią](#konfiguracja-z-historią)
+5. [Subrow (typy złożone)](#subrow-typy-złożone)
+6. [Kompletny moduł](#kompletny-moduł)
+
+---
+
+## Prosty słownik
+
+### Jednostka miary (z Towary)
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+**Cechy:**
+- `config="true"` - tabela konfiguracyjna
+- `guided="Root"` - dostępna z menu głównego
+- `localization="dictionary"` - tłumaczenie przez słownik
+- Relacja zwrotna (`JednostkaDlugosci`)
+
+---
+
+## Główna encja
+
+### Towar (fragment z Towary)
+
+```xml
+
+
+ IElementSlownika
+ IKodowany
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+---
+
+## Master-Detail
+
+### Przecena okresowa z pozycjami (z Towary)
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Context
+
+
+
+ Context
+
+
+
+
+
+```
+
+---
+
+## Konfiguracja z historią
+
+### Procedura SME z historią (z Core)
+
+```xml
+
+
+
+
+
+```
+
+---
+
+## Subrow (typy złożone)
+
+### DefinicjaCyklu (z Core)
+
+```xml
+
+
+ Browsable(false)
+
+
+
+
+
+
+
+
+ Browsable(false)
+
+
+```
+
+### Adres (z Core)
+
+```xml
+
+
+ MaskEdit("00-000", SaveLiteral=false)
+ SqlResolving(IgnoreDashes=true, NoDashesData=true)
+
+
+
+ Dictionary("Miejscowość")
+
+
+ Dictionary("Miejscowość")
+
+
+ Dictionary("Ulica")
+
+
+
+
+
+```
+
+---
+
+## Kompletny moduł
+
+### Przykład prostego modułu
+
+```xml
+
+
+
+
+
+ ../..
+
+
+ Soneta.Core
+ Soneta.CRM
+ Soneta.Kadry
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ IRightsSource
+ IProjektHost
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
diff --git a/soneta-business-xml/references/modules-catalog.md b/soneta-business-xml/references/modules-catalog.md
new file mode 100644
index 0000000..cb9da16
--- /dev/null
+++ b/soneta-business-xml/references/modules-catalog.md
@@ -0,0 +1,525 @@
+# Katalog modułów Soneta
+
+Katalog modułów dla platform Soneta (enova365, Soneta Enterprise).
+
+## Spis treści
+
+1. [Architektura: Konfiguracja vs Operacje](#architektura-konfiguracja-vs-operacje)
+2. [Lista modułów](#lista-modułów)
+3. [Najważniejsze typy do relacji](#najważniejsze-typy-do-relacji)
+4. [Popularne Subrow](#popularne-subrow)
+5. [Interfejsy](#interfejsy)
+6. [Moduły szczegółowo](#moduły-szczegółowo)
+
+---
+
+## Architektura: Konfiguracja vs Operacje
+
+enova365 stosuje wzorzec **Definicja → Operacja**, gdzie:
+
+- **Tabele konfiguracyjne (`config="true"`)** - definiują zachowanie systemu
+ - Tworzone podczas wdrożenia
+ - Określają algorytmy, nazwy, numerację, sposób przetwarzania
+ - Często mają prefiks/sufiks: `Definicja`, `Def`, `Config`
+
+- **Tabele operacyjne** - przechowują dane transakcyjne
+ - Tworzone podczas codziennej pracy
+ - Ich zachowanie określa powiązana definicja
+
+### Przykłady par Definicja → Operacja
+
+| Definicja (config) | Operacja | Opis |
+|-------------------|----------|------|
+| `DefinicjaDokumentu` | `DokEwidencja` | Definiuje typ dokumentu, numerację, zachowanie |
+| `DefDokHandlowego` | `DokumentHandlowy` | Definiuje typ dokumentu handlowego |
+| `DefinicjaElementu` | `WypElement` | Definiuje element wypłaty, algorytm naliczania |
+| `DefinicjaListyPlac` | `ListaPlac` | Definiuje typ listy płac |
+| `DefinicjaNieobecnosci` | nieobecności w kalendarzu | Definiuje typ nieobecności |
+| `DefinicjaSzkolenia` | `RealizacjaSzkolenia` | Definiuje typ szkolenia |
+| `DefDokHandlowego` | `DokumentHandlowy` | Definiuje fakturę, WZ, PZ, itd. |
+
+---
+
+## Lista modułów
+
+| Moduł | Namespace | Opis |
+|-------|-----------|------|
+| Business | Soneta.Business.Db | Definicje systemowe, operatorzy, uprawnienia |
+| Core | Soneta.Core | Definicje dokumentów, stawki VAT, oddziały, adresy |
+| CRM | Soneta.CRM | Kontrahenci, banki, urzędy, kontakty |
+| Kadry | Soneta.Kadry | Pracownicy, umowy, wydziały |
+| Kalend | Soneta.Kalend | Kalendarze, grafiki pracy, RCP, nieobecności |
+| Place | Soneta.Place | Listy płac, wypłaty, elementy wynagrodzenia |
+| Handel | Soneta.Handel | Dokumenty handlowe, definicje dokumentów |
+| Towary | Soneta.Towary | Towary, jednostki, ceny, kody CN |
+| Magazyny | Soneta.Magazyny | Magazyny, okresy magazynowe |
+| Kasa | Soneta.Kasa | Płatności, rachunki bankowe, formy płatności |
+| Ksiega | Soneta.Ksiega | Konta, dekrety, schematy księgowe |
+| SrodkiTrwale | Soneta.SrodkiTrwale | Środki trwałe, amortyzacja |
+| Waluty | Soneta.Waluty | Waluty, tabele kursowe |
+| Deklaracje | Soneta.Deklaracje | Deklaracje podatkowe |
+| EwidencjaVat | Soneta.EwidencjaVat | Ewidencja VAT |
+| Delegacje | Soneta.Delegacje | Delegacje krajowe i zagraniczne |
+| HR | Soneta.HR | Oceny, rekrutacja, szkolenia, uprawnienia |
+| HR2 | Soneta.HR2 | Opisy stanowisk, kompetencje, cele |
+| Oceny | Soneta.Oceny | System ocen pracowniczych |
+| Produkcja | Soneta.Produkcja | Technologie, operacje produkcyjne |
+| ProdukcjaPro | Soneta.ProdukcjaPro | Zaawansowana produkcja, zlecenia |
+| Zadania | Soneta.Zadania | Projekty, zadania, kampanie, budżety |
+| Windykacja | Soneta.Windykacja | Sprawy windykacyjne |
+| Support | Soneta.Support | Zgłoszenia serwisowe (tickety) |
+| Samochodowka | Soneta.Samochodowka | Ewidencja przejazdów, pojazdy |
+| Vehicles | Soneta.Vehicles | Flota pojazdów, rezerwacje |
+| RealEstate | Soneta.RealEstate | Nieruchomości, stanowiska pracy |
+| RMK | Soneta.RMK | Rozliczenia międzyokresowe kosztów |
+| BI | Soneta.BI | Business Intelligence, dashboardy |
+
+---
+
+## Najważniejsze typy do relacji
+
+### Podmioty i kontrahenci (CRM)
+
+```xml
+Soneta.CRM
+
+
+
+
+```
+
+### Pracownicy i kadry (Kadry)
+
+```xml
+Soneta.Kadry
+
+
+
+
+```
+
+### Towary i magazyny (Towary, Magazyny)
+
+```xml
+Soneta.Towary
+Soneta.Magazyny
+
+
+
+
+```
+
+### Dokumenty handlowe (Handel)
+
+```xml
+Soneta.Handel
+
+
+
+```
+
+### Finanse i płatności (Kasa, Waluty)
+
+```xml
+Soneta.Kasa
+Soneta.Waluty
+
+
+
+
+```
+
+### Definicje i konfiguracja (Core)
+
+```xml
+Soneta.Core
+
+
+
+
+
+```
+
+---
+
+## Popularne Subrow
+
+### Adres (Core)
+
+```xml
+Soneta.Core
+
+```
+
+Zawiera: KodPocztowy, Miejscowosc, Ulica, NrDomu, NrLokalu, Poczta, Wojewodztwo
+
+### Osoba (Core)
+
+```xml
+
+```
+
+Zawiera: Imie, Nazwisko, DrugieImie, PESEL, DataUrodzenia
+
+### Kontakt (Core)
+
+```xml
+
+```
+
+Zawiera: Telefon, Fax, Email, WWW
+
+### NumerDokumentu (Core)
+
+```xml
+
+```
+
+Zawiera: Symbol, Numer, Pelny
+
+### FromTo (wbudowany)
+
+```xml
+
+```
+
+Zawiera: From (data od), To (data do)
+
+### BruttoNetto, BruttoNettoCy (Handel)
+
+```xml
+Soneta.Handel
+
+
+```
+
+---
+
+## Interfejsy
+
+| Interface | Moduł | Opis |
+|-----------|-------|------|
+| `IKontrahent` | Core | Kontrahent (relacja polimorficzna) |
+| `IPodmiotKasowy` | Kasa | Podmiot kasowy |
+| `IRightsSource` | Business | Źródło uprawnień |
+| `IGuidedRow` | Business | Wiersz z nawigacją |
+| `IDokument` | Core | Dokument |
+| `IDokumentKasowy` | Core | Dokument kasowy |
+| `IDokumentPlatny` | Core | Dokument płatny |
+| `IDokumentKsiegowalny` | Core | Dokument księgowalny |
+
+---
+
+## Moduły szczegółowo
+
+### Core (Soneta.Core)
+
+**Tabele konfiguracyjne (config=true):**
+DefinicjaDokumentu, DefinicjaDokumentuOA, CentrumKosztow, ZrodloFinansowania, RodzajZrodla, DefinicjaPodzielnikaKosztow, DefinicjaStawkiVat, DefinicjaStawkiAkcyzy, OddzialFirmy, KrajTbl, IsoProcedura, StrukturaOrganizacyjna, DefinicjaElementuStrukturyOrganizacyjnej, DefTeczki, RodzajKontaktu, DomyslnyCel, Slownik, SlownikZewn, SystemZewn, ScheduleDefs, ProceduryVAT, WarningDefs, KrajSME
+
+**Tabele eksportowalne (guided=Exported):**
+DokEwidencja
+
+**Tabele operacyjne (guided=Root):**
+HistoriaDanychOddziału, HistoriaDanychFirmyBase, ElementStrukturyOrganizacyjnej, Teczka, Discussion, Konwersacja, Aktualnosci
+
+**Subrow:**
+DefinicjaCyklu, DefinicjaNumeracji, NumerDokumentu, Adres, AdresRozszerzony, Kontakt, Osoba, StawkaVat
+
+---
+
+### CRM (Soneta.CRM)
+
+**Tabele konfiguracyjne (config=true):**
+DefKategKth, FormaPrawna, RoleOpiekun, AuthProvider, AuthAzureConfig, SzablonSms, ZrodloKontaktu, Branza, DefTransakcji, StanyTransakcji, DefLeadow, StanyLeada, PriorytetyLeadow, PriorytetyTran
+
+**Tabele operacyjne (guided=Root):**
+Kontrahent, Bank, UrzadSkarbowy, UrzadCelny, OddziałZUS, InstytucjaFinansowaPPK, Lokalizacja, OsobaKontrahent, WizytowkaFirmy, KontoPocztowe, WiadomoscEmail, SzablonEmail, Transakcja, Lead, Opiekun
+
+**Subrow:**
+PowiazaniePodmiotu
+
+---
+
+### Kadry (Soneta.Kadry)
+
+**Tabele konfiguracyjne (config=true):**
+DefPodstawyStazu, DefinicjaWydziału, Wydzial, GrupaZaszeregowania, TytulUbezpieczenia4, KodPracyWSzególnychWarunkachCharakterze, ZestawDodatków, DefinicjaAkordu, DefinicjaOświadczenia, DefinicjaBadaniaLekarskiego, DefSzkolenBHP, DefJezykowObcych, DefFundPozycz, KatCzynnSzkod, DefCzynnSzkod, KatZglSygnal
+
+**Tabele operacyjne (guided=Root):**
+Pracownik, Umowa, Dodatek, CzlonekRodziny, Akord, WniosekUrlopowy, OświadczeniePracownika, NagrodaKara, Pozyczka, ZgodaNaEdycję, KorektaZajęciaKomorniczego, UmowyZewnetrzne, CzynnSzkodPrac
+
+**Subrow:**
+Zaszeregowanie, Etat, StazPracyPracownika, Urodzony, DokumentOsoby, Obywatelstwo, StopienNiepelnosp, DaneZUS, DanePFRON, Ubezpieczenia, UmowaOPrace, ZawarcieUmowy, RozwiazanieUmowy, StatystykaGUS, PodatkiInfo, StanRodzinny
+
+---
+
+### Kalend (Soneta.Kalend)
+
+**Tabele konfiguracyjne (config=true):**
+CzytnikRCP, DefinicjaLimitu, DefinicjaStrefy, DefinicjaDnia, DefinicjaNieobecnosci, DefinicjaGrafikaPracy, DefinicjaZestawieniaCzasu, DefAlgorytmRCP, DefinicjaRozliczeniaCzasuPracy, DefinicjaRodzajuPracyZdalnej, DefinicjaZdarzeniaRCP, DefinicjaAktualizacjiKalendarza, DefWeryfKalend
+
+**Tabele operacyjne (guided=Root):**
+KalendarzBase, GrafikPracy, RozliczenieCzasuPracy, ElementRozliczeniaCzasuPracy, WniosekPracyZdalnej, DokumentAktualizacjiKalendarza, ObiektDoPlanowania
+
+**Subrow:**
+CzasPracy, Nadgodziny, Nocne, ZwolnienieZUS, UrlopMacierzyński, UrlopWychowawczy, UrlopWypoczynkowy, ZLA
+
+---
+
+### Place (Soneta.Place)
+
+**Tabele konfiguracyjne (config=true):**
+DefinicjaListyPlac, DefinicjaElementu, PozycjaPIT, KodRSA, DefinicjaElementuRozliczenia
+
+**Tabele operacyjne (guided=Root):**
+ListaPlac, Wyplata, WypElement, Zaliczka, KosztAutorski, ZaniechaniePodatkowe, OświadczenieZusOpieka, DodatekAutomatyczny, DefinicjaPlanowanejListyPłac, PlanowanaListaPłac, ZasiłekInnyPłatnik, DokumentRozliczeniaKontrahenta, DokumentRozliczeniaPracownika
+
+**Subrow:**
+KorektaDefElementu, CzasDefElementu, WspolczynnikDefElementu, KreatorAlgorytmu, AlgorytmDefElementu, KosztyUzyskaniaPrzychodu, ZaliczkaPodatku, UlgaPodatkowa, UbezpieczenieSpoleczne, UbezpieczenieZdrowotne, NarzutyNaWynagrodzenie, PodstawaUrlopu, PodstawaZasilkow, Zaokraglenie
+
+---
+
+### Handel (Soneta.Handel)
+
+**Tabele konfiguracyjne (config=true):**
+DefDokHandlowego, DefUrzadzeniaUz, DrukarkaFiskalna
+
+**Tabele eksportowalne (guided=Exported):**
+DokumentHandlowy, UrzadzenieUz
+
+**Tabele operacyjne (guided=Root):**
+PrzesylkaSpedyt, PaczkaWzorcowa
+
+**Subrow:**
+Realizacja, BruttoNetto, BruttoNettoCy, MozliwosciEdycji, Wersjonowanie, Przesylka, PunktOdbioru, EDokument, KreatorDokumentu, DokumentObcy, Wymiary
+
+---
+
+### Towary (Soneta.Towary)
+
+**Tabele konfiguracyjne (config=true):**
+Jednostka, Przelicznik, DefinicjaCeny
+
+**Tabele operacyjne (guided=Root):**
+Towar, KodCN, KodBDO, KodCPV, KodSUP, SchemOpakowan, ElementKompletu, CenaGrupowa, PrzecenaOkresowa
+
+**Subrow:**
+GrupyDostawOpcje, AlgorytmCeny, AlgorytmRabatu, ProduktInfo, WspolczynnikCeny
+
+---
+
+### Magazyny (Soneta.Magazyny)
+
+**Tabele konfiguracyjne (config=true):**
+Magazyn, OkresMagazynowy
+
+**Subrow:**
+PartiaTowaru, ParametryRezerwacji
+
+---
+
+### Kasa (Soneta.Kasa)
+
+**Tabele konfiguracyjne (config=true):**
+FormatWymianyElektronicznej, SposobZaplaty, FormaPlatnosci, DefinicjaPaczkiPrzelewu, TypIdenPodPrzel, EwidencjaSP, OkresMW, SerwisBankowy
+
+**Tabele eksportowalne (guided=Exported):**
+Platnosc, DokKasowyBase
+
+**Tabele operacyjne (guided=Root):**
+RachunekBankowyPodmiotu, Zaplata, RaportESP, RozliczenieSP, DokRozliczBase, PreliminarzDokument
+
+**Subrow:**
+NumerRachunku, RachunekBankowy, KartaPlatnicza, ElixirInfo, OdsetkiKarne
+
+---
+
+### Ksiega (Soneta.Ksiega)
+
+**Tabele konfiguracyjne (config=true):**
+OkresObrachunkowy, DefinicjaSlownika, SchematKsiegowy, RelacjaOpisAnal, ZestawienieKS, MatrycaBase, DefinicjaKregu, ZnacznikKonta, GrupaKont, SchematPodz
+
+**Tabele operacyjne (guided=Root):**
+DekretBase, KontoBase, ElemSlownika, WynikZestKS, SprawozdanieKS, ZleDlugiDokument
+
+**Subrow:**
+KPiR, DefinicjaZakresu
+
+---
+
+### Waluty (Soneta.Waluty)
+
+**Tabele konfiguracyjne (config=true):**
+Waluta, TabelaKursowa
+
+**Subrow:**
+Euro
+
+---
+
+### SrodkiTrwale (Soneta.SrodkiTrwale)
+
+**Tabele konfiguracyjne (config=true):**
+RodzajST, MiejsceUzytkowania, KategoriaST, KategoriaZapotrzebowania, TytulDokumentuST
+
+**Tabele operacyjne (guided=Root):**
+SrodekTrwalyBase, DokumentST, DokumentUL, ZestawST, LokalizacjaNier, RodzajPO, Wyposazenie
+
+**Subrow:**
+Sezonowosc, ParametryAmortyzacji
+
+---
+
+### HR (Soneta.HR)
+
+**Tabele konfiguracyjne (config=true):**
+DefElementuOcenyPracownika, WzorOcenyPracownika, DefinicjaStanowiska, DefinicjaFunkcji, DefinicjaEtapuRekrutacji, KategoriaUprawnienia, KategoriaSzkolenia, EtapRealizacjiSzkolenia, GrupaStanow
+
+**Tabele operacyjne (guided=Root):**
+OcenaPracownika, Rekrutacja, EtapRekrutacji, Wyszukanie, DefinicjaUprawnienia, UprawnieniePracownika, DefinicjaSzkolenia, DostawcaSzkoleń, OfertaSzkolenia, BudżetSzkoleń, WniosekOSzkolenie, RealizacjaSzkolenia
+
+---
+
+### Oceny (Soneta.Oceny)
+
+**Tabele konfiguracyjne (config=true):**
+DefinicjaSekcjiDokumentu, ZakresWartości, SkalaOcen, ElementSkaliOcen, KategoriaElementuOceny, DefinicjaElementuOceny, DefinicjaArkuszaOceny, DefinicjaOceny
+
+**Tabele operacyjne (guided=Root):**
+OcenaRealizacja, OcenaArkusz, OcenaPowiaz
+
+**Subrow:**
+MiaraElementuOceny, WartośćElementuOceny
+
+---
+
+### Zadania (Soneta.Zadania)
+
+**Tabele konfiguracyjne (config=true):**
+DefKampania, DefProjektu, StanProjektu, DefZadania, StanZadania, PriorytetZadania, DefBudgetAspect, DefBudgetCategory, DefBudgetCategoryRelation, DefBudget, BudgetPeriod, DefPlanVersion, DefsKoresp, StanyKoresp, TypyUrzadzen, KategorieAkt, Zespoly
+
+**Tabele operacyjne (guided=Root):**
+Projekt, Zadanie, Kampania, WersjaPlanu, Urzadzenie, PlanowanyPrzeglad, Korespondencja, BudzetyProjektu, GoogleCalendars, ZadaniaDnia
+
+**Subrow:**
+Budzet
+
+---
+
+### Produkcja (Soneta.Produkcja)
+
+**Tabele konfiguracyjne (config=true):**
+ProdProdukt, ProdSlownik
+
+**Tabele operacyjne (guided=Root):**
+Technologia, Operacja, PozycjaTechn, KosztTechn, CzasTechn, ProdZasob, ProdOsoba, ProdAwaria, ProdMeldunekBraku
+
+---
+
+### ProdukcjaPro (Soneta.ProdukcjaPro)
+
+**Tabele konfiguracyjne (config=true):**
+ProWydzial, ProUzytkownikPaneluMeldunkowego
+
+**Tabele operacyjne (guided=Root):**
+ProTechnologia, ProZlecenie, ProMeldunek, ProZasob, ProOsoba, ProStawka, ProDefinicjaMeldunku, ProKompetencja, ProDefinicjaOperacji, ProZestawienieMaterialow
+
+---
+
+### Support (Soneta.Support)
+
+**Tabele konfiguracyjne (config=true):**
+TicketDefinition, Priority, State, Product, ProductVersion, OperatorToTeam, SLACalendar
+
+**Tabele operacyjne (guided=Root):**
+Ticket, Team, RelationToDoc, SLADocument, TicketFollower
+
+---
+
+### Vehicles (Soneta.Vehicles)
+
+**Tabele konfiguracyjne (config=true):**
+VehicleType, VehicleState, ReservationDef, ReservationState
+
+**Tabele operacyjne (guided=Root):**
+VehicleDetails, VehicleEvent, VehicleReading, Reservation, Fine, Insurance, DamageEvent, TechInspection, VehicleHis
+
+---
+
+### Windykacja (Soneta.Windykacja)
+
+**Tabele konfiguracyjne (config=true):**
+EtapDefinicjiWindykacji, DefinicjaSprawyWindykacyjnej, StanWindykacji
+
+**Tabele operacyjne (guided=Root):**
+SprawaWindykacyjna
+
+**Subrow:**
+WindykacjaInfo
+
+---
+
+### RealEstate (Soneta.RealEstate)
+
+**Tabele konfiguracyjne (config=true):**
+TypNieruchomosc, StanNieruchomosci, CelRezerwacji, DefinicjaAlgorytmuUslugi, DefinicjaRozliczeniaMediow
+
+**Tabele operacyjne (guided=Root):**
+Nieruchomosc, NieruchomoscHis, NieruchomoscZdarzenie, StanowiskoPracy, RezerwacjaStanowiskaPracy, UslugaNieruch, RozliczenieMediow
+
+**Subrow:**
+AlgorytmNieruchomosci, AlgorytmUslugi
+
+---
+
+### Delegacje (Soneta.Delegacje)
+
+**Tabele konfiguracyjne (config=true):**
+KrajDelegacji, StawkiDelegacji
+
+**Tabele operacyjne (guided=Root):**
+Delegacja, KosztDelegacji
+
+---
+
+### Samochodowka (Soneta.Samochodowka)
+
+**Tabele konfiguracyjne (config=true):**
+EkoRodzajPaliwa, EkoRodzajSilnika
+
+**Tabele operacyjne (guided=Root):**
+Pojazd, DefinicjaTrasy, Przejazd, KosztEP, RozliczenieEP
+
+**Subrow:**
+Trasa
+
+---
+
+### RMK (Soneta.RMK)
+
+**Tabele operacyjne (guided=Root):**
+KosztRMK, DokumentRMK
+
+---
+
+### BI (Soneta.BI)
+
+**Tabele konfiguracyjne (config=true):**
+DataSource, DataModel, ModelGroupBy, ModelOrderBy, TimeSpanDefinition, TimeSpanSet, TimeSpanItem, DashboardItemLocation, DashboardViewLocation, DashboardItemDefinition, ChartParam, DataSetDefinition, ColumnDefinition, SerializationDefinition, AnalysisArea
+
+**Subrow:**
+FieldProxy, TableProxy
+
+---
+
+### Business (Soneta.Business.Db)
+
+**Tabele konfiguracyjne (config=true):**
+CfgNode, Operator, Entitle, DBItem, DBGroup, WizardDefinition, WizardStepDefinition, UserGroup, SysNotification, DashboardArea, DashboardView, SystemRole, RoleCategory, RuntimeSolution, RuntimeProject, PivotViews, NotifiCategories
+
+**Tabele operacyjne (guided=Root):**
+FeatureDefinition, FeatureTransferDefinition, FeatureSetDefinition, DictionaryItem, Task, SystemFiles, AppTokens
+
+**Subrow:**
+RuntimeDefinitionInfo, RuntimeFields, AlgorithmColumn
diff --git a/soneta-business-xml/references/relations-guide.md b/soneta-business-xml/references/relations-guide.md
new file mode 100644
index 0000000..e073043
--- /dev/null
+++ b/soneta-business-xml/references/relations-guide.md
@@ -0,0 +1,277 @@
+# Relacje między obiektami - Przewodnik
+
+## Spis treści
+
+1. [Typy relacji](#typy-relacji)
+2. [Relacja jeden-do-wielu (master-detail)](#relacja-jeden-do-wielu)
+3. [Relacja wiele-do-wielu](#relacja-wiele-do-wielu)
+4. [Relacja do interfejsu](#relacja-do-interfejsu)
+5. [Historia (wersjonowanie)](#historia-wersjonowanie)
+6. [Relacja zwrotna (self-reference)](#relacja-zwrotna)
+
+---
+
+## Typy relacji
+
+| Typ | Opis | W bazie danych | Przykład |
+|-----|------|----------------|----------|
+| Jeden-do-wielu | Dokument → Pozycje | FK (ID) | Faktura ma wiele pozycji |
+| Wiele-do-wielu | Przez tabelę łączącą | 2x FK | Towar ↔ Kategorie |
+| Interface'owa | Polimorficzna do wielu tabel | (tabela, ID) | IKontrahent → Osoba lub Firma |
+| Historia | Wersjonowanie temporalne | FK + okres | Ceny towaru w czasie |
+| Zwrotna | Do tej samej tabeli | FK (ID) | Kategoria nadrzędna |
+
+---
+
+## Relacja jeden-do-wielu
+
+### Wzorzec: Dokument z pozycjami
+
+```xml
+
+
+
+
+
+```
+
+### Kluczowe atrybuty relacji podrzędnej
+
+| Atrybut | Wartość | Znaczenie |
+|---------|---------|-----------|
+| `required="true"` | | Pozycja musi mieć dokument |
+| `readonly="true"` | | Nie można przenosić między dokumentami |
+| `keyprimary="true"` | | Klucz główny zaczyna się od dokumentu |
+| `children="Pozycje"` | | Nazwa kolekcji w dokumencie: `dokument.Pozycje` |
+| `delete="cascade"` | | Usunięcie dokumentu usuwa pozycje |
+| `relguided="inner"` | | **Wymagane** dla tabel szczegółów (bez `guided`) |
+
+### Zasada relguided="inner"
+
+Tabele bez atrybutu `guided` (tabele szczegółów) **muszą mieć dokładnie jedną** relację z `relguided="inner"`. Wskazuje ona obiekt główny, którego szczegóły są opisywane.
+
+### Klucz złożony z Lp
+
+```xml
+
+
+
+
+```
+
+---
+
+## Relacja wiele-do-wielu
+
+### Wzorzec: Tabela łącząca
+
+```xml
+
+
+```
+
+### Wzajemne keycol
+
+Element `` w kolumnie relacji tworzy indeks złożony:
+
+```xml
+
+
+
+
+
+
+```
+
+---
+
+## Relacja do interfejsu (polimorficzna)
+
+Relacja interface'owa pozwala na wskazanie obiektu z **dowolnej tabeli** implementującej dany interface. W bazie danych zapisywana jest para: `(nazwa_tabeli, ID)`.
+
+### Deklaracja interfejsu
+
+Interface musi być zadeklarowany w business.xml. Sama definicja interfejsu (metody, właściwości) jest w kodzie C#.
+
+```xml
+
+
+
+```
+
+### Wzorzec: Relacja interface'owa
+
+```xml
+
+
+```
+
+### Różnica: relacja zwykła vs interface'owa
+
+| Cecha | Relacja zwykła | Relacja interface'owa |
+|-------|----------------|----------------------|
+| Typ kolumny | `NazwaTabeli` | `INazwaInterface` |
+| W bazie danych | tylko `ID` | `(nazwa_tabeli, ID)` |
+| Wskazuje na | jedną konkretną tabelę | dowolną tabelę implementującą interface |
+| Przykład | `type="Kontrahent"` | `type="IKontrahent"` |
+
+### Popularne interfejsy enova365
+
+| Interfejs | Opis |
+|-----------|------|
+| `IKontrahent` | Kontrahent (osoba/firma) |
+| `IPodmiotKasowy` | Podmiot kasowy |
+| `IRightsSource` | Źródło uprawnień |
+| `IElementSlownika` | Element słownika |
+| `IGuidedRow` | Wiersz z nawigacją |
+
+---
+
+## Historia (wersjonowanie)
+
+### Wzorzec: Dane historyczne
+
+```xml
+
+```
+
+### Kluczowe atrybuty historii
+
+| Atrybut | Wartość | Znaczenie |
+|---------|---------|-----------|
+| `keyclass="History"` | | Klasa indeksu historycznego |
+| `keyclasscol="Okres"` | | Kolumna z okresem (FromTo) |
+
+### Typ FromTo
+
+Wbudowany typ dla okresów czasowych z polami `From` i `To`.
+
+---
+
+## Relacja zwrotna
+
+### Wzorzec: Struktura hierarchiczna
+
+```xml
+
+```
+
+### Z poziomem zagnieżdżenia
+
+```xml
+
+
+
+
+```
+
+---
+
+## Wzorce złożone
+
+### Relacja z dodatkowymi danymi
+
+```xml
+
+```
+
+### Relacja z kaskadowym usuwaniem warunkowym
+
+```xml
+
+
+
+
+```
diff --git a/soneta-business-xml/references/table-reference.md b/soneta-business-xml/references/table-reference.md
new file mode 100644
index 0000000..4778a06
--- /dev/null
+++ b/soneta-business-xml/references/table-reference.md
@@ -0,0 +1,289 @@
+# Table Reference - Kompletna dokumentacja
+
+## Spis treści
+
+1. [Atrybuty table](#atrybuty-table)
+2. [Atrybuty col](#atrybuty-col)
+3. [Element key](#element-key)
+4. [Element verifier](#element-verifier)
+5. [Element attribute](#element-attribute)
+
+---
+
+## Atrybuty table
+
+| Atrybut | Wymagany | Typ | Opis |
+|---------|----------|-----|------|
+| `name` | ✓ | string | Nazwa klasy C# (PascalCase, l.poj.) |
+| `tablename` | ✓ | string | Nazwa tabeli w bazie (PascalCase, l.mn.) |
+| `guided` | | string | `Root` = główna tabela (dokument, kartoteka) |
+| `config` | | boolean | `true` = tabela konfiguracyjna (wdrożeniowa) |
+| `caption` | | string | Etykieta pojedynczego rekordu |
+| `tablecaption` | | string | Etykieta listy rekordów |
+| `namespace` | | string | Nadpisuje namespace z modułu |
+| `name8` | | string | Skrócona nazwa (max 8 znaków, legacy) |
+| `cached` | | boolean | `true` = cache'owanie w pamięci |
+| `timestamp` | | boolean | `true` = automatyczne pole timestamp |
+| `optimisticlocking` | | boolean | `true` = optymistyczne blokowanie |
+| `lock` | | string | Tryb blokowania |
+| `warnings` | | string | `Off` = wyłącza ostrzeżenia |
+
+### Rodzaje tabel
+
+**`guided="Root"`** - Główne tabele programu:
+- Dokumenty, kartoteki (towar, pracownik, kontrahent)
+- Dostępne z menu głównego
+
+**`guided="Exported"`** - Tabele eksportowalne:
+- Jak Root, ale z możliwością eksportu do systemów zewnętrznych
+- Najważniejsze tabele transakcyjne (DokumentHandlowy, Platnosc)
+- Używaj dla dokumentów wymagających integracji
+
+**Bez `guided`** - Tabele szczegółów:
+- Pozycje dokumentu, kody towaru, adresy
+- Muszą mieć dokładnie jedną relację `relguided="inner"`
+
+**`config="true"`** - Tabele konfiguracyjne:
+- Dane wdrożeniowe: definicje, słowniki, ustawienia
+- Konfiguracja algorytmów, formularzy, wydruków
+
+**Bez `config`** - Tabele operacyjne:
+- Dane zbierane podczas pracy: dokumenty, transakcje
+
+### Przykład table z wszystkimi atrybutami
+
+```xml
+
+```
+
+---
+
+## Atrybuty col
+
+### Podstawowe
+
+| Atrybut | Wymagany | Typ | Opis |
+|---------|----------|-----|------|
+| `name` | ✓ | string | Nazwa właściwości C# |
+| `type` | ✓ | string | Typ danych (patrz typy) |
+| `length` | dla string | uint/max | Długość tekstu lub `"max"` dla nieograniczonej |
+| `required` | | RequiredType | `true`/`false`/`noverified` |
+| `readonly` | | ReadonlyType | `true`/`false`/`set` |
+| `caption` | | string | Etykieta pola w UI |
+| `description` | | string | Jedno/dwuzdaniowy opis pola (tooltip) |
+| `category` | | string | Kategoria w edytorze właściwości |
+
+### Ograniczenia typów
+
+- **`text`** i **`binary`** - nie mogą być kluczami (`keyprimary`, `keyunique`)
+- **`string length="max"`** - tekst bez ograniczenia, wczytywany z rekordem
+- **`text`** - wczytywany na żądanie (osobne zapytanie SQL)
+
+### Modyfikatory
+
+| Atrybut | Typ | Opis |
+|---------|-----|------|
+| `modifier` | string | Modyfikator C#: `public virtual`, `protected`, `internal` |
+| `important` | boolean | `true` = pole wyświetlane na liście |
+| `selector` | boolean | `true` = pole selektor typu |
+| `batchfield` | boolean | `false` = pomijane przy batch operations |
+| `fulltext` | boolean | `true` = indeksowanie pełnotekstowe |
+| `specialaccess` | boolean | `true` = specjalne uprawnienia |
+
+### Relacje
+
+| Atrybut | Typ | Opis |
+|---------|-----|------|
+| `children` | string | Nazwa kolekcji dzieci w obiekcie nadrzędnym |
+| `relname` | string | Opis relacji |
+| `relguided` | string | `inner` = nawigacja wewnętrzna |
+| `relright` | boolean | `true` = prawa do relacji |
+| `reldefault` | boolean | `true` = domyślna relacja |
+| `delete` | string | Akcja przy usuwaniu: `cascade`, `setnull` |
+| `setonlynull` | boolean | `true` = można ustawić tylko raz |
+
+### Indeksy (inline w col)
+
+| Atrybut | Typ | Opis |
+|---------|-----|------|
+| `keyprimary` | boolean | `true` = część klucza głównego |
+| `keyunique` | boolean | `true` = wartość unikalna |
+| `keyclass` | string | Klasa indeksu: `History`, `Lp` |
+| `keyclasscol` | string | Kolumna dla keyclass |
+
+### Lokalizacja
+
+| Atrybut | Typ | Opis |
+|---------|-----|------|
+| `localization` | LocalizationType | `none`/`dictionary`/`db` |
+| `name12` | string | Skrócona nazwa kolumny (max 12 zn.) |
+| `cstype` | string | Nadpisanie typu C# |
+
+---
+
+## RequiredType - wartości
+
+- `true` - pole wymagane, walidowane
+- `false` - pole opcjonalne
+- `noverified` - pole wymagane, ale bez walidacji
+
+## ReadonlyType - wartości
+
+- `true` - tylko do odczytu
+- `false` - edytowalne
+- `set` - można ustawić tylko przy tworzeniu
+
+---
+
+## Element key
+
+Definiuje indeks na tabeli.
+
+```xml
+
+
+
+
+
+
+
+
+```
+
+### Atrybuty key
+
+| Atrybut | Typ | Opis |
+|---------|-----|------|
+| `name` | string | Nazwa indeksu (konwencja: `Wg` + kolumny) |
+| `keyunique` | boolean | `true` = indeks unikalny |
+| `keyprimary` | boolean | `true` = klucz główny |
+| `keyclass` | string | Klasa indeksu |
+| `keyclasscol` | string | Kolumna dla klasy |
+| `lock` | string | Tryb blokowania: `ExclusiveGet` |
+
+### Element keycol
+
+```xml
+
+```
+
+### Element keyinclude
+
+Dodatkowe kolumny w indeksie (INCLUDE w SQL):
+
+```xml
+
+
+
+
+```
+
+---
+
+## Element verifier
+
+Walidator pola wywoływany przy zapisie.
+
+```xml
+
+
+
+
+```
+
+### Atrybuty verifier
+
+| Atrybut | Wymagany | Typ | Opis |
+|---------|----------|-----|------|
+| `name` | ✓ | string | Pełna nazwa klasy weryfikatora |
+| `onadded` | | boolean | `true` = tylko przy dodawaniu |
+
+---
+
+## Element attribute
+
+Atrybut C# dodawany do właściwości.
+
+```xml
+
+ MaskEdit("00-000", SaveLiteral=false)
+ Browsable(false)
+ Dictionary("Miejscowość")
+ Obsolete("Użyj pola X")
+ Context
+ Context(Required=false)
+
+```
+
+### Popularne atrybuty
+
+| Atrybut | Opis |
+|---------|------|
+| `Browsable(false)` | Ukrywa pole w UI |
+| `Context` | Pole kontekstowe |
+| `Context(Required=false)` | Opcjonalny kontekst |
+| `Dictionary("nazwa")` | Słownik podpowiedzi |
+| `MaskEdit("maska")` | Maska wprowadzania |
+| `Obsolete("msg")` | Oznacza jako przestarzałe |
+| `NumeratorItem` | Element numeratora |
+
+---
+
+## Przykład kompletnej tabeli
+
+```xml
+
+
+ IRightsSource
+ IDefinicjaDokumentuOA
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Context
+
+
+
+
+
+
+
+
+
+
+```
diff --git a/soneta-programming-basics/SKILL.md b/soneta-programming-basics/SKILL.md
new file mode 100644
index 0000000..7778736
--- /dev/null
+++ b/soneta-programming-basics/SKILL.md
@@ -0,0 +1,351 @@
+---
+name: soneta-programming-basics
+description: >
+ Fundamentalne klasy ORM platformy enova365/Soneta Enterprise. Obejmuje mapowanie
+ obiektowo-relacyjne (Row, Table, Module), zarządzanie sesją (Session), logowanie
+ (Login, Database, BusApplication), paczki danych (Datapack, GuidedRow) oraz
+ kontekst (Context). Używaj gdy użytkownik pyta o podstawowe klasy logiki biznesowej,
+ strukturę obiektów ORM, sesje i transakcje, hierarchię klas Row/Table/Module,
+ mechanizm Datapack i synchronizację danych, lub kontekst aplikacji enova365.
+---
+
+# Soneta Programming Basics - Podstawowe klasy ORM
+
+Skill zawiera dokumentację fundamentalnych klas logiki biznesowej platformy enova365/Soneta Enterprise. Klasy te stanowią podstawę mapowania obiektowo-relacyjnego (ORM) i są niezbędne do tworzenia dodatków.
+
+## Architektura warstw
+
+```
+┌─────────────────────────────────────────────────────┐
+│ Interfejs graficzny (UI) │
+├─────────────────────────────────────────────────────┤
+│ Context │ ← Komunikacja UI ↔ logika
+├─────────────────────────────────────────────────────┤
+│ Logika biznesowa │
+│ ┌─────────────────────────────────────────────┐ │
+│ │ BusApplication (Singleton) │ │
+│ │ └── Database (konfiguracja bazy) │ │
+│ │ └── Login (uwierzytelnienie) │ │
+│ │ └── Session (zarządzanie danymi) │ │
+│ │ └── Module → Table → Row │ │
+│ └─────────────────────────────────────────────┘ │
+├─────────────────────────────────────────────────────┤
+│ Baza danych SQL │
+└─────────────────────────────────────────────────────┘
+```
+
+## 3 poziomy logiki biznesowej
+
+| Poziom | Opis | Przykłady klas |
+|--------|------|----------------|
+| **1. Bazowe** | Klasy wspólne dla wszystkich modułów (Soneta.Business.dll) | `Row`, `Table`, `Module`, `Session`, `Context` |
+| **2. Generowane** | Klasy generowane przez BusinessGenerator z *.business.xml (sufiksy: Row, Table, Module) | `TowarRow`, `TowarTable`, `TowaryModule` |
+| **3. Implementowane** | Klasy konkretne tworzone przez programistę | `Towar`, `Towary` (bez sufiksów) |
+
+**BusinessGenerator** jest automatycznie uruchamiany podczas kompilacji dla plików `*.business.xml`. Szczegółowy opis definiowania business.xml znajduje się w skill **soneta-business-xml**.
+
+## Hierarchia głównych klas
+
+```
+Row (abstrakcyjna)
+ └── GuidedRow (+ Guid, Attachments, ChangeInfos)
+ └── ExportedRow (+ Exported flag)
+
+Table (abstrakcyjna)
+ └── GuidedTable (indeksator po Guid)
+ └── ExportedTable
+
+Module (abstrakcyjna)
+ └── [NazwaModulu]Module (np. TowaryModule)
+```
+
+## Thread-safety
+
+### Obiekty single-threaded (NIE współdzielić między wątkami)
+- `Session`
+- `Module`
+- `Table`
+- `Row`
+- `Context`
+- oraz wszystkie klasy pochodne
+
+Każdy wątek powinien tworzyć własną sesję.
+
+### Obiekty multi-threaded (można współdzielić)
+- `BusApplication`
+- `Database`
+- `Login`
+
+## Klasa Session - fundamenty
+
+Session to kluczowa klasa do zarządzania danymi. **Każda operacja na danych wymaga sesji.**
+
+### Tworzenie sesji
+
+```csharp
+// Przez Login
+Session session = login.CreateSession(readOnly: false, config: false, name: "MojaSesja");
+
+// Parametry konstruktora:
+// readOnly: true = tylko odczyt, false = edycja
+// config: true = dane konfiguracyjne (cache), false = dane operacyjne (aktualne)
+```
+
+### Typy sesji
+
+| Typ | ReadOnly | Config | Użycie |
+|-----|----------|--------|--------|
+| Edycyjna operacyjna | false | false | Modyfikacja dokumentów, kartotek |
+| ReadOnly operacyjna | true | false | Odczyt danych transakcyjnych |
+| Edycyjna konfiguracyjna | false | true | Modyfikacja ustawień |
+| ReadOnly konfiguracyjna | true | true | Odczyt konfiguracji |
+
+**WAŻNE:** W sesji operacyjnej nie można modyfikować obiektów konfiguracyjnych - wymagana jest sesja konfiguracyjna (`config: true`).
+
+### Transakcje biznesowe (WAŻNE!)
+
+**Każda zmiana obiektu MUSI być w transakcji biznesowej** otwieranej przez `Session.Logout(editMode: true)`:
+- Dodawanie nowych obiektów
+- Modyfikacja właściwości (properties)
+- Kasowanie obiektów
+
+```csharp
+// Logout(editMode: true) - transakcja edycyjna (można modyfikować)
+using (var transaction = session.Logout(editMode: true))
+{
+ towar.Nazwa = "Zmieniona nazwa";
+ transaction.Commit(); // lub CommitUI()
+}
+
+// Logout(editMode: false) - transakcja tylko do odczytu
+// (modyfikacje możliwe tylko w zagnieżdżonej transakcji edycyjnej)
+using (var readTransaction = session.Logout(editMode: false))
+{
+ // odczyt danych...
+
+ // zagnieżdżona transakcja edycyjna
+ using (var editTransaction = session.Logout(editMode: true))
+ {
+ var cena = towar.Ceny["Hurtowa"];
+ cena.Netto = new DoubleCy(100m);
+ editTransaction.Commit();
+ }
+
+ readTransaction.Commit(); // WYMAGANE! Inaczej zmiany z zagnieżdżonych transakcji przepadną
+}
+```
+
+**Brak Commit() = automatyczny rollback przy Dispose()** (dotyczy też transakcji tylko do odczytu!)
+
+### Optimistic locking
+
+Zmiany wykonywane są w trybie **optimistic-lock**:
+- Zmiany kumulują się w sesji
+- `Session.Save()` zapisuje wszystkie zmiany razem
+- Konflikty wykrywane w momencie zapisu
+
+### Ważne zasady
+
+- Session implementuje `IDisposable` - **zawsze wywołuj Dispose()** lub używaj `using`
+- Wiele sesji może współistnieć jednocześnie
+- Sesja konfiguracyjna używa cache'a (optymalizacja odczytów)
+- Sesja operacyjna zawsze czyta z bazy (aktualność danych)
+- **Nie mieszaj obiektów z różnych sesji** - użyj `session.Get(obiekt)` aby doczytać obiekt w bieżącej sesji
+
+## Klasa Module
+
+Moduł grupuje logicznie powiązane tabele. **Nie ma odwzorowania w bazie danych.**
+
+```csharp
+// Dostęp do modułu - extension method (zalecane)
+var tm = session.GetTowary();
+var hm = session.GetHandel();
+var crm = session.GetCRM();
+var bm = session.GetBusiness();
+
+// Dostęp do tabel
+Towary towary = tm.Towary;
+Jednostki jednostki = tm.Jednostki;
+
+// Moduł implementuje ISessionable
+Session s = tm.Session;
+```
+
+## Klasa Table
+
+Reprezentuje tabelę w bazie danych. Udostępnia dostęp do kolekcji wierszy.
+
+```csharp
+var towary = tm.Towary;
+
+// Iteracja po kluczu podstawowym
+foreach (Towar t in towary.WgKodu) { ... }
+
+// Iteracja po innym kluczu
+foreach (Towar t in towary.WgNazwy) { ... }
+
+// Właściwości
+Table.AccessRight // Prawa dostępu
+Table.Session // Sesja (ISessionable)
+Table.Module // Moduł nadrzędny
+Table.PrimaryKey // Klucz podstawowy
+```
+
+## Klasa Row
+
+Reprezentuje pojedynczy wiersz (rekord) z tabeli.
+
+### Właściwości bazowe
+
+```csharp
+Row.ID // int - PODSTAWOWY identyfikator obiektu w tabeli (autoincrement, Primary Key)
+Row.State // RowState - stan obiektu w sesji
+Row.Table // Table - tabela nadrzędna
+Row.Module // Module - moduł
+Row.Session // Session - sesja
+```
+
+**ID** jest automatycznie generowany przez bazę danych i stanowi klucz główny (Primary Key) tabeli.
+
+### Stany obiektu (RowState)
+
+| Stan | Opis |
+|------|------|
+| `Detached` | Nowy obiekt, nie przypisany do tabeli |
+| `Unchanged` | Wczytany z bazy, bez zmian |
+| `Modified` | Zmodyfikowany w sesji |
+| `Added` | Nowy, dodany do tabeli, nie zapisany w bazie |
+| `Deleted` | Skasowany, do usunięcia z bazy |
+
+## Klucze i indeksy
+
+Definiowane w *.business.xml, mapowane na indeksy w bazie danych.
+
+```xml
+
+
+
+```
+
+| Atrybut | Znaczenie |
+|---------|-----------|
+| `keyprimary="true"` | Klucz podstawowy (domyślne sortowanie) |
+| `keyunique="true"` | Wartości unikalne w tabeli |
+
+**Uwaga:** `keyprimary` w business.xml to **nie to samo** co Primary Key w bazie (który jest zawsze na kolumnie ID).
+
+## Interfejs ISessionable
+
+```csharp
+public interface ISessionable {
+ Session Session { get; }
+}
+```
+
+Implementują go: `Session`, `Module`, `Table`, `Row`, `Context`, `Key`.
+
+Używany jako argument funkcji wymagających kontekstu sesji:
+
+```csharp
+// Metoda statyczna GetInstance - akceptuje ISessionable
+public static TowaryModule GetInstance(ISessionable session)
+
+// Extension method - wygodniejsza składnia (tylko dla Session)
+public static TowaryModule GetTowary(this Session session)
+```
+
+**Zalecane użycie:**
+```csharp
+// Extension method (prostsze)
+var tm = session.GetTowary();
+
+// GetInstance (gdy mamy ISessionable, np. Row lub Context)
+var tm = TowaryModule.GetInstance(context);
+var tm = TowaryModule.GetInstance(towar); // towar implementuje ISessionable
+```
+
+## Szczegółowa dokumentacja
+
+- **[references/session-login.md](references/session-login.md)** - BusApplication, Database, Login, Session
+- **[references/datapack-guidedrow.md](references/datapack-guidedrow.md)** - Paczki danych, GuidedRow, ExportedRow, synchronizacja
+- **[references/context.md](references/context.md)** - Klasa Context, komunikacja UI ↔ logika
+- **[references/examples.md](references/examples.md)** - Przykłady kodu i wzorce użycia
+
+## Szybki start - wzorce kodu
+
+### Odczyt danych
+
+```csharp
+using (var session = login.CreateSession(true, false, "Odczyt"))
+{
+ var tm = session.GetTowary(); // Extension method
+ foreach (Towar t in tm.Towary.WgKodu)
+ {
+ Console.WriteLine($"{t.Kod}: {t.Nazwa}");
+ }
+}
+```
+
+### Tworzenie nowego obiektu
+
+```csharp
+using (var session = login.CreateSession(false, false, "Dodawanie"))
+{
+ var tm = session.GetTowary();
+
+ using (var transaction = session.Logout(editMode: true))
+ {
+ var towar = new Towar();
+ tm.Towary.AddRow(towar);
+ towar.Kod = "NOWY001";
+ towar.Nazwa = "Nowy towar";
+ transaction.Commit();
+ }
+
+ session.Save();
+}
+```
+
+### Modyfikacja istniejącego obiektu
+
+```csharp
+using (var session = login.CreateSession(false, false, "Edycja"))
+{
+ var tm = session.GetTowary();
+ var towar = tm.Towary.WgKodu["STARY001"];
+ if (towar != null)
+ {
+ using (var transaction = session.Logout(editMode: true))
+ {
+ towar.Nazwa = "Zmieniona nazwa";
+ transaction.Commit();
+ }
+ }
+ session.Save();
+}
+```
+
+## Konwencje nazewnicze
+
+| Element | Konwencja | Przykład |
+|---------|-----------|----------|
+| Klasa wiersza (Row) | PascalCase, l.poj. | `Towar`, `Kontrahent` |
+| Klasa tabeli | PascalCase, l.mn. | `Towary`, `Kontrahenci` |
+| Klasa modułu | Nazwa + Module | `TowaryModule` |
+| Klucz | Wg + nazwa kolumny | `WgKodu`, `WgNazwy` |
+| Namespace | Soneta.NazwaModułu | `Soneta.Towary` |
+
+### Język identyfikatorów
+
+| Typ | Język | Przykłady |
+|-----|-------|-----------|
+| Logika biznesowa | **polski** | `Towar`, `Kontrahent`, `DokumentHandlowy`, `Faktura` |
+| Identyfikatory systemowe | **angielski** | `Session`, `Context`, `Row`, `Table`, `Module` |
+
+**Można łączyć polski i angielski** w nazwach metod i klas:
+```csharp
+RetrieveTowary()
+UpdateKontrahent()
+GetDokumentyHandlowe()
+CreateFaktura()
+```
diff --git a/soneta-programming-basics/references/context.md b/soneta-programming-basics/references/context.md
new file mode 100644
index 0000000..235a8ac
--- /dev/null
+++ b/soneta-programming-basics/references/context.md
@@ -0,0 +1,334 @@
+# Klasa Context
+
+Dokumentacja klasy Context odpowiedzialnej za komunikację między warstwą logiki biznesowej a interfejsem graficznym.
+
+## Czym jest Context?
+
+Context to **kontener par klucz-wartość**, gdzie:
+- **Klucz** = typ (Type)
+- **Wartość** = obiekt tego typu (object)
+
+Kontekst jest stale aktualizowany podczas pracy z programem i przechowuje informacje o aktualnym stanie interfejsu.
+
+## Zawartość kontekstu
+
+Przykładowa zawartość przy otwartej liście kontrahentów:
+
+| Typ | Opis |
+|-----|------|
+| `SelectedCounter` | Liczba zaznaczonych wierszy na gridzie |
+| `Kontrahent[]` | Kolekcja zaznaczonych kontrahentów |
+| `UILocation` | Aktywny element interfejsu |
+| `INavigatorContext` | Kontekst grida (zaznaczenia, focus) |
+| `View` | Źródło danych grida |
+| `Params` | Klasa parametrów filtrów |
+| `LicencjaProgramu` | Informacje o licencji |
+| `Login` | Zalogowany użytkownik |
+| `MsSqlDatabase` | Baza danych |
+
+## Odczyt z kontekstu
+
+### Metody GetOrDefault i GetRequired (zalecane)
+
+```csharp
+public void Action(Context context)
+{
+ // Zwraca obiekt lub null, gdy brak obiektu
+ Kontrahent? knt = context.GetOrDefault();
+
+ // Zwraca obiekt lub wyjątek, gdy brak obiektu
+ Kontrahent knt2 = context.GetRequired();
+}
+```
+
+### Przez indeksator (rzuca wyjątek gdy brak)
+
+```csharp
+public void Action(Context cx)
+{
+ // Rzuca wyjątek gdy brak obiektu w kontekście
+ Kontrahent knt = (Kontrahent)cx[typeof(Kontrahent)];
+
+ // Bez wyjątku - drugi parametr
+ Kontrahent knt2 = (Kontrahent)cx[typeof(Kontrahent), false];
+}
+```
+
+### Przez metodę Get (bezpieczna)
+
+```csharp
+public void Action(Context cx)
+{
+ // Zwraca true jeśli znaleziono, false jeśli nie
+ if (cx.Get(out DokumentHandlowy dokument))
+ {
+ // dokument znaleziony
+ }
+ else
+ {
+ // dokument nie znaleziony (dokument = null)
+ }
+}
+```
+
+## Zapis do kontekstu
+
+```csharp
+public void Action(Context cx)
+{
+ // Przez indeksator
+ Kontrahent knt = ...;
+ cx[typeof(Kontrahent)] = knt;
+
+ // Przez metodę Set
+ DokumentHandlowy dok = ...;
+ cx.Set(dok);
+}
+```
+
+## Zastosowania
+
+### 1. Filtry na listach głównych
+
+Klasy parametrów filtrów dziedziczą z `ContextBase` i są automatycznie w kontekście.
+
+```csharp
+// Definicja klasy parametrów (w ViewInfo)
+public class TowaryParams(Context context) : ContextBase(context)
+{
+ public Magazyn? Magazyn
+ {
+ get => Context.GetOrDefault();
+ set => Context.Set(value);
+ }
+
+ public TypTowaru Typ {
+ get => Context.GetOrDefault();
+ set => Context.Set(value);
+ }
+
+ [Accessor(AutoChange = true)]
+ public string SearchString { get; set; }
+}
+```
+
+```xml
+
+
+
+
+```
+
+Wartości filtrów są dostępne przez kontekst dla:
+- Widoków (filtrowanie danych)
+- Workerów (właściwości wyliczane)
+- Wydruków
+
+### 2. Wartości domyślne nowych obiektów
+
+Kontekst używany do inicjalizacji nowych obiektów wartościami z filtrów. Uzupełniane są właściwości zaznaczone atrybutem `[Context]`, który oznacza próbę odczytania wartości do ustawienia property z kontekstu.
+
+```
+Lista faktur:
+ Filtr Magazyn: "Sklep"
+ Filtr Kontrahent: "Drynda"
+ ↓
+Nowy dokument:
+ Magazyn: "Sklep" (z kontekstu - property z [Context])
+ Kontrahent: "Drynda" (z kontekstu - property z [Context])
+```
+
+### 3. Wydruki
+
+Wydruki mają dostęp do obiektów z kontekstu jako źródła danych.
+
+```csharp
+// W kodzie wydruku
+Context cx = ...;
+if (cx.Get(out Kontrahent[] kontrahenci))
+{
+ // kontrahenci[] = zaznaczone na liście
+}
+```
+
+### 4. Workery - atrybut [Context]
+
+Workery mogą pobierać parametry z kontekstu automatycznie.
+
+```csharp
+public class MojWorker
+{
+ [Context] // Pobierane z kontekstu
+ public Magazyn Magazyn { get; set; }
+
+ [Context] // Jeśli brak w kontekście - okno parametrów
+ public Kontrahent Kontrahent { get; set; }
+}
+```
+
+### 5. Właściwości wyliczane zależne od filtrów
+
+```csharp
+// Worker wyliczający stan magazynowy
+public class StanMagazynu : IWorker
+{
+ public object Compute(Context cx, object source)
+ {
+ Towar towar = source as Towar;
+
+ // Pobranie magazynu z kontekstu (z filtra)
+ if (cx.Get(out Magazyn magazyn))
+ {
+ return towar.GetStan(magazyn);
+ }
+ return towar.GetStanCalkowity();
+ }
+}
+```
+
+## Klasa ContextBase
+
+Bazowa klasa dla obiektów automatycznie umieszczanych w kontekście.
+
+```csharp
+public class MojaKlasaParametrow(Context context) : ContextBase(context)
+{
+ [Accessor(AutoChange = true)]
+ public Date DataOd { get; set; }
+
+ [Accessor(AutoChange = true)]
+ public Date DataDo { get; set; }
+
+ public Kontrahent Kontrahent {
+ get => Context.GetOrDefault();
+ set => Context.Set(value);
+ }
+}
+```
+
+Obiekty dziedziczące z `ContextBase` i nie tylko:
+- Są automatycznie dodawane do kontekstu
+- Wywoływane jest zdarzenie `OnChanged` przy zmianie właściwości
+- Obsługują bindowanie do kontrolek UI
+- Właściwości połączone z UI (formularze, parametry) mogą być zadeklarowane z `[Accessor(AutoChange = true)]`, dzięki czemu Accessor automatycznie uruchomi mechanizm powiadamiania o zmianach i nie będzie konieczne wywołanie `Session.InvokeChanged()` lub `Context.InvokeChanged()`
+
+## Interfejs INavigatorContext
+
+Dostępny w kontekście gdy aktywna jest lista (grid).
+
+```csharp
+public void Action(Context cx)
+{
+ if (cx.Get(out INavigatorContext nav))
+ {
+ // Wiersz z focusem
+ object current = nav.Current;
+
+ // Zaznaczone wiersze
+ IEnumerable selected = nav.Selected;
+
+ // Liczba zaznaczonych
+ int count = nav.SelectedCount;
+ }
+}
+```
+
+## Kolekcje zaznaczonych obiektów
+
+W kontekście znajdują się tablice zaznaczonych obiektów.
+
+```csharp
+public void Action(Context cx)
+{
+ // Zaznaczeni kontrahenci
+ if (cx.Get(out Kontrahent[] kontrahenci))
+ {
+ foreach (var k in kontrahenci)
+ {
+ // ...
+ }
+ }
+
+ // Zaznaczone dokumenty
+ if (cx.Get(out DokumentHandlowy[] dokumenty))
+ {
+ // ...
+ }
+}
+```
+
+## Context implementuje ISessionable
+
+```csharp
+public void Action(Context cx)
+{
+ // Dostęp do sesji przez kontekst
+ Session session = cx.Session;
+
+ // Dostęp do modułu przez sesję
+ var tm = session.GetTowary();
+}
+```
+
+## Pełny przykład - Worker z kontekstem
+
+```csharp
+[assembly: Worker]
+
+namespace Soneta.Towary;
+
+public class TowarExtenderParams(Context context) : ContextBase(context)
+{
+ [Accessor(AutoChange = true)]
+ [Caption("Magazyn filtrowania")]
+ public Magazyn MagazynFiltra { get; set; }
+}
+
+public class TowarExtender
+{
+ [Context]
+ public TowarExtenderParams Params { get; set; }
+
+ [Context]
+ public Towar Towar { get; set; }
+
+ public decimal StanWMagazynie =>
+ Params.MagazynFiltra != null
+ ? PoliczStanMagazynu(Towar, Params.MagazynFiltra)
+ : PoliczStanMagazynu(Towar);
+
+ private decimal PoliczStanMagazynu(Towar towar, Magazyn magazyn)
+ {
+ // Wyliczyć stan we wskazanym magazynie
+ return 0;
+ }
+
+ private decimal PoliczStanMagazynu(Towar towar)
+ {
+ // Wyliczyć stan w całej firmie
+ return 0;
+ }
+}
+```
+
+## Dobre praktyki
+
+1. **Używaj Get, GetOrDefault, GetRequired** zamiast indeksatora - bezpieczniejsze
+2. **Sprawdzaj obecność** obiektów w kontekście przed użyciem
+3. **Dziedzicz z ContextBase** dla własnych klas parametrów i pamiętaj o konstruktorze `(Context context)`
+4. **Używaj [Context]** w workerach dla parametrów z kontekstu
+5. **Stosuj `[Accessor(AutoChange = true)]`** lub `InvokeChanged()` dla powiadamiania UI o zmianach
+
+## Typowe typy w kontekście
+
+| Typ | Kiedy dostępny |
+|-----|----------------|
+| `Login` | Zawsze po zalogowaniu |
+| `Database` | Zawsze po zalogowaniu |
+| `LicencjaProgramu` | Zawsze po zalogowaniu |
+| `Session` | Gdy aktywny widok z danymi |
+| `View` | Gdy aktywna lista |
+| `INavigatorContext` | Gdy aktywna lista |
+| `[Obiekt][]` | Zaznaczenia na liście |
+| `[ViewInfo]+Params` | Klasa parametrów widoku |
+| `UILocation` | Lokalizacja w UI |
diff --git a/soneta-programming-basics/references/datapack-guidedrow.md b/soneta-programming-basics/references/datapack-guidedrow.md
new file mode 100644
index 0000000..a08a5b4
--- /dev/null
+++ b/soneta-programming-basics/references/datapack-guidedrow.md
@@ -0,0 +1,245 @@
+# Datapack i GuidedRow - Paczki danych
+
+Dokumentacja mechanizmu paczek danych (Datapack) służącego do grupowania powiązanych obiektów i ich synchronizacji między bazami danych.
+
+## Czym jest Datapack?
+
+**Datapack** to struktura obiektów różnych typów powiązanych relacjami, które tworzą logiczną całość.
+
+### Przykład: Dokument handlowy
+
+```
+DokumentHandlowy (Root)
+ ├── PozycjaDokHandlowego[] (Child)
+ ├── SumaVAT[] (Child)
+ └── Platnosc[] (Child)
+```
+
+Faktura bez pozycji nie jest kompletną fakturą - wszystkie te obiekty stanowią jedną paczkę danych.
+
+## Hierarchia klas Row i Table
+
+```
+Row (abstrakcyjna) Table (abstrakcyjna)
+ │ └── ID: int └── GuidedTable (indeksator po Guid)
+ │ └── State: RowState └── ExportedTable
+ │
+ └── GuidedRow
+ │ └── Guid: System.Guid
+ │ └── Attachments
+ │ └── FirstChangeInfo, LastChangeInfo
+ │ └── Note
+ │
+ └── ExportedRow
+ └── Exported: bool
+```
+
+## Atrybut guided w business.xml
+
+Atrybut `guided` w definicji tabeli określa rolę obiektu w strukturze Datapack.
+
+| Wartość | Klasa bazowa | Opis |
+|---------|--------------|------|
+| `Root` | `GuidedRow` | Główny element paczki danych. Posiada GUID. |
+| `Exported` | `ExportedRow` | Jak Root + flaga Exported (czy wyeksportowany) |
+| `Child` | `Row` | Element podrzędny w paczce. Musi mieć relację `relguided`. |
+| `None` | `Row` | Nie uczestniczy w mechanizmie Datapack |
+
+**Domyślnie:** `guided="Child"`
+
+### Przykłady definicji
+
+```xml
+
+
+
+
+
+
+
+
+```
+
+## Atrybut relguided
+
+Określa relację obiektu Child do obiektu Root w strukturze Datapack.
+
+| Wartość | Opis |
+|---------|------|
+| `inner` | Obiekt podrzędny zagnieżdżony wewnątrz roota w XML |
+| `outer` | Obiekt podrzędny poza rootem w XML (ale powiązany) |
+| (puste) | Relacja nie jest częścią Datapack |
+
+### Kiedy używać relguided
+
+```xml
+
+
+ delete="cascade"
+ children="Pozycje"/>
+
+
+
+ children="Pozycje"/>
+```
+
+**Reguły:**
+- Tabela Child może mieć **tylko jedną** kolumnę z `relguided`
+- Tabela Root **nie posiada** relacji `relguided` (jest korzeniem paczki)
+
+## GuidedRow - szczegóły
+
+### Właściwości
+
+| Właściwość | Typ | Opis |
+|------------|-----|------|
+| `Guid` | `System.Guid` | Globalnie unikalny identyfikator |
+| `Attachments` | `AttachmentCollection` | Kolekcja załączników |
+| `DefaultImage` | `Attachment` | Domyślne zdjęcie obiektu |
+| `Note` | `string` | Notatka tekstowa |
+| `FirstChangeInfo` | `ChangeInfo` | Pierwsza zmiana w historii |
+| `LastChangeInfo` | `ChangeInfo` | Ostatnia zmiana w historii |
+| `IsAdded` | `bool` | Czy nowo dodany |
+| `IsModified` | `bool` | Czy zmodyfikowany |
+| `IsDeleted` | `bool` | Czy skasowany |
+
+### Załączniki
+
+Załączniki można podpinać **tylko** do obiektów wywodzących się z `GuidedRow`.
+
+```csharp
+GuidedRow row = ...;
+
+// Dostęp do załączników
+foreach (Attachment att in row.Attachments)
+{
+ Console.WriteLine(att.Nazwa);
+}
+
+// Domyślne zdjęcie
+Attachment img = row.DefaultImage;
+```
+
+## ExportedRow
+
+Rozszerza `GuidedRow` o flagę `Exported`.
+
+### Użycie
+
+Obiekty, które po eksporcie do systemów zewnętrznych **nie powinny być modyfikowane**.
+
+**Przykład:** Przelew wyeksportowany do systemu bankowego - po zaksięgowaniu nie powinien być zmieniany w ERP.
+
+```xml
+
+```
+
+### Właściwość
+
+| Właściwość | Typ | Opis |
+|------------|-----|------|
+| `Exported` | `bool` | `true` = obiekt wyeksportowany, nie modyfikować |
+
+## Historia zmian (ChangeInfos)
+
+System loguje zmiany na obiektach `GuidedRow`.
+
+### Tabela ChangeInfos
+
+| Kolumna | Opis |
+|---------|------|
+| `SourceTable` | Nazwa tabeli źródłowej |
+| `SourceGuid` | GUID zmodyfikowanego obiektu |
+| `Time` | Data i czas zmiany |
+| `Operator` | Kto dokonał zmiany |
+
+### Dostęp do historii
+
+```csharp
+var bm = session.GetBusiness();
+
+// Iteracja po historii zmian kontrahenta
+Kontrahent knt = ...;
+foreach (ChangeInfo ci in bm.ChangeInfos[knt])
+{
+ Console.WriteLine($"{ci.Time}: {ci.Operator}");
+}
+
+// Skróty na obiekcie
+Console.WriteLine($"Utworzono: {knt.FirstChangeInfo?.Time}");
+Console.WriteLine($"Ostatnia zmiana: {knt.LastChangeInfo?.Time}");
+```
+
+**Uwaga:** Zmiany na obiektach Child są rejestrowane na poziomie Root.
+
+## Blokady
+
+Modyfikacja **dowolnego** obiektu w strukturze Datapack zakłada blokadę na poziomie **Root**.
+
+```
+DokumentHandlowy ← BLOKADA
+ ├── PozycjaDokHandlowego (modyfikacja tutaj)
+ └── SumaVAT
+```
+
+Nie można równolegle edytować obiektów należących do jednego Datapacka.
+
+## GuidedTable
+
+Odpowiednik `GuidedRow` dla tabel - dodaje indeksator po GUID.
+
+```csharp
+GuidedTable towary = ...;
+
+// Pobranie obiektu po GUID
+Guid guid = new Guid("65336878-70cf-4e64-bd72-b742cd26a657");
+Towar towar = towary[guid];
+```
+
+## Wzorce użycia
+
+### Definiowanie struktury Datapack
+
+```xml
+
+
+
+
+
+```
+
+## Podsumowanie atrybutów
+
+| Atrybut | Gdzie | Wartości | Opis |
+|---------|-------|----------|------|
+| `guided` | `` | Root, Exported, Child, None | Rola w Datapack |
+| `relguided` | `` | inner, outer, (puste) | Relacja Child→Root |
+| `delete` | `` | cascade, restrict, setnull | Akcja przy usuwaniu roota |
diff --git a/soneta-programming-basics/references/examples.md b/soneta-programming-basics/references/examples.md
new file mode 100644
index 0000000..0989b0f
--- /dev/null
+++ b/soneta-programming-basics/references/examples.md
@@ -0,0 +1,643 @@
+# Przykłady kodu - Podstawowe klasy ORM
+
+Praktyczne przykłady użycia podstawowych klas logiki biznesowej enova365/Soneta.
+
+## Ważne zasady
+
+### Thread-safety
+
+**Obiekty single-threaded** - nie współdziel między wątkami:
+- `Session`, `Module`, `Table`, `Row`, `Context`
+
+**Obiekty multi-threaded** - można współdzielić:
+- `BusApplication`, `Database`, `Login`
+
+Każdy wątek powinien tworzyć własną sesję (Login można współdzielić).
+
+### Extension methods dla modułów
+
+Dostęp do modułów przez extension methods:
+
+```csharp
+var tm = session.GetTowary();
+var hm = session.GetHandel();
+var crm = session.GetCRM();
+var kadry = session.GetKadry();
+var bm = session.GetBusiness();
+```
+
+### Transakcje biznesowe
+
+**Każda zmiana obiektu MUSI być w transakcji** `Session.Logout(editMode: true)`:
+
+```csharp
+using (var transaction = session.Logout(editMode: true))
+{
+ // Zmiany: dodawanie, modyfikacja, kasowanie
+ obiekt.Wlasciwosc = nowaWartosc;
+ transaction.Commit(); // Zatwierdza zmiany
+}
+// Brak Commit() = automatyczny rollback
+
+session.Save(); // Zapis do bazy danych
+```
+
+## Dostęp do danych
+
+### Odczyt listy towarów
+
+```csharp
+using Soneta.Business;
+using Soneta.Towary;
+
+public void WyswietlTowary(Login login)
+{
+ // Sesja tylko do odczytu
+ using (var session = login.CreateSession(true, false, "OdczytTowarow"))
+ {
+ var tm = session.GetTowary(); // Extension method
+
+ // Iteracja po kluczu podstawowym (WgKodu)
+ foreach (Towar t in tm.Towary.WgKodu)
+ {
+ Console.WriteLine($"{t.Kod}: {t.Nazwa}");
+ }
+ }
+}
+```
+
+### Wyszukiwanie po kluczu
+
+```csharp
+public Towar ZnajdzTowar(Session session, string kod)
+{
+ var tm = session.GetTowary();
+
+ // Wyszukiwanie po kluczu unikalnym
+ return tm.Towary.WgKodu[kod];
+}
+```
+
+### Iteracja z filtrowaniem
+
+```csharp
+public void WyswietlAktywneTowary(Session session)
+{
+ var tm = session.GetTowary();
+
+ foreach (Towar t in tm.Towary.WgKodu)
+ {
+ // Filtrowanie w kodzie
+ if (t.Typ == TypTowaru.Towar)
+ {
+ Console.WriteLine(t.Nazwa);
+ }
+ }
+}
+```
+
+## Tworzenie obiektów
+
+### Dodawanie nowego towaru
+
+```csharp
+public void DodajTowar(Login login)
+{
+ // Sesja edycyjna
+ using (var session = login.CreateSession(false, false, "DodawanieTowaru"))
+ {
+ var tm = session.GetTowary();
+
+ // Transakcja biznesowa - wymagana!
+ using (var transaction = session.Logout(editMode: true))
+ {
+ // Utworzenie nowego obiektu
+ var towar = new Towar();
+
+ // Dodanie do tabeli (zmiana stanu na Added)
+ tm.Towary.AddRow(towar);
+
+ // Ustawienie właściwości
+ towar.Kod = "NOWY001";
+ towar.Nazwa = "Nowy towar";
+ towar.Typ = TypTowaru.Towar;
+
+ transaction.Commit();
+ }
+
+ // Zapisanie do bazy
+ session.Save();
+ }
+}
+```
+
+### Dodawanie dokumentu z pozycjami
+
+```csharp
+public void UtworzFakture(Login login, Kontrahent kontrahentZInnejSesji,
+ List<(Towar towar, int ilosc)> pozycjeZInnejSesji)
+{
+ using (var session = login.CreateSession(false, false, "TworzenieFaktury"))
+ {
+ var hm = session.GetHandel();
+
+ // WAŻNE: Obiekty z innej sesji trzeba doczytać w bieżącej sesji!
+ var kontrahent = session.Get(kontrahentZInnejSesji);
+
+ // Cała operacja w jednej transakcji
+ using (var transaction = session.Logout(editMode: true))
+ {
+ // Utworzenie nagłówka dokumentu
+ var faktura = new DokumentHandlowy();
+ hm.DokHandlowe.AddRow(faktura);
+
+ faktura.Definicja = hm.DefDokHandlowe.WgSymbolu["FV"];
+ faktura.Kontrahent = kontrahent;
+ faktura.Data = Date.Today;
+
+ // Dodanie pozycji
+ int lp = 1;
+ foreach (var (towarZInnejSesji, ilosc) in pozycjeZInnejSesji)
+ {
+ // Doczytaj towar w bieżącej sesji
+ var towar = session.Get(towarZInnejSesji);
+
+ var poz = new PozycjaDokHandlowego(faktura);
+ faktura.Pozycje.AddRow(poz);
+
+ poz.Towar = towar;
+ poz.Ilosc = new Quantity(ilosc, towar.Jednostka.Kod);
+ poz.Lp = lp++;
+ }
+
+ transaction.Commit();
+ }
+
+ session.Save();
+ }
+}
+```
+
+**WAŻNE:** W jednej sesji nie można mieszać obiektów z różnych sesji. Użyj `session.Get(obiekt)` aby doczytać obiekt w bieżącej sesji.
+
+## Modyfikacja obiektów
+
+### Aktualizacja pojedynczego obiektu
+
+```csharp
+public void ZmienNazweTowaru(Login login, string kod, string nowaNazwa)
+{
+ using (var session = login.CreateSession(false, false, "EdycjaTowaru"))
+ {
+ var tm = session.GetTowary();
+ var towar = tm.Towary.WgKodu[kod];
+
+ if (towar != null)
+ {
+ using (var transaction = session.Logout(editMode: true))
+ {
+ towar.Nazwa = nowaNazwa;
+ transaction.Commit();
+ }
+ session.Save();
+ }
+ }
+}
+```
+
+### Aktualizacja z transakcją biznesową
+
+```csharp
+public void AktualizujCeny(Login login, string nazwaCeny, decimal procentPodwyzki)
+{
+ using (var session = login.CreateSession(false, false, "AktualizacjaCen"))
+ {
+ var tm = session.GetTowary();
+
+ foreach (Towar t in tm.Towary.WgKodu)
+ {
+ // Transakcja biznesowa - WYMAGANA dla każdej zmiany!
+ using (var transaction = session.Logout(editMode: true))
+ {
+ var cena = t.Ceny[nazwaCeny];
+ if (cena != null)
+ {
+ cena.Netto = new DoubleCy(cena.Netto.Value * (1 + procentPodwyzki / 100));
+ }
+ transaction.Commit();
+ }
+ }
+
+ session.Save(); // Zapisuje wszystkie zmiany do bazy
+ }
+}
+```
+
+## Usuwanie obiektów
+
+### Usuwanie obiektu
+
+```csharp
+public void UsunTowar(Login login, string kod)
+{
+ using (var session = login.CreateSession(false, false, "UsuwanieTowaru"))
+ {
+ var tm = session.GetTowary();
+ var towar = tm.Towary.WgKodu[kod];
+
+ if (towar != null)
+ {
+ using (var transaction = session.Logout(editMode: true))
+ {
+ towar.Delete(); // Zmiana stanu na Deleted
+ transaction.Commit();
+ }
+ session.Save(); // Fizyczne usunięcie z bazy
+ }
+ }
+}
+```
+
+## Praca z kontekstem
+
+### Worker wyliczający właściwość
+
+```csharp
+// Rejestracja workera na poziomie assembly
+[assembly: Worker]
+
+public class TowarWorker
+{
+ [Context]
+ public Magazyn MagazynFiltra { get; set; }
+
+ [Context]
+ public Towar Towar { get; set; }
+
+ public decimal StanMagazynowy
+ {
+ get
+ {
+ if (MagazynFiltra != null)
+ {
+ return PoliczStan(Towar, MagazynFiltra);
+ }
+ return PoliczStanCalkowity(Towar);
+ }
+ }
+
+ private decimal PoliczStan(Towar towar, Magazyn magazyn)
+ {
+ // Implementacja...
+ return 0;
+ }
+
+ private decimal PoliczStanCalkowity(Towar towar)
+ {
+ // Implementacja...
+ return 0;
+ }
+}
+```
+
+### Akcja workera w menu Czynności
+
+```csharp
+// Rejestracja workera na poziomie assembly
+[assembly: Worker]
+
+public class WyslijEmailWorker
+{
+ [Context]
+ public Kontrahent[] Kontrahenci { get; set; }
+
+ [Context]
+ public Context Context { get; set; }
+
+ [Action("Wyślij email")]
+ public void Execute()
+ {
+ foreach (var k in Kontrahenci)
+ {
+ if (!string.IsNullOrEmpty(k.Email))
+ {
+ WyslijEmail(k.Email);
+ }
+ }
+ }
+
+ private void WyslijEmail(string email)
+ {
+ // Implementacja...
+ }
+}
+```
+
+### Klasa parametrów (ContextBase)
+
+Klasa `ContextBase` jest przeznaczona do budowania klas parametrów, nie workerów:
+
+```csharp
+public class FiltryTowarow(Context context) : ContextBase(context)
+{
+ public Magazyn Magazyn { get; set; }
+
+ [Caption("Typ towaru")] // Etykieta w UI, gdy inna niż nazwa property
+ public TypTowaru? Typ { get; set; }
+
+ public bool TylkoAktywne { get; set; } = true;
+}
+```
+
+**Uwaga:** W klasach parametrów atrybut `[Context]` nie jest wymagany.
+
+**Współdzielenie wartości przez Context** - wartości parametrów można przechowywać w obiekcie Context, co pozwala na współdzielenie między różnymi klasami parametrów:
+
+```csharp
+public class FiltryTowarow(Context context) : ContextBase(context)
+{
+ public Magazyn Magazyn
+ {
+ get => Context.GetOrDefault();
+ set => Context.Set(value);
+ }
+
+ [Caption("Typ towaru")]
+ public TypTowaru? Typ
+ {
+ get => Context.GetOrDefault();
+ set => Context.Set(value);
+ }
+}
+```
+
+## Praca z GuidedRow
+
+### Dostęp do historii zmian
+
+```csharp
+public void PokazHistorie(Session session, Kontrahent kontrahent)
+{
+ var bm = session.GetBusiness();
+
+ Console.WriteLine($"Historia zmian dla: {kontrahent.Nazwa}");
+
+ foreach (ChangeInfo ci in bm.ChangeInfos[kontrahent])
+ {
+ Console.WriteLine($" {ci.Time}: {ci.Operator}");
+ }
+
+ // Skróty
+ Console.WriteLine($"Utworzono: {kontrahent.FirstChangeInfo?.Time}");
+ Console.WriteLine($"Ostatnia zmiana: {kontrahent.LastChangeInfo?.Time}");
+}
+```
+
+### Praca z załącznikami
+
+```csharp
+public void DodajZalacznik(Login login, Towar towar, byte[] plik, string nazwa)
+{
+ using (var session = login.CreateSession(false, false, "DodawanieZalacznika"))
+ {
+ // Doczytaj towar w bieżącej sesji
+ var towarInSession = session.Get(towar);
+
+ using (var transaction = session.Logout(editMode: true))
+ {
+ var attachment = new Attachment(towarInSession, AttachmentType.Attachments);
+ towarInSession.Module.Business.Attachments.AddRow(attachment);
+
+ attachment.Name = nazwa;
+ attachment.RawData = plik;
+
+ transaction.Commit();
+ }
+ session.Save();
+ }
+}
+
+public void WyswietlZalaczniki(Towar towar)
+{
+ foreach (Attachment att in towar.Attachments)
+ {
+ Console.WriteLine($"- {att.Name} ({att.RawData.Length} bajtów)");
+ }
+
+ // Domyślne zdjęcie
+ using var defaultImage = towar.DefaultImage;
+ if (defaultImage != null)
+ {
+ Console.WriteLine($"Zdjęcie główne: {defaultImage.FileName}");
+ }
+}
+```
+
+## Dane konfiguracyjne vs operacyjne
+
+### Odczyt danych konfiguracyjnych
+
+```csharp
+// Odczyt pojedynczej wartości
+var opisDlaSzt = login.ExecuteConfig(configSession =>
+ configSession.GetTowary().Jednostki.WgKodu["szt"]?.Opis);
+
+// Odczyt listy wartości prostych
+public string[] PobierzKodyJednostek(Login login)
+{
+ return login.ExecuteConfig(configSession =>
+ {
+ var tm = configSession.GetTowary();
+ return tm.Jednostki.WgKodu.Select(j => j.Kod).ToArray();
+ });
+}
+```
+
+**WAŻNE:** Używając `ExecuteConfig()` nie można zwracać obiektów sesyjnych z sesji konfiguracyjnej, ponieważ może być używana w innym wątku do innych celów. Zwracaj tylko wartości proste lub kopie danych.
+
+```csharp
+public void OdczytKonfiguracji(Login login)
+{
+ // Własna sesja konfiguracyjna - gdy potrzebny dostęp do obiektów
+ using (var session = login.CreateSession(true, true, "Konfiguracja"))
+ {
+ var tm = session.GetTowary();
+
+ foreach (Jednostka j in tm.Jednostki.WgKodu)
+ {
+ Console.WriteLine($"{j.Kod}: {j.Opis}");
+ }
+ }
+}
+```
+
+### Modyfikacja danych konfiguracyjnych
+
+```csharp
+public void DodajJednostke(Login login, string kod, string opis)
+{
+ // Sesja edycyjna konfiguracyjna
+ using (var session = login.CreateSession(false, true, "DodawanieJednostki"))
+ {
+ var tm = session.GetTowary();
+
+ using (var transaction = session.Logout(editMode: true))
+ {
+ var jednostka = new Jednostka();
+ tm.Jednostki.AddRow(jednostka);
+
+ jednostka.Kod = kod;
+ jednostka.Opis = opis;
+
+ transaction.Commit();
+ }
+
+ session.Save();
+ }
+}
+```
+
+## Pełny przykład - import towarów
+
+```csharp
+public class ImportTowarow
+{
+ public void Importuj(Login login, string sciezkaPliku)
+ {
+ var dane = WczytajZPliku(sciezkaPliku);
+
+ using (var session = login.CreateSession(false, false, "ImportTowarow"))
+ {
+ var tm = session.GetTowary();
+ int dodano = 0;
+ int zaktualizowano = 0;
+
+ // Cały import w jednej transakcji
+ using (var transaction = session.Logout(editMode: true))
+ {
+ foreach (var wiersz in dane)
+ {
+ // Sprawdź czy towar istnieje
+ var towar = tm.Towary.WgKodu[wiersz.Kod];
+
+ if (towar == null)
+ {
+ // Dodaj nowy
+ towar = new Towar();
+ tm.Towary.AddRow(towar);
+ towar.Kod = wiersz.Kod;
+ dodano++;
+ }
+ else
+ {
+ zaktualizowano++;
+ }
+
+ // Ustaw/aktualizuj właściwości
+ towar.Nazwa = wiersz.Nazwa;
+ var cena = towar.Ceny["Hurtowa"];
+ cena.Netto = new DoubleCy(wiersz.Cena);
+ }
+
+ transaction.Commit();
+ }
+
+ session.Save();
+
+ Console.WriteLine($"Import zakończony:");
+ Console.WriteLine($" Dodano: {dodano}");
+ Console.WriteLine($" Zaktualizowano: {zaktualizowano}");
+ }
+ }
+
+ private List WczytajZPliku(string sciezka)
+ {
+ // Implementacja wczytywania z CSV/Excel...
+ return new List();
+ }
+
+ private class DaneImportu
+ {
+ public string Kod { get; set; }
+ public string Nazwa { get; set; }
+ public decimal Cena { get; set; }
+ }
+}
+```
+
+## Obsługa błędów
+
+### Wzorzec try-catch z sesją
+
+```csharp
+public void BezpiecznaOperacja(Login login)
+{
+ using (var session = login.CreateSession(false, false, "Operacja"))
+ {
+ try
+ {
+ var tm = session.GetTowary();
+
+ using (var transaction = session.Logout(editMode: true))
+ {
+ // Operacje na danych...
+ var towar = new Towar();
+ tm.Towary.AddRow(towar);
+ towar.Kod = "TEST";
+
+ transaction.Commit();
+ }
+
+ session.Save();
+ }
+ catch (Exception ex)
+ {
+ // Logowanie błędu
+ Console.WriteLine($"Błąd: {ex.Message}");
+ // Zmiany nie zostały zatwierdzone (brak Commit lub Save)
+ // Sesja zostanie automatycznie zwolniona przez using
+ }
+ }
+}
+```
+
+### Wzorzec z wieloma operacjami
+
+```csharp
+public void WieleOperacji(Login login, List kody)
+{
+ using (var session = login.CreateSession(false, false, "WieleOperacji"))
+ {
+ var tm = session.GetTowary();
+ var bledy = new List();
+
+ foreach (var kod in kody)
+ {
+ try
+ {
+ using (var transaction = session.Logout(editMode: true))
+ {
+ var towar = tm.Towary.WgKodu[kod];
+ if (towar != null)
+ {
+ towar.Delete();
+ transaction.Commit();
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ bledy.Add($"{kod}: {ex.Message}");
+ // Kontynuuj z następnym elementem
+ }
+ }
+
+ session.Save(); // Zapisz udane operacje
+
+ if (bledy.Any())
+ {
+ Console.WriteLine("Błędy: " + string.Join(", ", bledy));
+ }
+ }
+}
+```
diff --git a/soneta-programming-basics/references/session-login.md b/soneta-programming-basics/references/session-login.md
new file mode 100644
index 0000000..f877b4b
--- /dev/null
+++ b/soneta-programming-basics/references/session-login.md
@@ -0,0 +1,366 @@
+# Session, Login, Database, BusApplication
+
+Dokumentacja klas zarządzających połączeniem z bazą danych i sesjami w platformie enova365/Soneta.
+
+## Hierarchia obiektów
+
+```
+BusApplication (Singleton)
+ └── Database[] (kolekcja baz danych)
+ └── Login (uwierzytelniony użytkownik)
+ └── Session[] (sesje robocze)
+ └── Module → Table → Row
+```
+
+## BusApplication
+
+Singleton reprezentujący instancję aplikacji ERP. Tworzony podczas inicjalizacji systemu.
+
+### Dostęp do instancji
+
+```csharp
+// Singleton
+BusApplication app = BusApplication.Instance;
+
+// Dostęp do bazy danych po nazwie
+Database db = BusApplication.Instance["BazaDemo"];
+
+// Iteracja po wszystkich bazach
+foreach (Database db in BusApplication.Instance)
+{
+ Console.WriteLine(db.Name);
+}
+```
+
+### Właściwości
+
+| Właściwość | Typ | Opis |
+|------------|-----|------|
+| `Instance` | `BusApplication` | Statyczny singleton |
+| `Is365` | `bool` | `true` = wersja HTML, `false` = wersja okienkowa |
+| `this[string]` | `Database` | Indeksator - baza po nazwie |
+
+## Database
+
+Abstrakcyjna klasa reprezentująca bazę danych. Konkretne implementacje dla wspieranych silników:
+
+```
+Database (abstrakcyjna)
+ └── SqlDatabase (abstrakcyjna)
+ ├── MsSqlDatabase (SQL Server)
+ └── AzureDatabase (Azure SQL)
+```
+
+**Uwaga:** MySqlDatabase oraz OracleDatabase nie są już obsługiwane.
+
+### Konfiguracja
+
+Obiekty Database są deserializowane z pliku `Lista baz danych.xml`.
+
+### Właściwości
+
+| Właściwość | Typ | Opis |
+|------------|-----|------|
+| `Name` | `string` | Nazwa bazy danych |
+| `DefaultDatabase` | `bool` | Czy baza domyślna |
+| `DatabaseName` | `string` | Nazwa bazy w silniku SQL (SqlDatabase) |
+
+### Logowanie do bazy
+
+```csharp
+Database db = BusApplication.Instance["BazaDemo"];
+
+// ZALECANE: Logowanie z LoginParameters
+Login login = db.Login(new LoginParameters
+{
+ UserName = "Administrator",
+ UserPassword = "password"
+});
+
+// Logowanie zintegrowane Windows
+Login login = db.Login(new LoginParameters
+{
+ UserName = LoginParameters.WindowsAuthenticationUser
+});
+```
+
+## Login
+
+Obiekt reprezentujący zalogowanego użytkownika. Zarządza sesjami.
+
+### Tworzenie
+
+```csharp
+Database db = BusApplication.Instance["BazaDemo"];
+Login login = db.Login(new LoginParameters
+{
+ UserName = "Administrator",
+ UserPassword = "password"
+});
+```
+
+### Dostęp do informacji o operatorze
+
+**WAŻNE:** Właściwości `Operator` i `Entitle` w klasie `Login` nie należy stosować, ponieważ używają obiektu z `ConfigSession` w sposób niekontrolowany.
+
+```csharp
+// NIE ZALECANE:
+// var op = login.Operator; // unikać!
+// var ent = login.Entitle; // unikać!
+
+// ZALECANE: Użyj w konkretnej sesji
+using (var session = login.CreateSession(true, false, "Odczyt"))
+{
+ var op = session.AuthorizationInfo.Operator;
+ Console.WriteLine($"Zalogowany: {op.Name} - {op.FullName}");
+}
+```
+
+### Właściwości informacyjne
+
+| Właściwość | Typ | Opis |
+|------------|-----|------|
+| `IsWebUser` | `bool` | Czy operator pulpitu (web) |
+| `Licencje` | `IEnumerable` | Pobrane licencje |
+| `Database` | `Database` | Baza danych logowania |
+
+### Tworzenie sesji
+
+```csharp
+// ZALECANA sygnatura (czytelność + debugowanie)
+Session session = login.CreateSession(
+ readOnly: false, // true = tylko odczyt
+ config: false, // true = dane konfiguracyjne
+ name: "MojaSesja" // nazwa sesji - pomocna przy debugowaniu
+);
+```
+
+**Zawsze używaj wersji z parametrem `name`** - ułatwia debugowanie i identyfikację sesji.
+
+### Dostęp do danych konfiguracyjnych
+
+```csharp
+// ZALECANE: ExecuteConfig z lambdą (zwraca wartość prostą)
+var opisDlaSzt = login.ExecuteConfig(configSession =>
+ configSession.GetTowary().Jednostki.WgKodu["szt"]?.Opis);
+
+// NIE ZALECANE: login.ConfigSession
+// var configSession = login.ConfigSession; // unikać!
+```
+
+**WAŻNE:** Używając `ExecuteConfig()` nie można zwracać obiektów sesyjnych z sesji konfiguracyjnej, ponieważ może być używana w innym wątku do innych celów. Zwracaj tylko wartości proste lub kopie danych.
+
+### Sygnatury CreateSession
+
+```csharp
+public Session CreateSession(bool readOnly, bool config, string name)
+public Session CreateSession(bool readOnly, bool config)
+public Session CreateSession() // readOnly=false, config=false
+```
+
+## Session
+
+Fundamentalna klasa do zarządzania danymi. **Każda operacja na danych wymaga sesji.**
+
+### Tworzenie
+
+```csharp
+// ZAWSZE używaj using lub wywołuj Dispose()
+using (var session = login.CreateSession(false, false, "MojaSesja"))
+{
+ // operacje na danych
+ session.Save();
+}
+```
+
+### Typy sesji - macierz
+
+| ReadOnly | Config | Zastosowanie |
+|----------|--------|--------------|
+| `false` | `false` | **Edycja operacyjna** - dokumenty, kartoteki |
+| `true` | `false` | **Odczyt operacyjny** - raporty, wyświetlanie |
+| `false` | `true` | **Edycja konfiguracyjna** - ustawienia systemu |
+| `true` | `true` | **Odczyt konfiguracyjny** - odczyt słowników |
+
+**WAŻNE:** W sesji operacyjnej (`config: false`) nie można modyfikować obiektów konfiguracyjnych. Do modyfikacji konfiguracji wymagana jest sesja konfiguracyjna (`config: true`).
+
+### Właściwości
+
+| Właściwość | Typ | Opis |
+|------------|-----|------|
+| `ReadOnly` | `bool` | Czy sesja tylko do odczytu |
+| `IsConfig` | `bool` | Czy sesja konfiguracyjna |
+| `Name` | `string` | Nazwa sesji |
+| `Login` | `Login` | Obiekt logowania |
+| `Database` | `Database` | Baza danych |
+
+### Metody zarządzania danymi
+
+```csharp
+// Zapisanie zmian do bazy
+session.Save();
+```
+
+### Dane operacyjne vs konfiguracyjne
+
+**Dane operacyjne (`config=false`):**
+- Dokumenty, kartoteki, transakcje
+- Zawsze odczytywane z bazy (aktualność)
+- Modyfikacje zapisywane natychmiast przy `Save()`
+
+**Dane konfiguracyjne (`config=true`):**
+- Słowniki, definicje, ustawienia
+- Buforowane w cache (optymalizacja)
+- Modyfikowane rzadko, odczytywane często
+- Określane atrybutem `config="true"` w business.xml
+
+### Wiele sesji jednocześnie
+
+```csharp
+// Normalne zjawisko - wiele sesji może współistnieć
+using (var session1 = login.CreateSession(true, false, "Lista1"))
+using (var session2 = login.CreateSession(true, false, "Lista2"))
+{
+ // Obie sesje mogą odczytywać te same dane
+ var tm1 = session1.GetTowary();
+ var tm2 = session2.GetTowary();
+}
+```
+
+### Transakcje biznesowe - Session.Logout()
+
+**WAŻNE:** Każda zmiana obiektu biznesowego MUSI być w transakcji!
+
+```csharp
+using (var session = login.CreateSession(false, false, "Edycja"))
+{
+ var tm = session.GetTowary();
+ var towar = tm.Towary.WgKodu["KOD001"];
+
+ // Logout(editMode: true) - transakcja EDYCYJNA (można modyfikować)
+ using (var transaction = session.Logout(editMode: true))
+ {
+ towar.Nazwa = "Nowa nazwa";
+ var cena = towar.Ceny["Hurtowa"];
+ cena.Netto = new DoubleCy(100.00m);
+ transaction.Commit(); // Zatwierdza zmiany w sesji
+ }
+ // Brak Commit() = rollback (przywrócenie stanu sprzed Logout)
+
+ session.Save(); // Zapisuje do bazy danych
+}
+```
+
+### Logout(editMode: false) - transakcja tylko do odczytu
+
+```csharp
+using (var session = login.CreateSession(false, false, "Przeglad"))
+{
+ var tm = session.GetTowary();
+ var towar = tm.Towary.WgKodu["KOD001"];
+
+ // Transakcja tylko do odczytu
+ using (var readTrans = session.Logout(editMode: false))
+ {
+ // Tutaj NIE można modyfikować
+
+ // Ale można otworzyć zagnieżdżoną transakcję edycyjną
+ using (var editTrans = session.Logout(editMode: true))
+ {
+ var cena = towar.Ceny["Hurtowa"];
+ cena.Netto = new DoubleCy(200m);
+ editTrans.Commit();
+ }
+
+ // WAŻNE: Commit wymagany też dla transakcji readonly!
+ // Inaczej zmiany z zagnieżdżonych transakcji edycyjnych przepadną
+ readTrans.Commit();
+ }
+ session.Save();
+}
+```
+
+| Metoda | Opis |
+|--------|------|
+| `session.Logout(editMode: true)` | Transakcja edycyjna - można modyfikować |
+| `session.Logout(editMode: false)` | Transakcja tylko do odczytu |
+| `transaction.Commit()` | Zatwierdza zmiany (wymagane dla obu typów!) |
+| `transaction.CommitUI()` | Zatwierdza + odświeża UI |
+| `transaction.Dispose()` | Bez Commit = rollback (także zagnieżdżonych zmian) |
+
+## Kompletny przykład
+
+```csharp
+// 1. Pobranie instancji aplikacji
+BusApplication app = BusApplication.Instance;
+
+// 2. Pobranie bazy danych
+Database db = app["MojaBaza"];
+
+// 3. Logowanie
+Login login = db.Login(new LoginParameters
+{
+ UserName = "admin",
+ UserPassword = "haslo"
+});
+
+// 4. Utworzenie sesji (zawsze z nazwą!)
+using (var session = login.CreateSession(false, false, "Import"))
+{
+ // 5. Pobranie modułu (extension method)
+ var tm = session.GetTowary();
+
+ // 6. Transakcja biznesowa - WYMAGANA dla zmian!
+ using (var transaction = session.Logout(editMode: true))
+ {
+ var nowyTowar = new Towar();
+ tm.Towary.AddRow(nowyTowar);
+ nowyTowar.Kod = "IMPORT001";
+ nowyTowar.Nazwa = "Zaimportowany towar";
+
+ transaction.Commit();
+ }
+
+ // 7. Zapis do bazy
+ session.Save();
+}
+// 8. Session automatycznie Dispose() przez using
+```
+
+## Thread-safety
+
+### Obiekty multi-threaded (można współdzielić między wątkami)
+- `BusApplication`
+- `Database`
+- `Login`
+
+### Obiekty single-threaded (NIE współdzielić)
+- `Session`, `Module`, `Table`, `Row`, `Context`
+
+```csharp
+// DOBRZE - Login można współdzielić, każdy wątek tworzy własną sesję
+Login sharedLogin = db.Login(new LoginParameters { UserName = "admin", UserPassword = "haslo" });
+
+Parallel.ForEach(items, item => {
+ using (var session = sharedLogin.CreateSession(false, false, "Watek"))
+ {
+ var tm = session.GetTowary();
+ using (var transaction = session.Logout(editMode: true))
+ {
+ // operacje...
+ transaction.Commit();
+ }
+ session.Save();
+ }
+});
+```
+
+## Sesja bez interfejsu graficznego
+
+Sesja działa w warstwie logiki biznesowej - **nie wymaga UI**.
+
+Przykłady użycia bez interfejsu:
+- **Harmonogram Zadań** - usługa Windows wykonująca operacje bazodanowe
+- **Importy danych** - procesy wsadowe
+- **Testy jednostkowe** - automatyczne testy logiki
+- **API REST** - obsługa żądań HTTP