feat: content import system - Markdown parser, importer, 7 decks + 3 tutorials + 5 cheatsheets

Dieser Commit ist enthalten in:
hafroese 2026-04-02 23:09:27 +02:00
Ursprung 1c59b667f2
Commit 6a504254b0
17 geänderte Dateien mit 2658 neuen und 0 gelöschten Zeilen

Datei anzeigen

@ -0,0 +1,81 @@
# Omnis Commands Cheat Sheet
## Die 10 wichtigsten Befehle
| # | Befehl | Was es tut | JS-Aequivalent |
|---|--------|-----------|----------------|
| 1 | `Calculate lX as expr` | Berechnung + Zuweisung | `let x = expr` |
| 2 | `Do obj.$method()` | Methodenaufruf | `obj.method()` |
| 3 | `If ... Else ... End If` | Bedingung | `if ... else ...` |
| 4 | `For i from a to b step c` | Zaehlschleife | `for (let i=a; i<=b; i+=c)` |
| 5 | `For each line in list` | Listen-Iteration | `for (const item of arr)` |
| 6 | `While ... End While` | Bedingungsschleife | `while (...)` |
| 7 | `Quit method lVal` | Methode beenden + Return | `return val` |
| 8 | `OK message {text}` | Nachricht anzeigen | `alert(text)` |
| 9 | `Switch ... Case ... End Switch` | Fallunterscheidung | `switch ... case` |
| 10 | `Do inherited` | Super-Methode rufen | `super.method()` |
## Variablen & Berechnung
```omnis
Calculate lName as "Harry" String zuweisen
Calculate lSum as lA + lB Berechnen
Calculate lText as con("Hallo ", lName) String verketten
Calculate lUpper as upp(lName) Grossbuchstaben
Calculate lLen as len(lName) String-Laenge
Calculate lSub as mid(lName, 2, 3) Substring
Calculate lPos as pos("r", lName) Zeichen finden
```
## Kontrollfluss
```omnis
If lAge >= 18 If lStatus = 'A' | lStatus = 'B'
# erwachsen # A oder B
Else If lAge >= 14 End If
# jugendlich
Else Switch lStatus
# kind Case 'A'
End If # aktiv
Case 'I'
While lX < 100 # inaktiv
Calculate lX as lX + 1 Default
End While # sonstiges
End Switch
For lI from 1 to 10 step 1
# lI = 1, 2, 3, ...10
End For
```
## Dialoge
```omnis
OK message {Fertig!} Info-Dialog
Yes/No message {Loeschen?} Ja/Nein Dialog
If flag true ... End If Ergebnis pruefen
Prompt for input {Name?} lName Eingabe-Dialog
No/Yes message {Abbrechen?} Nein/Ja (Default=Nein)
```
## Debugging
```omnis
Breakpoint Debugger oeffnen (= debugger; in JS)
OK message {Debug: [lVar]} Quick-Debug mit Message
Trace log {[lVar]} In Trace-Log schreiben
```
## SQL-Befehle (ueber Session/Statement)
```omnis
Do lSess.$logon(host, user, pw, 'sess') Returns #F Verbinden
Do lStmt.$prepare('SELECT...WHERE id=:1') Returns #F Vorbereiten
Do lStmt.$execute(lID) Returns #F Ausfuehren
Do lStmt.$fetch(lList, kFetchAll) Returns #F Ergebnis holen
Do lStmt.$execdirect('INSERT...') Returns #F Direkt ausfuehren
```
## Merkhilfe: Die Befehls-Familien
```
DATEN: Calculate, Do, Set current list
FLUSS: If/Else/End If, For/End For, While/End While, Switch/Case/End Switch
METHODE: Quit method, Do inherited, Quit all methods
DIALOG: OK message, Yes/No message, Prompt for input
FENSTER: Open window, Close window, Redraw, Enter data
SQL: $logon, $prepare, $execute, $fetch, $execdirect
```

Datei anzeigen

