From 09c40f22dcd895b777ccffc6f7daa60407deaa80 Mon Sep 17 00:00:00 2001 From: Marcin Wojas Date: Fri, 26 Dec 2025 22:22:34 +0100 Subject: [PATCH] Added: soneta-business-xml, soneta-programming-basics --- .DS_Store | Bin 0 -> 6148 bytes soneta-business-xml/SKILL.md | 305 +++++++++ soneta-business-xml/assets/Business.xsd | 192 ++++++ soneta-business-xml/references/examples.md | 353 ++++++++++ .../references/modules-catalog.md | 525 ++++++++++++++ .../references/relations-guide.md | 277 ++++++++ .../references/table-reference.md | 289 ++++++++ soneta-programming-basics/SKILL.md | 351 ++++++++++ .../references/context.md | 334 +++++++++ .../references/datapack-guidedrow.md | 245 +++++++ .../references/examples.md | 643 ++++++++++++++++++ .../references/session-login.md | 366 ++++++++++ 12 files changed, 3880 insertions(+) create mode 100644 .DS_Store create mode 100644 soneta-business-xml/SKILL.md create mode 100644 soneta-business-xml/assets/Business.xsd create mode 100644 soneta-business-xml/references/examples.md create mode 100644 soneta-business-xml/references/modules-catalog.md create mode 100644 soneta-business-xml/references/relations-guide.md create mode 100644 soneta-business-xml/references/table-reference.md create mode 100644 soneta-programming-basics/SKILL.md create mode 100644 soneta-programming-basics/references/context.md create mode 100644 soneta-programming-basics/references/datapack-guidedrow.md create mode 100644 soneta-programming-basics/references/examples.md create mode 100644 soneta-programming-basics/references/session-login.md diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..0f14af3bf9ad990edd5adc3fc640c116f1ac7133 GIT binary patch literal 6148 zcmeHK%Sr=55UkN00v-%_(cAn$4*tOs;=!{&;BJ%q+v{z+YPM~|4AFI}_TobQ;!~9eJhJMVea-A0RBv6_sTsM!3f(sqSu`XV z2nK?IU?3RyaRzv1OQt7=(FX&;KrrymfcA&XCafHL!?Ja-)Ad>YiBLjamt$detQ>no zdML?KiI$rDiIFUw_Uv($V{d5bNM&Z$@tNNqFR9EpQp1nv)!^u6xU0kP#;_ZIM6s)DK!BA literal 0 HcmV?d00001 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