From 3e5239cb60fa684e74fb8c3dbff88ab5c0baae40 Mon Sep 17 00:00:00 2001 From: Marcin Wojas Date: Sat, 16 May 2026 16:06:36 +0200 Subject: [PATCH] =?UTF-8?q?Przemianowa=C5=82em=20istnij=C4=85ce=20skille?= =?UTF-8?q?=20na=20prostsze=20nazwy=20-=20porz=C4=85dki?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 44 ++-- .../Dodatkowe elementy projektu.md | 2 +- soneta-addon-planning/SKILL.md | 2 +- soneta-erp/SKILL.md | 37 ++++ soneta-place-def-elementow/SKILL.md | 35 ++- .../SKILL.md | 200 +++++++++++++++--- .../references/context.md | 6 +- .../references/datapack-guidedrow.md | 0 .../references/examples.md | 0 .../references/session-login.md | 42 ++-- 10 files changed, 277 insertions(+), 91 deletions(-) create mode 100644 soneta-erp/SKILL.md rename {soneta-programming-basics => soneta-programming}/SKILL.md (61%) rename {soneta-programming-basics => soneta-programming}/references/context.md (98%) rename {soneta-programming-basics => soneta-programming}/references/datapack-guidedrow.md (100%) rename {soneta-programming-basics => soneta-programming}/references/examples.md (100%) rename {soneta-programming-basics => soneta-programming}/references/session-login.md (90%) diff --git a/README.md b/README.md index 3ad5d1c..a79d1e2 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,16 @@ # Soneta / enova365 AI Skills -Zestaw skills dla asystentów AI (Claude, Cursor, Windsurf, itp.) wspierających programowanie i projektowanie z platformą **enova365/Soneta Enterprise**. +Zestaw skills dla asystentów AI (Claude, Cursor, Windsurf, itp.) wspierających programowanie, projektowanie i konfigurację platformy **enova365 / Soneta Enterprise / Triva**. ## Dostępne skille -### 1. soneta-programming-basics +### 0. soneta-erp (meta-skill) + +Mapa i przewodnik po pozostałych skillach. Pomaga wybrać właściwy skill w zależności od warstwy zadania (dane, UI, logika, płace). + +**Kiedy używać:** rozpoczynasz nowe zadanie dla enova365/Soneta/Triva i nie wiesz, który skill zastosować; zadanie obejmuje wiele warstw platformy i potrzebna jest koordynacja między skillami. + +### 1. soneta-programming Fundamentalne klasy ORM platformy enova365/Soneta Enterprise. @@ -68,36 +74,36 @@ System projektowy (design system) Soneta / enova365 do budowania aplikacji webow **Kiedy używać:** projektowanie stron/aplikacji w stylu enova365, dashboardy, formularze, strony logowania, panele administracyjne. -### 6. soneta-mcp-ui-guide +### 6. soneta-place-def-elementow -Obsługa programów Soneta (enova365, Triva) przez narzędzia MCP `soneta_ui`. +Tworzenie i konfiguracja definicji elementów wynagrodzenia w enova365 (moduł Płace). **Zakres:** -- Nawigacja po modułach i folderach programu (Handel, Kadry, Księgowość, CRM, itp.) -- Przeglądanie list z filtrowaniem i stronicowaniem -- Otwieranie formularzy i przełączanie zakładek -- Edycja danych na formularzach (pola oznaczone jako `edytowany`) -- Dodawanie nowych obiektów -- Mapa ~100 najczęściej używanych folderów programu +- Algorytmy naliczania: kreator, edytor C# (`_Param`, `_Wylicz`, `_Wartość1h`), algorytmy wbudowane +- 12 wzorców dla Dodatków, 5 dla Nieobecności, 5 dla Dodatków automatycznych (z analizy ~247 definicji) +- Receptury kodu C#: iterowanie po elementach, staż pracy, wymiar etatu, czas pracy, wskaźniki, cechy pracownika +- Konfiguracja zakładek: Ogólne, Deklaracje (PIT/ZUS), Nieobecności, Algorytm +- Metody sterujące naliczaniem (`_PodstawaUrlopu`, `_PodstawaZasiłku`) -**Kiedy używać:** odczyt/edycja danych w enova365 lub Triva przez MCP — kontrahenci, faktury, pracownicy, towary, stany magazynowe, przelewy, deklaracje. +**Kiedy używać:** tworzenie/modyfikacja definicji elementu wynagrodzenia, pisanie algorytmów płacowych (premia procentowa, dodatek stażowy, zasiłek chorobowy, ekwiwalent za urlop). ## Powiązania między skillami Skille są zaprojektowane do współpracy: -1. **soneta-addon-planning** → planuje strukturę nowego dodatku -2. **soneta-business-xml** → definiuje obiekty biznesowe w XML -3. **soneta-programming-basics** → pokazuje jak pracować z wygenerowanymi klasami C# -4. **soneta-form-xml** → tworzy formularze UI dla obiektów -5. **soneta-ui-style** → styluje interfejs webowy zgodnie z design systemem enova365 -6. **soneta-mcp-ui-guide** → obsługuje dane w działającej instancji enova365/Triva przez MCP +1. **soneta-erp** → wskazuje właściwy skill dla danego zadania +2. **soneta-addon-planning** → planuje strukturę nowego dodatku +3. **soneta-business-xml** → definiuje obiekty biznesowe w XML +4. **soneta-programming** → pokazuje jak pracować z wygenerowanymi klasami C# +5. **soneta-form-xml** → tworzy formularze UI dla obiektów +6. **soneta-ui-style** → styluje interfejs webowy zgodnie z design systemem enova365 +7. **soneta-place-def-elementow** → konfiguruje warstwę płacową (definicje elementów wynagrodzenia) ## Instalacja ### Claude Code -Skopiuj folder ze skillem do `~/.claude/skills/`. +Skopiuj foldery skilli do `~/.claude/skills/`. ### Cursor / Windsurf / inne IDE @@ -105,4 +111,4 @@ Dodaj zawartość skilli do kontekstu projektu lub rules. ## Licencja -MIT +MIT \ No newline at end of file diff --git a/soneta-addon-planning/Dodatkowe elementy projektu.md b/soneta-addon-planning/Dodatkowe elementy projektu.md index bdd26fb..e461c13 100644 --- a/soneta-addon-planning/Dodatkowe elementy projektu.md +++ b/soneta-addon-planning/Dodatkowe elementy projektu.md @@ -87,7 +87,7 @@ Plan projektu generowany jest jako dokument Markdown z następującą strukturą Po zatwierdzeniu planu projektu: 1. **enova365-business-xml** - generowanie pliku business.xml na podstawie modelu danych -2. **soneta-programming-basics** - implementacja workerów i logiki biznesowej +2. **soneta-programming** - implementacja workerów i logiki biznesowej ## Szczegółowa dokumentacja diff --git a/soneta-addon-planning/SKILL.md b/soneta-addon-planning/SKILL.md index 9131bcc..646b274 100644 --- a/soneta-addon-planning/SKILL.md +++ b/soneta-addon-planning/SKILL.md @@ -325,4 +325,4 @@ Po zakończeniu wszystkich etapów wygeneruj dokument TODO z kolejnymi krokami: Po zatwierdzeniu planu projektu: 1. **soneta-business-xml** — generowanie pliku business.xml na podstawie modelu danych z Etapu 3 2. **soneta-form-xml** — generowanie formularzy i widoków UI na podstawie sekcji 3.4 i 3.5 -3. **soneta-programming-basics** — implementacja logiki biznesowej, workerów +3. **soneta-programming** — implementacja logiki biznesowej, workerów diff --git a/soneta-erp/SKILL.md b/soneta-erp/SKILL.md new file mode 100644 index 0000000..ae3d5e0 --- /dev/null +++ b/soneta-erp/SKILL.md @@ -0,0 +1,37 @@ +--- +name: soneta-erp +description: > + Mapa i przewodnik po wyspecjalizowanych skillach do pracy z platformą Soneta ERP + (enova365, Soneta Enterprise, Triva). Pomaga wybrać właściwy skill w zależności od + zadania: programowanie ORM (soneta-programming), planowanie dodatków + (soneta-addon-planning), definicje obiektów biznesowych (soneta-business-xml), + formularze UI (soneta-form-xml), definicje elementów wynagrodzenia + (soneta-place-def-elementow). Używaj tego skilla ZAWSZE gdy użytkownik: (1) rozpoczyna + nowe zadanie związane z enova365/Soneta/Triva i nie jest jasne, który wyspecjalizowany + skill zastosować; (2) pyta ogólnie o tworzenie dodatków, modułów lub rozszerzeń dla + Soneta ERP; (3) wspomina o platformie enova, Soneta Enterprise, Triva bez sprecyzowania + warstwy (dane, UI, logika, płace); (4) chce poznać dostępne narzędzia/skille do pracy + z ekosystemem Soneta; (5) realizuje zadanie obejmujące wiele warstw platformy + (np. nowy moduł z bazą danych, formularzami i logiką) i potrzebuje koordynacji między + skillami. +--- + +# Mapa skills podczas pracy z Soneta ERP (enova/Triva) + +* `/soneta-programming` - 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, Context +* `/soneta-addon-planning` - Planowanie projektów dodatków dla platformy enova365/Soneta Enterprise. Tworzy + kompletną dokumentację projektową obejmującą: strukturę danych (tabele, relacje), + elementy konfigurowalne, definicje list i menu, formularze, workery i raporty. + Używaj gdy użytkownik prosi o zaplanowanie nowego modułu/dodatku enova365, + przygotowanie założeń projektu, stworzenie specyfikacji funkcjonalnej dodatku, + lub zdefiniowanie struktury danych i interfejsu użytkownika dla nowego modułu. +* `/soneta-business-xml` - 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-form-xml` - XML z nieistniejącymi elementami. ZAWSZE używaj tego skilla gdy użytkownik: (1) prosi o utworzenie lub modyfikację pliku pageform.xml, viewform.xml, form.xml, lookupform.xml lub gridform.xml dla enova365/Soneta; (2) pyta o elementy DataForm, Page, Group, Grid, Field, Row, Stack, Flow, Command, Include, Appearance, GroupBy w enova365; (3) pyta o składnię EditValue, DataContext, Visibility, RowCondition, Renderable, CaptionHtml, Footer, Class lub układ UI formularzy enova365; (4) pokazuje istniejący plik form.xml/pageform.xml/viewform.xml i pyta o jego strukturę lub chce go rozszerzyć; (5) pyta o warunkową widoczność, formatowanie warunkowe (Appearance), bindowanie danych lub wzorce UI w Soneta/enova365. diff --git a/soneta-place-def-elementow/SKILL.md b/soneta-place-def-elementow/SKILL.md index 53c515c..7ef991f 100644 --- a/soneta-place-def-elementow/SKILL.md +++ b/soneta-place-def-elementow/SKILL.md @@ -143,31 +143,46 @@ update_field_value(["_Tekst=public void Nazwa_Param(...) {\\n ...\\n}\\n\\npu ## Wskazówki przy tworzeniu nowych algorytmów -1. **Wybierz wzorzec** — większość nowych elementów pasuje do jednego z istniejących wzorców. Przeczytaj `references/wzorce-algorytmiczne.md` i zacznij od skopiowania najbliższego wzorca. +1. **`Element` to parametr metody** — w kodzie algorytmu `Element` nie jest zmienną globalną ani polem klasy — jest **pierwszym parametrem** każdej metody (`_Param`, `_Wylicz`, `_Wartość1h` itd.). + Metoda musi zawsze zawierać te parametry. + Typ tego parametru musi odpowiadać rodzajowi definiowanego elementu: + - Etat → `Soneta.Place.WypElementEtat Element` + - Dodatek → `Soneta.Place.WypElementDodatek Element` + - Dodatek automatyczny → `Soneta.Place.WypElementDodatekAutomatyczny Element` + - Nieobecność → `Soneta.Place.WypElementNieobecnosc Element` + - Nadgodziny → `Soneta.Place.WypElementNadgodziny Element` + - Umowa → `Soneta.Place.WypElementUmowa Element` -2. **Źródło kwoty** — zdecyduj skąd pochodzi podstawa: + Przykład: jeśli algorytm odwołuje się do `Element.DodHistoria.Podstawa`, a definicja jest rodzaju **Dodatek**, to sygnatura metody musi wyglądać: + ```csharp + public void MojDodatek_Param(WypElementDodatek Element, WypSkladnik Składnik) { ... } + ``` + +2. **Wybierz wzorzec** — większość nowych elementów pasuje do jednego z istniejących wzorców. Przeczytaj `references/wzorce-algorytmiczne.md` i zacznij od skopiowania najbliższego wzorca. + +3. **Źródło kwoty** — zdecyduj skąd pochodzi podstawa: - Kwota z parametrów pracownika → `Element.DodHistoria.Podstawa` (Wzorzec A) - Kwota z konfiguracji programu → `module.Config.Zasiłki.*[Date]` (Wzorzec B) - Kwota stała z definicji → `Element.Definicja.Algorytm.KreatorAlgorytmu.Podstawa` (Wzorzec C) - Procent od zasadniczego → `ZasadniczeNominalne(Date)` + `Element.DodHistoria.Procent` (Wzorzec D) -3. **Czas i dni** — prawie wszystkie algorytmy ustawiają czas i dni z normy: +4. **Czas i dni** — prawie wszystkie algorytmy ustawiają czas i dni z normy: ```csharp CzasDni cd = Element.Pracownik.Czasy.Norma(Składnik.Okres); Składnik.Czas = cd.Czas; Składnik.Dni = cd.Dni; ``` -4. **Pomniejszenie za nieobecności** — użyj kreatora algorytmu z konfiguracją korekt lub ręcznie: `Element.Pracownik.Czasy.Nieobecnosci(Składnik.Okres).Dni` +5. **Pomniejszenie za nieobecności** — użyj kreatora algorytmu z konfiguracją korekt lub ręcznie: `Element.Pracownik.Czasy.Nieobecnosci(Składnik.Okres).Dni` -5. **Proporcjonalność do okresu** — gdy okres składnika jest krótszy niż pełny okres naliczania, przelicz proporcjonalnie (jak w Premii procentowej — Wzorzec D). +6. **Proporcjonalność do okresu** — gdy okres składnika jest krótszy niż pełny okres naliczania, przelicz proporcjonalnie (jak w Premii procentowej — Wzorzec D). -6. **Zasiłki** — zawsze używaj `new PodstawaZasiłku(Element)` i `WyliczPodstawęZasiłkuZaDzień(...)` — nie obliczaj podstawy zasiłku ręcznie. +7. **Zasiłki** — zawsze używaj `new PodstawaZasiłku(Element)` i `WyliczPodstawęZasiłkuZaDzień(...)` — nie obliczaj podstawy zasiłku ręcznie. -7. **Urlopy okolicznościowe** — używaj `new NaliczanieOkolicznosciowy(Element, Składnik).NaliczPodstawy()` — automatycznie ustawi Podstawa1 (za godziny) i Podstawa2 (za dni). +8. **Urlopy okolicznościowe** — używaj `new NaliczanieOkolicznosciowy(Element, Składnik).NaliczPodstawy()` — automatycznie ustawi Podstawa1 (za godziny) i Podstawa2 (za dni). -8. **Ekwiwalenty i odprawy** — używaj `new NaliczanieEkwiwalent(Element, Składnik).NaliczPodstawy()`. +9. **Ekwiwalenty i odprawy** — używaj `new NaliczanieEkwiwalent(Element, Składnik).NaliczPodstawy()`. -9. **Element.DodHistoria.Podstawa vs Element.DodHistoria.Kwota** — w rzeczywistych algorytmach kreatorowych kwota pobierana jest z `Element.DodHistoria.Podstawa` (nie `.Kwota`). Pole `.Kwota` występuje w dokumentacji, ale `.Podstawa` jest częściej stosowane w generowanym kodzie. +10. **Element.DodHistoria.Podstawa vs Element.DodHistoria.Kwota** — w rzeczywistych algorytmach kreatorowych kwota pobierana jest z `Element.DodHistoria.Podstawa` (nie `.Kwota`). Pole `.Kwota` występuje w dokumentacji, ale `.Podstawa` jest częściej stosowane w generowanym kodzie. -10. **Dodatkowe metody** — jeśli element ma odbiorców płatności (potrącenia, alimenty), zdefiniuj metody `_Odbiorca` i `_RachunekOdbiorcy`. Jeśli okres naliczania wymaga podziału, zdefiniuj `_CięcieOkresu`. Jeśli element wpływa na podstawy urlopów/zasiłków — przeczytaj `references/metody-sterujace-naliczaniem.md`. +11. **Dodatkowe metody** — jeśli element ma odbiorców płatności (potrącenia, alimenty), zdefiniuj metody `_Odbiorca` i `_RachunekOdbiorcy`. Jeśli okres naliczania wymaga podziału, zdefiniuj `_CięcieOkresu`. Jeśli element wpływa na podstawy urlopów/zasiłków — przeczytaj `references/metody-sterujace-naliczaniem.md`. diff --git a/soneta-programming-basics/SKILL.md b/soneta-programming/SKILL.md similarity index 61% rename from soneta-programming-basics/SKILL.md rename to soneta-programming/SKILL.md index 7778736..0427784 100644 --- a/soneta-programming-basics/SKILL.md +++ b/soneta-programming/SKILL.md @@ -1,5 +1,5 @@ --- -name: soneta-programming-basics +name: soneta-programming description: > Fundamentalne klasy ORM platformy enova365/Soneta Enterprise. Obejmuje mapowanie obiektowo-relacyjne (Row, Table, Module), zarządzanie sesją (Session), logowanie @@ -11,27 +11,19 @@ description: > # 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. +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 kodu i 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 │ -└─────────────────────────────────────────────────────┘ +BusApplication.Instance (singleton) - multihreaded + └── Database + └── Login + └── Session - singlethreaded + └── Module + └── Table + └── Row ``` ## 3 poziomy logiki biznesowej @@ -69,8 +61,6 @@ Module (abstrakcyjna) - `Context` - oraz wszystkie klasy pochodne -Każdy wątek powinien tworzyć własną sesję. - ### Obiekty multi-threaded (można współdzielić) - `BusApplication` - `Database` @@ -85,10 +75,6 @@ Session to kluczowa klasa do zarządzania danymi. **Każda operacja na danych wy ```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 @@ -151,6 +137,7 @@ Zmiany wykonywane są w trybie **optimistic-lock**: - 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 +- ID identyfikuje obiekt w tabeli, może powtarzać się w różnych tabelach ## Klasa Module @@ -258,10 +245,163 @@ public static TowaryModule GetTowary(this Session session) ```csharp // Extension method (prostsze) var tm = session.GetTowary(); +var tm = context.Session.GetTowary(); +var tm = towar.Session.GetTowary(); -// GetInstance (gdy mamy ISessionable, np. Row lub Context) -var tm = TowaryModule.GetInstance(context); -var tm = TowaryModule.GetInstance(towar); // towar implementuje ISessionable +// GetInstance (gdy mamy ISessionable, ale property Session jest niedostępne) +var tm = TowaryModule.GetInstance(sessionable); +``` + +## Kod biznesowy vs UI + +Kod biznesowy realizuje operacje logiki biznesowej (jak backend). +Kod UI (fronend) jest odpowiedzialny za prezentację danych i interakcję z użytkownikiem. +Kod biznesowy może być umieszczony w tej samej klasie z kodem UI. +Kod UI to np: +- obiekty `View`, `ViewInfo`, extender +- metody sterujące `IsReadOnlyXxx`, `IsVisibleXxxx`, `GetListXxx`, `IsEnabledXxx`, `GetNameXxx`, `GetAppearanceXxx` + +### Ważne zasady do stosowania w kodzie biznesowym + +- Nie używaj żadnych obiektów kodu UI, w szczególności `View` - zamiast tego możesz użyć `SubTable[condition]` +- Nie należy stosować warunków na prawa dostępu (np `if (Table.AccessRight == AccessRights.Denied) {...}`) + +## Serwisy + +Pozwalają tworzyć obiekty (komponenty), których czas życia będzie zależał od scope: +- App (BusApplication.Instance) +- Database +- Login +- Session (default - nie trzeba określać w deklaracji) + +Umieszczając deklarację interface serwisu w assembly wspólnym, pozwalają na udostępnianie serwisów między modułami, +nawet gdy nie ma odpowiedniej referencji. + +* **Tylko serwisy scope Session są single-threded, pozostałe są multi-threaded.** +* Serwis może być `IDisposable`. +* Dla serwisów App, Database, Login nie przechowuj obiektów sesyjnych. +* `[RequireOwnService]` tylko dla serwisów, które nie mogą być nadpisywane. + +### Przykład deklaracji + +```csharp +[assembly: Service(ServiceScope.Login)] + +namespace MyNamespace; + +[RequireServiceScope(ServiceScope.Login)] +public interface IRegistry { + void Method(); +} + +internal sealed class Registry : IRegistry { + public void Method() {} +} +``` + +### Odczytanie serwisu w kodzie + +```csharp +IRegistry registerRequired = login.GetRequiredService(); +IRegistry? registerOptional = login.GetService(); + +foreach (IRegistry registers in login.GetServices()) +{ + +} +``` + +### Użycie serwisu w worker lub extender - obiekt tworzony przez Context.CreareObject() + +```csharp +// Rozwiązanie lepsze +class MyWorker1(IRegistry registry) { +} + +class MyWorker2 { + [Context] + private IRegistry Registry { get; set; } +} +``` + +## Metadane modułów, tabel, kluczy, pól, itp + +Dostęp do metadanych obiektów biznesowych dostępny przez metody `static` klasy `ApplicationInfo`. +Odczytanie informacji o tabli `TableInfo info = ApplicationInfo.GetTableInfo(nazwaTabeli)`. Istnieje tylko jedna +referencja obiektu TableInfo dla tabeli. Można używać `ReferenceEquals`, `Dictionary`, itp. +Odczytanie wszystkich tabel `ApplicationInfo.GetTablesInfo()`, a np tabel dla modułu `ApplicationInfo.GetModuleInfo +(moduleName).TableInfos`. + +### Wykorzystuj `TableInfo` do weryfikacji tabeli + +```csharp +Row row1 = ...; +Row row2 = ...; +if (row1.Table.TableInfo==row2.Table.TableInfo) { + // Ta sama tabela, nawet gdy różne sesje +} +``` + +## Tłumaczenie i formatowanie napisów, tekstów i string + +Biblioteka obsługuje słowniki tłumaczące napisy w aplikacji Soneta. +* Tłumaczone napisy muszą używać metody typu string-extender `"napis dotłumaczenia".Translate()`. +* Tłumaczenie tekstów formatowanych przez `"napis {0} z wartością {1}".TranslateFormat(arg0, arg1)`. +* Gdy string ma być zignorowany przez tłumacza, MUSISZ zaznaczyć do metodą `"nie tłumaczymy".TranslateIgnore()`,inaczej błąd kompilacji. +* Jeżeli w metodzie lub klasie jest więcej napisów do zignorowania użyj atrybutu `[TranslateIgnore]`. +* Parametr metody jest ignorowany przez tłumacza, użyj atrybutu `[TranslateIgnore]` na parametrze. + +## Log zmian i obserwowalność + +Używaj standardowy narzędzi do logowania `ILogger`. Użyj `[TranslateIgnore]` w metodzie wywołującej log. +Używaj `logger.IsEnable(LogLevel)` kiedy parametry wymagają dodatkowych operacji. + +### Użycie `ILogger` oraz exception log + +```csharp +class Test +{ + private readonly logger = BusApplication.Instance.GetRequiredService>(); + + public decimal Kwota; + + [TranslateIgnore] + public void Metoda() + { + try { + logger.LogInformation("Wywołanie metody {nazwa}", nameof(Validate)); + if (kwota<0) + logger.LogWarning("Kwota {kwota} nie może być ujemna w metodzie '{metoda}'", Kwota, nameof(Validate)); + } + catch (Exception ex) { + + // Sposób na wrzucenie exception do trace + ex.Log(); + + throw; + } + } +} +``` + +### Śledzenie czasu wykonania z obsługą exception + +```csharp +class Test { + private static readonly ActSource actSource = new(nameof(Test), ActSource.TraceLevel.Default); + + public void Action() { + using var activity = actSource.Start(); + + try { + // Algorytm do śledzenia + } + catch (Exception ex) { + activity.AddExceptionWithError(ex); + throw; + } + } +} ``` ## Szczegółowa dokumentacja @@ -276,7 +416,7 @@ var tm = TowaryModule.GetInstance(towar); // towar implementuje ISessionable ### Odczyt danych ```csharp -using (var session = login.CreateSession(true, false, "Odczyt")) +using (var session = login.CreateSession(readOnly: true, config: false, name: "Odczyt")) { var tm = session.GetTowary(); // Extension method foreach (Towar t in tm.Towary.WgKodu) @@ -289,7 +429,7 @@ using (var session = login.CreateSession(true, false, "Odczyt")) ### Tworzenie nowego obiektu ```csharp -using (var session = login.CreateSession(false, false, "Dodawanie")) +using (var session = login.CreateSession(readOnly: false, config: false, name: "Dodawanie")) { var tm = session.GetTowary(); @@ -309,7 +449,7 @@ using (var session = login.CreateSession(false, false, "Dodawanie")) ### Modyfikacja istniejącego obiektu ```csharp -using (var session = login.CreateSession(false, false, "Edycja")) +using (var session = login.CreateSession(readOnly: false, config: false, name: "Edycja")) { var tm = session.GetTowary(); var towar = tm.Towary.WgKodu["STARY001"]; diff --git a/soneta-programming-basics/references/context.md b/soneta-programming/references/context.md similarity index 98% rename from soneta-programming-basics/references/context.md rename to soneta-programming/references/context.md index 235a8ac..1306cf4 100644 --- a/soneta-programming-basics/references/context.md +++ b/soneta-programming/references/context.md @@ -22,9 +22,7 @@ Przykładowa zawartość przy otwartej liście kontrahentów: | `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 @@ -41,7 +39,7 @@ public void Action(Context context) } ``` -### Przez indeksator (rzuca wyjątek gdy brak) +### Przez indeksator ```csharp public void Action(Context cx) @@ -76,7 +74,7 @@ public void Action(Context cx) ```csharp public void Action(Context cx) { - // Przez indeksator + // Przez indeksator z określeniem typu Kontrahent knt = ...; cx[typeof(Kontrahent)] = knt; diff --git a/soneta-programming-basics/references/datapack-guidedrow.md b/soneta-programming/references/datapack-guidedrow.md similarity index 100% rename from soneta-programming-basics/references/datapack-guidedrow.md rename to soneta-programming/references/datapack-guidedrow.md diff --git a/soneta-programming-basics/references/examples.md b/soneta-programming/references/examples.md similarity index 100% rename from soneta-programming-basics/references/examples.md rename to soneta-programming/references/examples.md diff --git a/soneta-programming-basics/references/session-login.md b/soneta-programming/references/session-login.md similarity index 90% rename from soneta-programming-basics/references/session-login.md rename to soneta-programming/references/session-login.md index f877b4b..bbe864a 100644 --- a/soneta-programming-basics/references/session-login.md +++ b/soneta-programming/references/session-login.md @@ -5,14 +5,14 @@ Dokumentacja klas zarządzających połączeniem z bazą danych i sesjami w plat ## Hierarchia obiektów ``` -BusApplication (Singleton) +BusApplication.Instance (Singleton) └── Database[] (kolekcja baz danych) └── Login (uwierzytelniony użytkownik) └── Session[] (sesje robocze) └── Module → Table → Row ``` -## BusApplication +## Klasa BusApplication Singleton reprezentujący instancję aplikacji ERP. Tworzony podczas inicjalizacji systemu. @@ -40,7 +40,7 @@ foreach (Database db in BusApplication.Instance) | `Is365` | `bool` | `true` = wersja HTML, `false` = wersja okienkowa | | `this[string]` | `Database` | Indeksator - baza po nazwie | -## Database +## Klasa Database Abstrakcyjna klasa reprezentująca bazę danych. Konkretne implementacje dla wspieranych silników: @@ -84,9 +84,9 @@ Login login = db.Login(new LoginParameters }); ``` -## Login +## Klasa Login -Obiekt reprezentujący zalogowanego użytkownika. Zarządza sesjami. +Obiekt reprezentujący zalogowanego użytkownika. Zarządza sesjami. IDisposable. ### Tworzenie @@ -109,7 +109,7 @@ Login login = db.Login(new LoginParameters // var ent = login.Entitle; // unikać! // ZALECANE: Użyj w konkretnej sesji -using (var session = login.CreateSession(true, false, "Odczyt")) +using (var session = login.CreateSession(readOnly: true, config: false, name: "Odczyt")) { var op = session.AuthorizationInfo.Operator; Console.WriteLine($"Zalogowany: {op.Name} - {op.FullName}"); @@ -153,20 +153,20 @@ var opisDlaSzt = login.ExecuteConfig(configSession => ### Sygnatury CreateSession ```csharp -public Session CreateSession(bool readOnly, bool config, string name) +public Session CreateSession(bool readOnly, bool config, string name) // rekomendowana public Session CreateSession(bool readOnly, bool config) public Session CreateSession() // readOnly=false, config=false ``` -## Session +## Klasa Session -Fundamentalna klasa do zarządzania danymi. **Każda operacja na danych wymaga sesji.** +Fundamentalna klasa do zarządzania danymi. **Każda operacja na danych wymaga sesji.** IDisposable. ### Tworzenie ```csharp // ZAWSZE używaj using lub wywołuj Dispose() -using (var session = login.CreateSession(false, false, "MojaSesja")) +using (var session = login.CreateSession(readOnly: false, config: false, name: "MojaSesja")) { // operacje na danych session.Save(); @@ -218,8 +218,8 @@ session.Save(); ```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")) +using (var session1 = login.CreateSession(readOnly: true, config: false, name: "Lista1")) +using (var session2 = login.CreateSession(readOnly: true, config: false, name: "Lista2")) { // Obie sesje mogą odczytywać te same dane var tm1 = session1.GetTowary(); @@ -232,7 +232,7 @@ using (var session2 = login.CreateSession(true, false, "Lista2")) **WAŻNE:** Każda zmiana obiektu biznesowego MUSI być w transakcji! ```csharp -using (var session = login.CreateSession(false, false, "Edycja")) +using (var session = login.CreateSession(readOnly: false, config: false, name: "Edycja")) { var tm = session.GetTowary(); var towar = tm.Towary.WgKodu["KOD001"]; @@ -254,7 +254,7 @@ using (var session = login.CreateSession(false, false, "Edycja")) ### Logout(editMode: false) - transakcja tylko do odczytu ```csharp -using (var session = login.CreateSession(false, false, "Przeglad")) +using (var session = login.CreateSession(readOnly: false, config: false, name: "Przeglad")) { var tm = session.GetTowary(); var towar = tm.Towary.WgKodu["KOD001"]; @@ -305,7 +305,7 @@ Login login = db.Login(new LoginParameters }); // 4. Utworzenie sesji (zawsze z nazwą!) -using (var session = login.CreateSession(false, false, "Import")) +using (var session = login.CreateSession(readOnly: false, config: false, name: "Import")) { // 5. Pobranie modułu (extension method) var tm = session.GetTowary(); @@ -342,7 +342,7 @@ using (var session = login.CreateSession(false, false, "Import")) Login sharedLogin = db.Login(new LoginParameters { UserName = "admin", UserPassword = "haslo" }); Parallel.ForEach(items, item => { - using (var session = sharedLogin.CreateSession(false, false, "Watek")) + using (var session = sharedLogin.CreateSession(readOnly: false, config: false, name: "Watek")) { var tm = session.GetTowary(); using (var transaction = session.Logout(editMode: true)) @@ -354,13 +354,3 @@ Parallel.ForEach(items, item => { } }); ``` - -## 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