@ -0,0 +1,88 @@
# Omnis $-Notation Cheat Sheet
## Navigation durch die Hierarchie
```
$root Die Omnis-Wurzel
.$libs Alle geoeffneten Libraries
.myLib Bestimmte Library
.$classes Alle Klassen
.myClass Bestimmte Klasse
.$methods Alle Methoden
.$objs Alle UI-Objekte
.$ivars Alle Instanz-Variablen
```
## Kontext-Shortcuts
| Pfad | Bedeutung | JS-Aequivalent |
|------|-----------|---------------|
| `$cinst` | Aktuelle Instanz | `this` |
| `$cclass` | Aktuelle Klasse | `this.constructor` |
| `$clib` | Aktuelle Library | - |
| `$ctask` | Aktueller Task | Global scope |
| `$cmethod` | Aktuelle Methode | - |
| `$cwind` | Aktuelles Window | `window` |
## UI-Objekte
```omnis
$cinst.$objs.feldName.$contents Wert lesen
$cinst.$objs.feldName.$contents.$assign(x) Wert setzen
$cinst.$objs.feldName.$visible Sichtbar?
$cinst.$objs.feldName.$enabled Aktiv?
$cinst.$objs.feldName.$textcolor Textfarbe
$cinst.$objs.feldName.$backcolor Hintergrundfarbe
$cinst.$objs.feldName.$font Schriftart
$cinst.$objs.feldName.$tooltip Tooltip-Text
$cinst.$objs.feldName.$dataname Gebundene Variable
```
## Listen-Notation
```omnis
lList.$linecount Anzahl Zeilen
lList.$line Aktuelle Zeile (1-basiert)
lList.$colcount Anzahl Spalten
lList.$cols Spalten-Collection
lList.$cols.$add(...) Spalte hinzufuegen
lList.$add() Zeile hinzufuegen
lList.$remove(n) Zeile n entfernen
lList.$clear() Alle Zeilen loeschen
lList.$search(expr) Suchen
lList.$sort(col, asc) Sortieren
lList.$sendall(expr) Auf alle Zeilen anwenden
lList.$merge(other) Listen zusammenfuegen
lList.$selected Auswahl-Flag der akt. Zeile
lList.[3].colname Spalte in Zeile 3
lList.colname Spalte in aktueller Zeile
```
## Methoden aufrufen
```omnis
Do iObj.$method() Ohne Rueckgabe
Do iObj.$method() Returns lResult Mit Rueckgabe
Do iObj.$method(p1, p2) Returns lR Mit Parametern
Do $cinst.$objs.btn.$visible.$assign(kTrue) Property setzen
Do inherited Super-Methode
```
## Wichtige Konstanten
```
kTrue / kFalse Boolean
kCharacter String-Typ
kInteger Ganzzahl-Typ
kNumber Dezimal-Typ
kDate Datum-Typ
kList Listen-Typ
kRow Row-Typ
kBoolean Boolean-Typ
kFetchAll Alle Zeilen holen
kFetchOne Eine Zeile holen
kSimplechar Einfacher String-Subtyp
k2dp 2 Dezimalstellen
```
## Merkhilfe: LESEN vs SETZEN
```
LESEN: Calculate lVal as $cinst.$objs.feld.$contents
SETZEN: Do $cinst.$objs.feld.$contents.$assign(lVal)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Nie = verwenden! Immer $assign() !
```

Datei anzeigen

@ -0,0 +1,112 @@
# Solution2 ERP Cheat Sheet
## Klassen-Praefixe - Was ist was?
```
w = Window (UI-Formular) wOrders, wLogin, wCustomerInvoicesWithList
o = Object (Business-Logik) oOrders, oLogin, oCreateInvoice
T_ = Table (Daten-Cursor) T_Orders, T_Parts, T_Super
sc = Schema (Datenstruktur) scOrderItems, scStaffWorkTimeLog
Q = Query QMOResourcesProcessingQuantity
r = Report (Druckbericht) rInvoice, rDeliveryNote, rCompanyList
js = JS Remote Form (Web) jsMainForm, jsSubForm, jsMainMenu
b = Base-Objekt (Submodul) bobjs
```
## Superklassen-Hierarchie
```
wMainWindow -----> Haupt-Dateneingabe-Fenster
wBaseWindow -----> Modale/Hilfs-Fenster
wSubWindow -----> Eingebettete Sub-Panels
oSuperData -----> Basis fuer Business-Logik-Objekte
T_Super -----> Basis fuer alle Table-Klassen
T_SuperVersion --> Versionierte Table-Klasse
```
## Die 22 Libraries
| Library | Bereich |
|---------|---------|
| `solution2` | Kern: Login, Navigation, Enterprise, Mitarbeiter, Kalender |
| `solution2Services` | Hintergrund-Services, Push, Callbacks |
| `BasicTools` | HTML, Import, Edit-Utilities |
| `DBAccess` | Datenbank-Zugriff, Berechtigungen |
| `Sales` | Auftraege, Lieferscheine, Rechnungen |
| `Purchase` | Einkauf, Lieferanten, E-Rechnungen |
| `Customer` | Kundenstamm, Berichte, Aktivitaeten |
| `Manufacturing` | Fertigungsauftraege, Stuecklisten, Kalkulation |
| `QualityInspection` | Qualitaetsprotokolle, Labor |
| `AdminAccounting` | Buchhaltung, Export, ZUGFeRD |
| `PPS` | Produktionsplanung (MRP) |
| `StaffWorkTime` | Arbeitszeit, Urlaub |
| `MobileWork` | Mobile/Web-Client (Remote Forms) |
| `_Analysis_SIM` | Analyse/Simulation |
## Datenbank-Pattern
```
DB: masterdemo Schema: soluser Engine: PostgreSQL
JEDE Tabelle hat:
- created (TIMESTAMP) Erstellungszeitpunkt
- modtime (TIMESTAMP) Letzte Aenderung
- revisor (INTEGER) Wer hat geaendert (Employee-ID)
- valid (BOOLEAN) Soft-Delete Flag
VIELE Tabellen haben Dual-Signature:
- firstsigned (BOOLEAN)
- needsecondsignature (BOOLEAN)
- secondrevisor (INTEGER)
- secondsigned (BOOLEAN)
```
## Die wichtigsten Tabellen
```
STAMMDATEN:
contact Kontakte/Ansprechpartner
warehouse Lager
dunninglevels Mahnstufen
VERKAUF:
orders Auftraege (103 Spalten!)
orderitems Auftragspositionen
deliverynoteitems Lieferscheinpositionen
customerinvoices Ausgangsrechnungen (90 Spalten)
customerinvoiceitems Rechnungspositionen
EINKAUF:
purchaseorder Bestellungen (72 Spalten)
supplierinvoices Eingangsrechnungen
stockreceipt Wareneingaenge
stockreceiptitems Wareneingangs-Positionen
LAGER:
stockrotationlog Lagerbewegungen
inventoryquantities Bestandsmengen
inventoryvalues Bestandswerte
FERTIGUNG:
qualityprotocolpending Qualitaetspruefungen
```
## Typischer Geschaeftsprozess-Flow
```
Auftrag (orders)
|
v
Lieferschein (deliverynoteitems)
|
v
Rechnung-Freigabe (customerinvoicerequirement)
|
v
Rechnung (customerinvoices)
|
v
Buchhaltung-Export (transfertoadminaccounting)
```
## RBAC-System
```
Berechtigungen = Form-Path-basiert
-> Berechtigungsgruppen werden Form-Pfaden zugewiesen
-> Nicht pro Screen, sondern pro Modul/Navigation
-> T_ModuleAccess2Methods steuert Methoden-Zugriff
```

Datei anzeigen

@ -0,0 +1,104 @@
# SQL in Omnis Cheat Sheet
## Verbindung aufbauen
```omnis
# Session-Objekt erstellen (im IDE: Variable lSess vom Typ Object)
Do lSess.$logon('localhost', 'postgres', 'passwort', 'meineSess') Returns #F
If flag true
# Verbunden!
End If
```
## SELECT - Daten lesen
```omnis
# SICHER mit Bind-Variablen (:1, :2)
Do lStmt.$prepare('SELECT * FROM contact WHERE companyid = :1 AND valid = :2') Returns #F
Do lStmt.$execute(lCompanyID, kTrue) Returns #F
Do lStmt.$fetch(lList, kFetchAll) Returns #F
# Alternative: @[]-Syntax (auch sicher)
Do lStmt.$execdirect('SELECT * FROM orders WHERE orderid = @[lOrderID]') Returns #F
Do lStmt.$fetch(lList, kFetchAll) Returns #F
```
## INSERT - Daten einfuegen
```omnis
Do lStmt.$execdirect(con( |
'INSERT INTO mytable (name, status, created, revisor, valid) ', |
'VALUES (@[lName], @[lStatus], now(), @[tEmployeeID], true)' |
)) Returns #F
```
## UPDATE - Daten aendern
```omnis
Do lStmt.$prepare(con( |
'UPDATE orders SET status = :1, modtime = now(), revisor = :2 ', |
'WHERE orderid = :3' |
)) Returns #F
Do lStmt.$execute(lNewStatus, tEmployeeID, lOrderID) Returns #F
```
## DELETE - Daten loeschen (VORSICHT!)
```omnis
# In Solution2: Soft-Delete bevorzugen!
Do lStmt.$execdirect(con( |
'UPDATE orders SET valid = false, modtime = now(), revisor = @[tEmployeeID] ', |
'WHERE orderid = @[lOrderID]' |
)) Returns #F
```
## Transaktionen
```omnis
Do lSess.$begin() Returns #F ;; START TRANSACTION
# ... mehrere SQL-Operationen ...
If lAllesOK
Do lSess.$commit() Returns #F ;; COMMIT
Else
Do lSess.$rollback() Returns #F ;; ROLLBACK
End If
```
## Fehlerbehandlung
```omnis
Do lStmt.$execute(lParam) Returns #F
If not(flag true)
Calculate lError as lSess.$lasterrortext
OK message {SQL-Fehler: [lError]}
End If
```
## Fetch-Modi
```
kFetchAll -> Alle Zeilen in Liste (fuer kleine/mittlere Ergebnisse)
kFetchOne -> Eine Zeile (fuer Schleifen bei grossen Ergebnissen)
kFetchBulk -> Block von N Zeilen (Kompromiss)
```
## WICHTIGE REGELN
```
IMMER: @[lVar] oder :1 (Bind-Variablen = SICHER)
NIE: [lVar] (Text-Substitution = SQL-INJECTION!)
IMMER: WHERE valid = true (Soft-Delete beachten!)
IMMER: modtime, revisor setzen bei UPDATE
IMMER: created, revisor, valid setzen bei INSERT
IMMER: #F pruefen nach jedem SQL-Aufruf
```
## Solution2-spezifische SQL-Tipps
```
Schema: soluser
Datenbank: masterdemo
Engine: PostgreSQL
Typische WHERE-Klausel:
WHERE valid = true
AND companyid = @[lCompanyID]
ORDER BY modtime DESC
Datum/Zeit:
now() -> aktueller Timestamp
current_date -> aktuelles Datum
@[#D] -> Omnis-Datum als Parameter
@[#T] -> Omnis-Timestamp als Parameter
```

Datei anzeigen

@ -0,0 +1,143 @@
# Window-Architektur Cheat Sheet
## Klassenhierarchie
```
wBaseWindow (Wurzel - keine Superklasse)
+-- wMainWindow (eigenstaendige Fenster: wOrders, wParts...)
+-- wSubWindow (eingebettete Panels: wOrder, wOrderItems...)
```
## Wichtigste Instanzvariablen
### Auf ALLEN Fenstern (von wBaseWindow):
| Variable | Zweck |
|----------|-------|
| `ioCode` | Business-Logik-Objekt |
| `iiRef2SubWindow` | Referenz auf aktives SubWindow |
| `ibControl2SubWindow` | `kTrue` = Commands gehen an SubWindow |
| `ilList` | Haupt-Datenliste |
| `irRow` | Aktuelle Datenzeile |
| `inEDMode` | Bearbeitungsmodus |
| `icCurrTabPane` | Aktiver Tab-Reiter |
### Nur auf wSubWindow:
| Variable | Zweck |
|----------|-------|
| `iiRef2Parent` | Referenz ZURUECK zum Elter |
| `icFormWindow` | Name fuer Rechte-Check |
| `icSubWindow` | SubWindow-Feldname |
## DAS zentrale Pattern: Command-Delegation
```omnis
## Auf jedem Fenster identisch:
If $cinst.ibControl2SubWindow
Do iiRef2SubWindow.$cXxx() ## -> Weiter ans SubWindow
Else
Do $cinst.ioCode.$cXxx() ## -> Business-Logik
End If
```
## Lebenszyklus
### $construct (SubWindow meldet sich an):
```omnis
Do inherited
Set reference iiRef2SubWindow to $cinst.$objs.wSubWindow.$ref
Set reference iiRef2Parent to pRef2Parent
Do iiRef2Parent.$setControl2SubWindow(kTrue) ## KONTROLLE UEBERNEHMEN
```
### $destruct (SubWindow meldet sich ab):
```omnis
If iiRef2Parent
Do iiRef2Parent.$setControl2SubWindow(kFalse) ## KONTROLLE ZURUECKGEBEN
End If
Do ilList.$define()
Do irRow.$define()
```
### $closeWindow (delegiert nach oben):
```omnis
Do iiRef2Parent.$closeWindow() ## Parent schliesst das Fenster
```
### $EnableTabPane (sperrt Tabs nach oben):
```omnis
Do iiRef2Parent.$EnableTabPane($cinst.inEDMode) ## Parent sperrt seine Tabs
```
## Command-Fluss Beispiel (Sales/wOrders)
```
User klickt [Edit]
-> wOrders.$cEdit (wMainWindow)
-> $closeRelatedWindow()
-> ibControl2SubWindow = kTrue
-> wOrder.$cEdit (wSubWindow Ebene 1)
-> ibControl2SubWindow = kTrue
-> wOrderItems.$cEdit (wSubWindow Ebene 2)
-> ibControl2SubWindow = kFalse
-> ioCode.$cEdit() == oOrderItems.$cEdit()
-> HIER passiert die Aktion!
```
## Alle delegierten Commands
### wMainWindow (mit $closeRelatedWindow):
`$cEdit`, `$cCancel`, `$cAudit`, `$cNextVersion`
### wSubWindow (ohne $closeRelatedWindow):
`$cEdit`, `$cCancel`, `$cInsert`, `$cDelete`, `$cSave`, `$cPrint`, `$cAudit`, `$cNextVersion`, `$cFirst`, `$cLast`
## Referenz-Kette
```
iiRef2SubWindow iiRef2SubWindow
MainWindow ----------> SubWindow ----------> SubSubWindow
<---------- <----------
iiRef2Parent iiRef2Parent
```
## Cross-Library Vererbung
```
# Innerhalb solution2-Library:
wMeinFenster extends wSubWindow
# Aus anderer Library (Sales, Manufacturing...):
wMeinFenster extends solution2.wSubWindow ## Library-Prefix noetig!
```
## TabPane-Konvention
```
TabPane-Objekt heisst IMMER: TP
Zugriff: $cwind.$objs.TP.$enableTabPanes(pEDMode)
```
## 7 Goldene Regeln
```
1. ibControl2SubWindow bestimmt ALLES
2. $construct: inherited aufrufen = Kette aufbauen
3. $destruct: Kontrolle zurueckgeben
4. Commands fliessen ABWAERTS (Main -> Sub -> SubSub)
5. TabPane-Sperren fliessen AUFWAERTS (Sub -> Parent)
6. $closeWindow delegiert AUFWAERTS
7. ioCode ist der letzte Stopp (kein SubWindow aktiv)
```
## Debugging Quick-Check
```omnis
# 1. Wer hat die Kontrolle?
Calculate lDebug as $cinst.ibControl2SubWindow
# 2. Ist SubWindow-Referenz gueltig?
If iiRef2SubWindow
# Referenz existiert
End If
# 3. Welches SubWindow ist aktiv?
Calculate lClass as iiRef2SubWindow.$classname
# 4. Hat $construct inherited aufgerufen?
# -> Breakpoint in wSubWindow.$construct setzen
# 5. Ist Superklasse korrekt?
# -> Class Inspector -> Superclass pruefen
```