KeyBalance Opdateringer

Genereret: 2026-10-20 18:47:30

Beskrivelse
#1988 - Nettobehov key, weekly reorder tasks and open-post fixes (20-10-26 18:46)

Summary


Net requirement (Nettobehov)
  • **SOrdreLinje / IOrdreLinje**: new field `LNettoSortKode` (Init: `ØnsketLevDato` YYYYMMDD + `SalgKøbProd` + zero-padded `OrdreNr` + `Løbenr`; empty for SalgKøbProd 4/5) and new key `Nettobehov` = VNummer, LNettoSortKode, SalgKøbProd, Løbenr, with KeepTotal on `IOrdreAntal` and `LeveresAntal`. Both are restructures.
  • **SOrdreLinje.LøbendeDispAntal**: now sums over the `Nettobehov` key up to the line's own sort code, and subtracts the delivered quantity (`LeveresAntal`) for both inflow (1;3;30..49) and outflow (0;2;10..29). Before, it summed `IOrdreAntal` over key `Vare` by date only, so lines on the same date were not ordered and delivered quantities were counted as still open.
  • **NETTOBEHOV_VAREKORT** (new): net requirement list per item, opened from **VAREKORT** with the new button/action `actNettobehov` (F8).

Reordering by week
  • **Vare**: new field `MaxOrdrestr` (max order size for new purchase/production orders).
  • **VGenbestilLin**: new AutoIncrement field `Løbenr`, added as a segment to all three keys, so one run can hold several lines for the same item (one per week). Restructure.
  • **VGENBESTILDAN_UGEVIS** (new): reorder proposal that walks the `Nettobehov` key and breaks on `weekno(ØnsketLevDato)`, creating a proposal line per week where availability falls below minimum (topped up to max when set). Items without demand fall back to the min/max check. BOM items and service items are skipped.
  • **MPS_GENBESTIL_KUN_UGE** / **_SUB** (new): the same per-week logic for BOM items, creating production orders (with `MaxOrdrestr` splitting into several orders) and reserving BOM via `MPS_RESERVERSTYKLISTE`, optional print via `MPS_UPRODORDRE_ANTAL`.
  • **MPS_POrdre_AktivOP** (new): helper that returns the active (first not completed) route step of a production order.

Open-post fixes
  • **Debitorpost / Kreditorpost**: the `ÅbenPostCreate` trigger now only fires when the bilag is not already in `DÅbenPost` / `KÅbenPost` (both files are unique on Bilag only).
  • **DÅbenPost / KÅbenPost**: converted from cp1252 to UTF-8 (fixes the garbled `Løbenr` names in the diff) and a TODO noting that the files are candidates for removal in favour of a lookup on the post file's Bilag key.

Bug fix
  • **KKLADDEKOPIER**: when the copied line had no date, the posting date was written to the *source* line (`KassekladdeLinje.Dato`) instead of the new line (`KKLADDELIN.Dato`).

Note for review
  • Rebased onto current master: `IOrdreLinje.WebStatus` and the new `Vare.Web*` fields from PR 1986 were already on master, so they are kept as-is and only the new fields are added next to them.
  • The new batch tasks are not added to any menu in this PR.

Files

  • FILE: Debitorpost, Kreditorpost, DÅbenPost, KÅbenPost, IOrdreLinje, SOrdreLinje, VGenbestilLin, Vare
  • TASK (changed): KKLADDEKOPIER, VAREKORT
  • TASK (new): NETTOBEHOV_VAREKORT, VGENBESTILDAN_UGEVIS, MPS_GENBESTIL_KUN_UGE, MPS_GENBESTIL_KUN_UGE_SUB, MPS_POrdre_AktivOP

Test plan

  • [ ] Restructure SOrdreLinje, IOrdreLinje, VGenbestilLin and Vare; check that LNettoSortKode is filled on existing lines
  • [ ] VAREKORT: F8 opens Nettobehovsliste for the item with lines in sort-code order and correct running disposable quantity
  • [ ] VGENBESTILDAN_UGEVIS creates one proposal line per week with shortage
  • [ ] MPS_GENBESTIL_KUN_UGE creates production orders per week and splits by MaxOrdrestr
  • [ ] Debitor/Kreditor posting on a bilag already in DÅbenPost/KÅbenPost no longer triggers ÅbenPostCreate
  • [ ] KKLADDEKOPIER: copying a line without a date sets the date on the new line

🤖 Generated with [Claude Code](https://claude.com/claude-code)
#1986 - KB web opsaet okt 26 (20-10-26 17:01)
#1967 - Thai AI-varefortolkning + BTM AIQA-modul i standarden (20-10-26 13:12)
**Varefortolkning (Thaibutikken live -> standard)**
  • Opdateret: Vare_Ft_Upload_KBFT, Vare_Ft_Upload_KBFT_Wrap (Dansk/Tæller/StopNow, kalder VareDK), Vare_GemVarerapport (Prioritet 20)
  • Nye: VareDK_Ft_Upload_KBFT (Claude-endpoint, kun dansk), VareDKIngr_Ft_Upload_KBFT
  • Gjort generisk: BillingId = System.LicensName + datapath() (Thai havde hardkodet), dagligvare = VGruppe.Kategori "MAD" eller "DAGLIGVARE..." (standardens felt er 10 tegn), ImageEval -> Vare.UPCNummer kun når FirmaCustom AI_ImageEvalUPC <> 0, $AIIN nulstilles
  • Alle brugte felter i Vare/VareIngredienser/VareSprog/VWeb findes allerede i standarden - ingen FILE-ændringer

**AIQA (BTM -> standard)**
  • Opdateret: QA_Chat_KBFT, AIQA_GemRapport, QAAI_Ft_Upload_KBFT_Wrap (kalder nu QA_Chat_KBFT_JSON), QAAI_NOTAT, PRGSETUP_QAAI (Scope = UseMCP bevaret), SORDRE_AIWRAP
  • Nye: QA_Chat_KBFT_JSON, QA_Chat_KBFT_JSON_ORDRE, QA_Chat_Claude_Direct, QAAI_Ft_Upload_KBFTJSON_Wrap, QAAI_SetCustom, QAAI_OpsaetAI, QAAI_PROMPT, QAAI_PromptListe, SORDRE_AIWRAP1, FILE ChatQA_PromptTekst
  • ChatQA_Log: farve virker med både GROEN/GUL/ROED og 10/14/16
  • Ikke med: SORDRE_AI_Shceduler_Wrap (BTM-hardkodet type 11 + dato), KreditVurdering_AIWRAP (eksperimentel)

Ingen API-nøgler i koden (Claude_APIKey m.fl. i FirmaCustom via QAAI_OpsaetAI). Trin pr. task max 25.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
#1951 - KB Webshop: opstart med få klik + rettelser fra Thaibutikken (okt-26) (20-10-26 12:59)
KB Webshop: opstart med få klik + rettelser fundet under opsætningen af Thaibutikken (19/10-2026).

**Opstart (WEB_KB_Opsaet)**
  • Forbindelseskode fra KBWeb (kbw1.…) - kun de felter, der skal bruges, vises; tilbudsfarve tilføjet.
  • API-adgang begge veje: TASKCALL Wizzard_API_TokenOpret (KBWEB), WEB_KB_ApiOpsaet (ny parameter Stille) og adresse + token til shoppen (kb_api_set).
  • "Kategorier fra varegrupper" (WEB_KB_KatFraGrupper) før Send alt.
  • Hemmelig nøgle op til 1000 tegn.

**Kategorier fra varegrupper (ny: WEB_KB_KatFraGrupper + VareKategorier.GrpKilde med nøgle)**
  • 3 niveauer: varekategori -> varegruppe -> undergruppe; navne fra collectionen (WEB_SF_COLLECTIONER.TekstF), ellers gruppens tekst (KUN STORE -> Stort forbogstav). Natjobbet vedligeholder. Røres ikke hos kunder med eget kategoritræ.

**Send til shoppen**
  • WEB_KB_VareSend: alle tegn KB sender som Windows-1252 (æøå, €, ' , kontroltegn) som \u-koder (PGRST102), bunker højst 12000 tegn (timeout med KB-nøgle), fejltekst gemmes i FirmaCustom KBW_<prefix>_VareFejl1..
  • WEB_KB_KategoriSend: fuld kørsel rydder kategorier, KB ikke længere har (kb_kategori_ryd).
  • WEB_KB_KategoriTekst: tekster/SEO/billede også fra collections for kategorier fra varegrupper; JSON-sikker linje.
  • WEB_KB_Tema: farver uden # får #.
  • WEB_KB_FakturaPdf: SELECT uden Show (kaldene sendte prefix ind i selectet -> "Ikke range til selectkald").
  • WEB_KB_JobKoe/SendAlt: parameterantal i TASKCALL passer.
  • VARE_KOPIER: NyVNummer kan modtages som parameter (ny vare fra shoppen).
  • Bestillingsvarer (Kreditor.AlleBestilling valgliste + WSetup.WebBestilLevTid) - samme som i PR 1947.

Alle TASKCALL i WEB_KB_*/WEB_API_*/Wizzard_API_* er tjekket mod de kaldte tasks (parametre + Show-selects). Testet i Thaibutikken-demo (4.137 varer, kategorier, tema).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
#1973 - Bedre skærmbilleder (20-10-26 08:11)
Bedre skærmbilleder
#1947 - KB Webshop i standarden + kampagne på kategori (okt-26) (18-10-26 11:52)
KB Webshop-integrationen og okt-26-rettelserne samlet i standarden, så JNF, Thaibutikken og nye kunder kan køre ren standard.

**KB Webshop (WEB_KB_*)**
  • Ordrer, varer, firmaer, kategorier, billeder, kampagner, booking, events, formularer, saldo, retur og maskiner/service.
  • Fakturabetaling og -udligning, og faktura-PDF (kun webfakturaer via WSetup.WebNySKP).
  • Sprog, jobkø, natjob, opsætning og Tema (logo og ikoner med cache-control).
  • API_Web_S1_*, API_Vare_S1_* og API_Salg_S1_WebShopSync til webshoppen, samt varegodkendelser og Web_JobLog.

**Kampagne på kategori**
  • Nyt felt Kategori nederst på RabatKampagneVarer.
  • Kampagne_BygKombi folder kategorien ud, også underkategorier. Det samme gælder DanForslagHoldbarhed, Kopier og kampagnekortet.

**FILE – kun nye fysiske felter nederst, intet flyttet eller omdøbt**
  • Vare, VGruppe, StykListe (+ nøglen IndgårVareNr), KontaktPerson, Kreditor og FakFragtGr.
  • IOrdreLinje/IORDRETEKST har nu samme fysiske felter som SOrdreLinje/SORDRETEKST (WebStatus, WebResponse).

**Menu**
  • KB API-opsætning (WEB_API_OPS) under Værktøjer → Værktøj, direkte i menuen. ActionList er uændret (158.939 tegn).

**Master er flettet ind** (f87f7946)
  • Konflikterne var tidligere versioner af grenens egne filer fra PR 1815/1829, og grenens nyere version er brugt.
  • Scope = UseApi/UseWeb, TaskType = Batch og string()-formaterne er tjekket på alle nye tasks.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
#1910 - små diff (15-10-26 22:46)
små diff
Manglede i @<80DB85FF-39E2-6CDC-B3B0-E9791EAA4F9E> commits..
#1894 - Tjek kun en gang "linjer der ikke er leveret" (15-10-26 22:40)
tjek kun en gang "linjer der ikke er leveret"
#1901 - Fix invalid string() date/time formats (15-10-26 22:39)

Summary

Audit of every `string(value;"format")` call in PTDSAMLET against how KRuntime formats dates (`FixDateFormat` -> .NET `DateTime`) and times (`FixTimeFormat` -> .NET `TimeSpan`, which is strict). Each fix was verified against .NET output.

  • **FormatException:** `gettime()` is a `TimeSpan`; `"TTMMSS"` and `"HHMMSSS"` threw. Now `"HHMMSS"` (Dokumenter_SendÅben, Lev_Import_StepHandler, plus the commented-out lines in DokumentBiblTilføj and Rep_okmsg).
  • **Wrong text:** `"M"`/`"D"` gave `5. oktober` / `mandag den 5. oktober 2026` in the TradeShift paths. Now `"%M"`/`"%d"`. NETS advis `"DD. SSS YYYY"` printed `05. SSS 2026`. Now `"DD. MMM YYYY"` (`05. okt. 2026`).
  • **Explicit separator:** `"DD:MM:YYYY"` already rendered `05.10.2026` (the ICU da-DK time separator), so it is now written as `"DD.MM.YYYY"`. Output is unchanged.
  • **Log noise:** `"X"`/`"x"` number formats logged `Format string error` (level 1) on every call. They were dropped on integers (same output) and replaced by the equivalent `"#,0.00"` on Beløb doubles (same `1.234,56` output).
  • The cp1252 files touched were converted to UTF-8 (no BOM). Line endings are unchanged, so æøå lines also show up in the diff.

Files

  • TASK: Dokumenter_SendÅben, DokumentBiblTilføj, Lev_Import_StepHandler, Rep_okmsg, NETS_LS_BetKørHeadSendAdvis, SORDRE_OVERF_SORDRETEKST_WE, DRykker, KBExp_DanHTML, KBExp_Godkend_Godk, KBExp_TilGodk, BS_V_UdskFaktura
  • FILE: Sag_KLSt_SkemaLinje, SOrdre_KLSt_SkemaLinje
  • EXTRA_PTD/TASK_OLD: EdiServer_ImportTradeShiftStatus

Test plan

  • [ ] Dokumenter_SendÅben: the file name gets a valid HHMMSS stamp and no error
  • [ ] Lev_Import_StepHandler: the Done file is moved with a HHMMSS stamp
  • [ ] DRykker / KBExp HTML: amounts still show as 1.234,56
  • [ ] NETS advis mail: the due date shows as e.g. 05. okt. 2026
  • [ ] KLSt schema lines: integer and decimal answers display as before
  • [ ] No new `Format string error` lines in the log

🤖 Generated with [Claude Code](https://claude.com/claude-code)
#1862 - LevAdresse.Email 150 chars; API_BI_FinBudPost Kontonr select as string (13-10-26 13:37)

Summary

  • **FILE LevAdresse**: `Email` length 35 -> 150 so full e-mail addresses fit (restructure of LevAdresse on next rebuild).
  • **TASK API_BI_FinBudPost**: `Kontonr` is a `BString`, so the open-ended `FromTo` range now starts at the string `"0"` instead of the numeric literal `0`.

Files

  • `FILE/LevAdresse.PTD`
  • `TASK/API_BI_FinBudPost.PTD`

Test plan

  • [ ] PTD compiles
  • [ ] LevAdresse restructures; an e-mail longer than 35 chars can be saved and read back
  • [ ] API_BI_FinBudPost returns budget posts for all accounts

🤖 Generated with [Claude Code](https://claude.com/claude-code)
#1851 - SUBTASKCALL targets: add TaskType = Batch (13-10-26 09:57)

Summary

Eleven subtasks called with SUBTASKCALL had no `TaskType` and so defaulted to Dialog, although a SUBTASKCALL always runs its target as a batch. As a Dialog, the in-process data load registered DataSync with no DataGuid (EMPTY-DATAGUID-SUB in Sentry, e.g. `UPDATEMATFORBRUG`).

The runtime now promotes such targets itself (Keybalance2018 PR, `WFTask.PromoteCalledSubTasks`); this makes the PTD say what it is. One inserted line per subtask, encoding and line endings untouched.

Files

  • `TASK/MPS_BEKRÆFTPLUK_SO.PTD` - UPDATEMATFORBRUG
  • `TASK/Oprydning_Vare.PTD` - SOrdre, IOrdre, STilbud
  • `TASK/SletVareErstattes.PTD` - RetFinals, SletErstatning
  • `TASK/MPS_EFFEKTIVITET.PTD` - MånedAfdeling, MånedAfdelingMedarbejder
  • `TASK/SORDRE_SendDokumentation.PTD` - BDokumenter
  • `TASK/API_OP_S1_PostFile.ptd` - LoopEmails
  • `TASK/FlexPosAPI_Barcode.PTD` - CheckOpretBC

Test plan

  • [x] PTD compile on everything without errors
  • [ ] Run `MPS_BEKRÆFTPLUK_SO`, `Oprydning_Vare`, `SletVareErstattes`: behave as before

🤖 Generated with [Claude Code](https://claude.com/claude-code)
#1812 - Fix/stralfors miljøvalg (13-10-26 06:41)
#1828 - Længere tekstfelter (okt-26) (13-10-26 06:40)
Tre tekstfelter var for korte til rigtige kundedata. Ved genopbygningen af JNF sandbox blev data afkortet:

| Felt | Før | Nu | Afkortet i JNF |
|---|---|---|---|
| VareKategorier.Navn | 50 | 80 | 154 kategorinavne |
| VareSpec_VareActiveSpecs.SpecsVString | 20 | 50 | 722 specifikationer |
| VareHtmlTekst.Beskrivelse | 4000 | 8000 | 31 HTML-tekster |

Ændringen er kun en udvidelse. Ingen felter flyttes eller fjernes, og eksisterende data bevares, når filerne genopbygges.

Test

Genopbyg de tre filer, og tjek at lange kategorinavne, specifikationer og webtekster gemmes fuldt ud.


🤖 Generated with [Claude Code](https://claude.com/claude-code)

#1846 - Scope = UseApi på API-tasks (13-10-26 06:38)
Alle `API_*`-tasks der manglede `UseApi` har fået `Scope = UseApi` (29 tasks, én linje pr. fil). Ingen af dem havde Scope i forvejen.

Ikke med:
  • `WEB_API_*` (opsætning af Objects, Token, TokenGrp m.fl.), `Wizzard_API_*` og udgående integrationer (AGCO, FlexPos, ECOAPI, DFAPI).
  • `API_IC_Varer` - den compiler ikke på master i forvejen (`Firma2.SE_nr was not found`, alias i tabelkolonne) og ville vælte bygget.

Bygget lokalt med `KBRebuild -S demoEmpty -IPTD changed_files -FC`: done OK.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
#1847 - Scope = UseWeb på tasks i WE_ALT-menuen (13-10-26 06:37)
Alle tasks der kan nås via menuen `WE_ALT` > ActionList har fået `Scope = UseWeb` (95 actions -> 95 tasks, én linje pr. fil).

  • 91 tasks uden Scope: `Scope = UseWeb` indsat.
  • 4 tasks med `Scope = UseMCP` (TSBC_W_Status, TSBC_W_StatusGrp, TSBC_W_StatusGrpSag, TS_W_StatusGrp): nu `Scope = [ UseMCP, UseWeb ]`.

Ikke med: de to direkte `TaskRef`-punkter i `WVMenuList/WE_ALT` (VARER_WE, Skema_Test), da de ikke går via ActionList.

Bygget lokalt med `KBRebuild -S demoEmpty -IPTD changed_files -FC`: done OK (med `FILE/WSetup.PTD` fra master, da `WSetup.WebNySKP` fra PR 1815 ikke var i den lokale program-mappe).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
#1829 - Pakkens indhold: kort udgave i stedet for at udelade ved for lang beskrivelse (13-10-26 06:34)
**Hvad:** `WEB_SF_VareTekstGQL` – når beskrivelse + fuld stykliste (varedeklaration/allergener/næring pr. komponent) bliver over 25.000 tegn, sendes nu en kort udgave af pakkens indhold med kun komponentnavne og links. Først hvis også den er for lang, sendes beskrivelsen uden pakkeindhold (som før).

**Hvorfor:** før forsvandt hele pakkeindholdet på store pakker.

**Risiko:** ingen ændring for varer under grænsen; kun én ny lokal variabel (KitKort).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
#1817 - Menu og ActionList (okt-26) (11-10-26 07:57)
Menupunkter til de nye skærme fra PR 3 og PR 4.

**Bygger på PR 4.** Den retargetes til master, når PR 2-4 er merget.

Indhold

  • **ActionList:** 20 nye actions, alle tilføjet SIDST. Actions er positionsbaserede, så ingen eksisterende er flyttet eller fjernet.
  • Opstart Shopify, Shipmondo og ISO-landekoder.
  • Filtre, bulk-send, genkobl, overgang og kategoribilleder.
  • Opskrifter, guides, anmeldelser, bookinger og kampagner.
  • Webfakturaer og afregninger fra Clearhaus og MobilePay.
  • **MainMenu og MainMenu_Ribbon:** menupunkterne under "Opstart Shopify" og Web. Kun tilføjelser.

Test

1. Indlæs ActionList og menu efter PR 2-4, og log ind igen.
2. Tjek, at de eksisterende menupunkter åbner det samme som før. Hvis login fejler med "Index out of range", er en action flyttet.
3. Åbn hvert nyt menupunkt.

JNF-skærme i standarden

8 tasks fra JNF, som ikke fandtes i standarden:
  • **Bankposter uden bilag:** BankpostIndAben_BS_WE.
  • **Kontoudtog:** DPOSTKONTOUDTOG og UDSKRIVDPOSTAABNEKTOG (kun relevante poster).
  • **Pluk med billede:** SORDRE_PLUKIMAGE_WE, SORDREWEB_PLUKIMAGE_WE og SORDREKORT_PLUKIMAGE_WE. Webordretypen tages fra WSetup.WebNySKP i stedet for hardcodet 15.
  • **Trigger-kø og log:** SYSTEM_TRIGGERSRUN og SYSTEM_TRIGGERSRUNLOG.

Felterne de kræver (nye felter og nøgler er tilføjet til sidst):
  • **Dokumentbiblotek:** felterne OrdreLinje og Enhed, nøglen OrdreLinje og FKEY Enhed (som i JNF).
  • **SOrdreLinje:** DokumentNavnV (virtuel). Viser linjens billede, ellers varens primære billede.

6 nye actions er tilføjet sidst i ActionList.


🤖 Generated with [Claude Code](https://claude.com/claude-code)

#1816 - Webordre, pluk og Shipmondo (okt-26) (11-10-26 07:19)
Webordrer kan plukkes og sendes på samme måde som almindelige ordrer. Pluk-flowet er som i JNF, og Shipmondo kan sættes op uden hardcoding.

Indhold

  • **Webordrekort (SORDREKORT_EDI):**
  • Ordre, debitor og fragt, betalingsspecifikation og forsendelser.
  • Ekspedér, annullér i Shopify, fakturér og plukseddel/følgeseddel.
  • **Pluk som i JNF:**
  • Plukliste og ordrescan med eller uden O foran (plukseddelstregkoden).
  • Ordren låses ved første scanning. SORDRE_PLUK_START tager kun låsen, når ordren er fri.
  • Scan leverer også på batch-linjer uden batchnummer, og enhedsstyring virker.
  • **Webordretypen** (WSetup.WebNySKP) vises i pluk- og EDI-listerne (SORDRE_PLUK*, SO_Pluk, SORDRE_PlukListe, SORDRE_EDI). Webordrer i eKladde kan plukkes uden bekræftelse. WebNySKP = 0 betyder som før.
  • **Shipmondo:**
  • Opsætning (TRANS_Shipmondo_Opsaet). Kunden udfylder kun API-bruger og API-nøgle.
  • Ved opret og import gemmes fejlsvar ikke som forsendelsesnummer, og fejlloggen er forbedret.
  • Attention og told følger landet.
  • **Land_UdfyldISO:** udfylder tomme ISO-landekoder (DK m.fl.), som fragt kræver.

Test (JNF sandbox)

1. Kør Land_UdfyldISO og TRANS_Shipmondo_Opsaet.
2. Hent en webordre, og scan plukseddelen. Ordren skal låses ved første varescan.
3. Lever alt, og opret forsendelse. Tjek label og land.
4. Kør en almindelig ordre (ordretype 0) gennem pluk og faktura som før.


🤖 Generated with [Claude Code](https://claude.com/claude-code)

#1815 - Shopify GQL-webstandard (okt-26) (11-10-26 06:26)
Fælles Shopify-integration via GraphQL. Den skal virke hos alle kunder og er testet i JNF sandbox og sammenholdt med Thaibutikken. Alt ligger i modulet **WShopSF**, så skærme og felter kun vises hos kunder med Shopify. Opsætningen sker på PRGSETUP_WEB (WSetup): intet er hardcodet, og Basic-butikker virker uden Plus.

Indhold

  • **Synk KB → Shopify (WEB_SF_*GQL + SystemTrigger_GQL_*)**
  • Køen fyldes af triggere og behandles af et job hvert 5. minut.
  • Varer: tekster, priser, lager pr. lokation, billeder, metafelter, varianter, kits og tags.
  • Kategorier, samlinger, brands og menu.
  • Kunder og B2B-firmaer, prislister, rabatter og kampagner.
  • Anmeldelser, guides, opskrifter, booking og maskiner.
  • **Ordreimport (Shopify → KB)**
  • Pris pr. 100/enhed og shoppens valuta.
  • Moms på nye udlandsdebitorer. Når debitoren kan genkendes, gættes der aldrig.
  • Ønsket leveringsdato er mindst ordredatoen, og webordretypen kan vælges (WSetup.WebNySKP).
  • Capture kun det fakturerede ved delfaktura. Kits udfoldes på webordrer.
  • Annullering og refusion.
  • **Kampagner:** kampagnekort, batch-tilbud, kombirabat, avis, labels og automatisk udløb kl. 00:00 (dansk tid). Udløbne kampagner slettes i Shopify.
  • **Web-indhold:** guides (SF_Guide), opskrifter (SF_Opskrift*), anmeldelser (WebAnmeldelse), booking (WebBooking*) og vare-relationer (VareRelation).
  • **Vare i appen:** VAREWEB_WE-skærmene (webtekster, specifikationer, kategorier, relationer, varianter) med knappen "Webshop" på VAREKORT_WE.
  • **Betalinger:** Clearhaus- og MobilePay-afregninger.
  • **Tema:** logo, farver og karrusel (WTema*).
  • **Token:** WEB_SF_Token (Dev Dashboard, 24 t) side om side med den eksisterende shpat-nøgle.
  • **Dokumentation:** KBWEB/SHOPIFY_OPSTART.md, SHOPIFY-GQL-ARKITEKTUR.md, SHOPIFY-APP-ADGANG.md, OPSAETNING-TJEK.md, PRIS-SYNK.md, API-KORTLAEGNING.md.

FILE-ændringer (kun nye felter nederst)

  • **Nye filer:** SF_Guide, SF_Opskrift, SF_OpskriftsVarer, VDKombiRabat, VareRelation, WEB_SF_COLLECTIONER, WEB_SF_MenuBillede, WEB_SF_MenuHovedFast, WebAnmeldelse, WebBooking og WebBookingType.
  • **Webfelter på eksisterende filer:** WSetup, Vare, VWeb, Debitor, KontaktPerson, Lokation, Maskine, RabatKampagne*, VareBatchTilbud, VareBrand, VareSpec_Specs, StykListe, SORDRETEKST, SOBetalingType, Dokumentbiblotek og ChatQA_Log.
  • **Debitor:** webfelterne ligger efter API-felterne (efter ValidFrom).

Hos kunder med egne felter bygges FILE ud fra kundens egen fil: kun de manglende felter tilføjes nederst.

Ikke med

  • **PR 4:** Shipmondo, pluk og EDI.
  • **PR 5:** ActionList og menu.
  • **Først efter validering:** VKLADDEOPT_OPRET_WE (optælling af én vare i appen).
  • **Holdes uden for repoet:** JNF-specifikke filer og temaet.

Test (JNF sandbox)

1. Indlæs FILE og genstart. Indlæs derefter TASK (UTF8 og 1252).
2. Udfyld PRGSETUP_WEB, hent token og kør "Opstart Shopify".
3. Ret en vare, en pris og lageret, og tjek dem i Shopify efter 5 minutter.
4. Hent en webordre, og fakturér den. Tjek capture, moms og valuta.
5. Opret en kampagne med udløb i dag, og tjek, at den er væk efter midnat.


🤖 Generated with [Claude Code](https://claude.com/claude-code)

#1814 - Thai-forbedringer og fakturamatch (okt-26) (11-10-26 05:32)
Forbedringer fra Thaibutikken, sammenlignet med standarden og JNF og gjort generelle. Hertil fakturamatch med og uden enhedsstyring. Thai-specifikke ting (madvarer, ingredienser, holdbarhedsbatch, FlexPOS-knapper) er IKKE med. Alt nyt er slået fra som standard eller vises kun, når funktionen er i brug: batch, enhedsstyring, GoCardless.

Batch / FIFO

  • **LotStyring** på LagerSetup og pr. ordretype på SKPSetup:
  • 0 = som hidtil
  • 1 = ældste hele batch
  • 2 = altid ældste batch

Felterne vises på PRGSETUP_Lager og SKPSetup.
  • **SOL_BATCH_FIFO:** Thai's rettede version.
  • Linjens egen reservation frigives først.
  • Restlinjen reserveres korrekt.
  • Fordelingen stopper, når alt er fordelt.
  • Restlinjer mærkes `Kilde = "SOLFIFO"`.
  • **Nye tasks:**
  • SOL_VaelgBatchIgen(_Ordre): "Genberegn batch". Rører ikke delvist leverede linjer.
  • VARE_LOTNR_Fordel/FordelBogfor: rettet version, som ikke auto-bogfører tomme kladder.
  • VARE_LOTNR_NytBatch og VARE_LOTNR_Ret.
  • **Højreklik** på VARE_LOTNRAlle: Ret batch, Fordel beholdning og Nyt batch.

Scan og enhedsstyring

  • **TMP_SOrdre_TilfojVareScan_WE / SORDRE_TilfojVareScan_WE:** en skannet kasse-EAN giver rigtig enhed, EAntal og basisantal. Det gælder KUN med enhedsstyring; uden kører præcis den gamle kode.
  • Batch fra label (GS1 AI 10/37) følges.
  • FIFO-restlinjer ryddes, når LotStyring > 0.
  • **SOrdreLinje.VEnhedAntal** = 1 uden enhedsstyring, som IOrdreLinje allerede gør.
  • **Ordrekort:** EAntal/ELevAntal-kolonner.
  • **SORDREKORT_WE:**
  • EAntal-kolonne.
  • Farve på linjer uden varenr.
  • Højreklik "Vis vare" og "Genberegn batch".
  • **SORDRE_WE:** farve på ordrenr efter status.
  • **SOrdreLinje_WE:** linjetekst/notat og "Vis vare".
  • **Indkøb:**
  • IORDREKORT: kolonnen Enheds Apris og "Hent BS priser".
  • IORDRE: "Arkiver ordre".
  • Indkøbs-appen: "Slet linje" og HoldbarhedsDato.
  • **Vare_EnhederStk** sikrer basisenhed ved enhedsstyring og kaldes fra FlexposAPI_Vare_Wrap.
  • **Plukliste (SORDRE_PLUK_WE) som i JNF:** alle bekræftede ordrer til levering, ordrescan med eller uden O foran, status og lås-ejer tjekkes.
  • **Pluk-kort (SORDREKORT_PLUK*_WE):**
  • Scan med almindelig EAN/kolli-EAN leverer også på linjer, som FIFO har givet batch.
  • Låsen tages ved første handling.

Fakturamatch (BS)

  • **BasisAntal** = samlet antal i basisenhed.
  • Med enhedsstyring omregnes kasse/kolli via Enhed_Vare.
  • Uden enhedsstyring bruges fakturaens antal.
  • Rettet i: BS_Ft_Upload_KBFT, AutoVare, IOLDi, OvfPriserIOrdre, TilfIOrdreLinje og BSSORDRE_Opret.
  • **UNITCODES_OPRETSTD:** startdialog og alias. Et tomt alias sletter ikke længere kundens alias.
  • **AutoVare:** to tabte matchregler er genindsat. Moms-autokorrektion når linjerne er inkl. moms.
  • **Overfør priser til indkøb** overskriver antal som standard, som før.
  • **TilfIOrdreLinje:** spærre mod dobbeltklik, og linjer uden varenr oprettes ikke.
  • **CVR-kontrollen:**
  • Gyldige svar meldes ikke længere som "ikke fundet".
  • Fejl fra CVR-API'et giver ikke fejl på bilaget.
  • **Fallback for linjetotal** er nu ekskl. moms; feltet er netto.

Bank og udligning

  • **Gem kontering** (Bank_GemKontering): husker konteringen pr. tekst, så Foreslå bruger den.
  • **Vend finanspost/kreditorpost til kladde:** FinPost_VendBankposter_TilKladde og Kredpost_Vendposter_TilKladde (modkonto er en parameter).
  • **GoCardless-fornyelse:** Bank_Ng_ExpiredCheck/ExpiredMail/AftaleForny med nye felter AdvarTrin/AdvarSendtDato nederst i Bank_NgAftaler. Kræver et dagligt job hos GoCardless-kunder.
  • **DUDLIGN/DAUTOUDLIGN:** valget "Uden besked". Standarden er som før.

Vare

  • **VAREKORT:**
  • F9 Åben fil (seneste dokument).
  • Fordel batch (afvises uden batchstyring).
  • **VARER:** F9 Åben fil. Ingen nye kolonner.
  • **VARELISTEKORT:** "Udskriv til kassen" (VareListe_KasseUdskrift: 2 kolonner med billede, pris og stregkode).

FILE-ændringer (kun nye felter nederst)

  • LagerSetup og SK
#1813 - Fejlrettelser i standarden (okt-26) (11-10-26 05:04)
Små, uafhængige fejlrettelser i eksisterende tasks. Ingen nye tasks og ingen FILE-ændringer. Fundet under Shopify-standard-arbejdet og sammenligningen med Thaibutikken/JNF.

Rettelser

  • **CVR-konkurstjek virkede aldrig:** `getjsontag` giver `"True"`/`"False"`, så `== "true"` matchede aldrig. Nu bruges `tolower(...)`. Det gælder:
  • CVR-tjekket i 10 debitor-/kreditortasks (DEBITOR, DEBITORKORT, DEBITOR_WE, KREDITOR, KREDITORKORT, KUNDEEMNER, Firma_OpretFraCVR, CRM_CVR_TJEK og BS_Ny/Opdater/AutoOpdaterKreditor)
  • BS_Ft_Kontrol_KBFT
  • `ReadyForInvoicing` i API_SOrdre_Opret_Batch
  • `buyer_accepts_marketing` i WEB_SF_OrdreHentEnJSON
  • **Bankafstemning, forslag (BankPost_FKont_Foreslå):**
  • Reglen "Start af" matchede aldrig: koden sammenlignede med "Start Af", men valget hedder "Start af".
  • Reglen "Del af" matchede aldrig: argumenterne til `strsearch` var byttet om.
  • En gemt kreditor-kontering blev aldrig brugt.
  • **Scan på ordre i appen (SORDRE_TilfojVareScan_WE):** en vare-EAN blev aldrig slået op, fordi der manglede et `!`. Nu virker det som scan i indkøb og genbestilling.
  • **Optælling i appen:**
  • "Slet linje" sendte kun LinjeId og kunne ramme forkert linje.
  • "Slet linje" lå også på F5 (= dobbeltklik/Rediger), så F5 kunne slette. Den er flyttet til F8.
  • **F5 = dobbeltklik:**
  • VARER_WE og VGenBestil_WE havde to handlinger på F5. Den anden er flyttet til F6.
  • VARE_LOTNR og VARE_BEHOLDNING_LOKATION har fået F5 = dobbeltklik.
  • **EXPORT_VARE_LOK_BATCH_BEH:** første linje blev skrevet to gange, og der var ingen overskrift.
  • **Sikkerhed:**
  • FlexPos_APIToken og Payment_Klarna_Capture havde nøgler hardkodet i koden. De læses nu fra Specialoplysninger (`FlexPOSAuth`/`KlarnaAuth`).
  • FlexPOS-tokenet overskrives kun ved et lykket login.

Kræver opsætning ved opdatering

  • **FlexPOS-kunder:** opret `FlexPOSAuth` i Specialoplysninger (base64 af client_id:client_secret) FØR opdatering.
  • **Klarna:** opret `KlarnaAuth`. Capture har reelt ikke virket før, fordi nøglen var "xxx".
  • **Nøgler i historikken:** de gamle nøgler ligger i git-historikken og bør skiftes.

Test (JNF sandbox)

1. Indlæs `INDLAES-PR1-FEJLRETTELSER-UTF8.PTD` og `-1252.PTD`, og tjek at de kompilerer.
2. **CVR:** opslag på en kendt konkursramt CVR viser beskeden.
3. **Bankafstemning:** en gemt regel "Start af" og "Del af" foreslår kontoen.
4. **App:** scan en vare-EAN på en ordre. I optællingen skal F5 = rediger, og F8 = slet.
5. **FlexPOS (hvis brugt):** med `FlexPOSAuth` sat skal token-hentning virke.

Kundespecifik regel fjernet fra standarden (11/10-2026)

  • WEB_SF_OrdreHentEnJSON (gammel REST-import): `//TREKANTES if strleft(title;11) == "ISTERNINGER" then VNummer = "10-2"` (indsat 2024-02-21 af Lasse). Skal kunden (Trekanten?) stadig bruge den, laegges linjen ind lokalt hos dem.


🤖 Generated with [Claude Code](https://claude.com/claude-code)

#1515 - KeyBalance API sep 26 (11-10-26 03:55)
Nye standard API'er rigtig mange tasks, lidt ekstra filer og felter - men alt nyt, burde ikke være noget farligt :)
#1772 - Blot fkey fejl (08-10-26 10:31)
Blot fkey fejl
#1743 - Bankfiler: tilpasning til Jyske Banks strukturerede adresser + diverse rettelser (08-10-26 06:22)
Bankfiler: tilpasning til Jyske Banks strukturerede adresser + diverse rettelser

  • EXPORT_BANK_ISO20022_Fil: ByNavn afkortes til 35 tegn, XML-header med dobbelte anførselstegn
  • EXPORT_BANKDATA: oprydning/omformatering, gemt som UTF-8
  • Bank_MIB_TransHent: brug transactions[].id og status, debug-logning
  • FSetup.AfdDiff: ny afdeling til kursdifferencer m.m., bruges i DUDLIGN/KUDLIGN ved tvungen afdeling
  • SGEBYR_BEREGN: valutaomregning af gebyr pr. gebyrfaktor
  • Vare: salgspris fra stykliste kun når varen har stykliste
  • KASSEKLADDE: menupunkter under Opsætning (Bogføring, Nummerserier)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#1737 - 061026 sylvest1100 (06-10-26 19:58)
funktion til at udligne post direkte op imod ørediff konto
#1736 - Udlejning / lager false (06-10-26 19:58)
#1529 - Div småting (30-09-26 11:46)
Diverse mindre rettelser og udvidelser på tværs af moduler.

FILE/FSetup.PTD

Mailskabelonens CSS er lagt om til KeyBalance-designet: ny farvepalet (#356977 / #eaeaea),
Arial som skrifttype og padding på celler. Baggrundsbilledet (maillogo.png som
`background-image`) er fjernet, og de citerede CSS-værdier er skrevet uden apostroffer,
så de rent faktisk bliver honoreret af mailklienterne.

FILE/KassekladdeLinje.PTD

Posteringsteksten på udligningslinjer tager nu hensyn til sproget på debitor/kreditor:
er kundens/leverandørens `Sprog` sat op med `TextLayer == 1`, dannes teksten på engelsk
("Payment") i stedet for dansk ("Indbetaling"/"Betaling"). Samtidig slås modkonto-varianten
op på `Modkonto` i stedet for `Kontonr`, som var forkert.

TASK/API_OP_S1_KE.ptd

  • Ny undertask og tabel med salgsordrer (SOrdre) på kundeemnet — åbne ordrer/tilbud
(`SalgKøbProd` 0 og 10..29) for den valgte debitor.
  • `CanEnter( KundeEmne.DKontonr )` på undertaskene, så de kun kører når der er en debitor.
  • SELECT-blokkene på SFaktura og Debitorpost er ryddet op (felter uden filprefiks,
korrekt formatering).

TASK/API_OP_S1_KP.ptd

Kontaktpersonens `Initial` er tilføjet som kolonne.

TASK/API_OP_S1_PostFile.ptd (ny)

Ny batch-task til Outlook-pluginet: gemmer en fil fra en mail via
`internetMessageId`/`networkMessageId`.

TASK/BS_Bilag.PTD

  • Ny handling "--> Omkostning" (actSkiftO) der kalder BS_Bilag_SkiftTilOmkostning,
som modstykke til den eksisterende skift-til-finans-handling. Vises kun når bilaget
ikke allerede er en omkostning.
  • Betingelsen på actOIOVis er ændret fra `OmkostArt == "Omkostning"` til
`OmkostArt <> "Vare"`, så også bilag uden omkostningsart kan vises.

TASK/Bank_Ng_Aftaler.PTD

Ny handling "Godkend (www)" der åbner aftalens `AftaleLink` i browseren via WWWOpen.

TASK/Bruger_NytPassword.ptd

Tom `Init()` på parameteren SendeType er fjernet.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

#1550 - Fjern midlertidige MCP_-kopier i EXTRA_PTD/TASK (30-09-26 11:45)

Formål


Fjerner de 20 midlertidige `EXTRA_PTD/TASK/MCP_*.PTD`-kopier.

Baggrund


Kopierne var et udrulningsvehikel, så kunder kunne få MCP-taskene *inden*
standardopdateringen landede. De var rene kopier af originalerne i `TASK/`,
hvor kun `TASK <navn> {` og den selv-refererende `TaskRef` var omdøbt til
`MCP_<navn>`.

`Scope = UseMCP` ligger nu i standard-taskene i `TASK/` (over 1.000 tasks),
og kunderne har dermed funktionen i basis-taskene. Kopierne er redundante.

Ændringer


Slettet i `EXTRA_PTD/TASK/`:

MCP_ALSTATISTIK, MCP_DEBITOR, MCP_DTRANSAKTIONER, MCP_DVSTATISTIK,
MCP_FKONTOPLAN, MCP_FTRANSAKTIONER, MCP_IOLSTATISTIK, MCP_KREDITOR,
MCP_KTRANSAKTIONER, MCP_LVSTATISTIK, MCP_MASKINE, MCP_MTRANSAKTIONER,
MCP_OLSTATISTIK, MCP_SAG, MCP_SFAKTURA, MCP_SFAKTURA_ALLE,
MCP_SOLSTATISTIK, MCP_STLSTATISTIK, MCP_VARER, MCP_VTRANSAKTIONER

I alt 20 filer, 2.984 linjer.

Bemærkninger


  • Ingen ændringer i `TASK/` eller `FILE/` — kun sletninger.
  • `EXTRA_PTD/TASK` indgår ikke i autobyg, så sletningerne påvirker ikke
pipelinen.
  • Kunder der i dag kører på `MCP_`-kopierne skal have standardopdateringen
med `Scope = UseMCP` i basis-taskene, inden denne fjernelse rulles ud.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

#1689 - Pakke-klipper: MergeMode styrer om objekter flettes, erstattes eller kun leveres som nye (30-09-26 09:14)

Oversigt

MergeMode på pakkens objektliste blev hidtil kun skrevet i manifestet - alt blev leveret som .PTD og overskrevet. Nu styrer den leverancen i trinnet "Build payload":

  • **Flet** (0): en FILE leveres som `.PTX` og flettes ind i kundens definition. En TASK kan ikke flettes og overskrives som før (loggen viser antallet).
  • **Erstat** (1): `.PTD`, uændret.
  • **Kun ny** (2): `.PTD` plus `#SKIPEXISTING <TYPE> <Navn>` i `PTDUpdate.ini` i pakkens rod, så KBAutoU springer objektet over hvor det findes. Kræver den nye KBAutoU (Keybalance2018-PR'en).

MergeMode accepteres som tekst eller tal. Manifestet viser den endelige sti. `PTDUpdate.ini` skrives uden BOM.

Bemærk: alle rækker står som standard på Flet, så næste klipning sender alle FILEs som `.PTX`. Sæt dem der skal overskrives til Erstat.

Filer

  • `azure-pipelines-package.yml`

Testplan

  • [ ] Klip med "Kun vis indhold" = Ja: loggen viser `MERGE FILE/...PTX` for Flet-FILEs
  • [ ] Et objekt sat til "Kun ny": `PTDUpdate.ini` ligger i pakkens rod med én `#SKIPEXISTING`-linje
  • [ ] Manifestets Path ender på `.PTX` for flettede FILEs

🤖 Generated with [Claude Code](https://claude.com/claude-code)
#1621 - Rettelser af compiler-warnings (typer, lookup-nøgler, manglende alias) (24-09-26 11:22)

Resumé

Retter en række warnings fra PTD-compileren.

  • **VOpt_OptKladdeOnScan_WE**: Parentesen i `lookupnc()` sad forkert, så nøglen blev en Bool. De to ShouldExecute har sandsynligvis aldrig været sande. Nu kører det første kald ved kendt scanning, og `TMP_VOPTVareLotScan_KORT_WE` åbner ved ukendt. **Ændret adfærd på web-scanneren.**
  • **VOpt_Optælling_HentPlaceringer**: `VarePlacering.Plac1/Plac3` er Long, `VOpt_Linje.Plac1/Plac3` er String. `string()` i både `lookupnc`-nøglen og tildelingerne i `OpretPlac`.
  • **SOrdre_OpretDebDokG_PDF**: "Modtager" slog `DebUsers.Løbenr` op med `ReelLogin` (streng). Bruger nu `GodkenderUserid` ligesom linjen over.
  • **KEVaskIMP_NNEmner**: `"S" + $Felt8` (String + ULong) → `string($Felt8)`. Dublettjekket slår stadig op på nøgle 1 (`KEVaskLøbenr`) og kan ikke ramme – ikke rettet her.
  • **HR_Fravar_Tilgang**: `FravarKode` havde Length 4, forældernøglen `HR_Fravar_Kode` bruger 10 (ligesom alle andre HR-filer). **Postlayout og alle fire nøgler ændres – eksisterende datafiler skal konverteres/rebuildes.**
  • **UARBEJDSKORT**: `SOrdre_Mobile` var linket to gange i samme task-træ. Linket i `Linjer` (fra PR 1541) hedder nu `SOrdre_Mobile[SOM]`, og de fire datoreferencer i `PrtFakturalinjer` peger på `SOM`.

De fire cp1252-filer er konverteret til UTF-8; linjeskift uændrede.

Filer

  • FILE/HR_Fravar_Tilgang.PTD
  • TASK/KEVaskIMP_NNEmner.PTD
  • TASK/SOrdre_OpretDebDokG_PDF.PTD
  • TASK/UARBEJDSKORT.PTD
  • TASK/VOpt_OptKladdeOnScan_WE.PTD
  • TASK/VOpt_Optælling_HentPlaceringer.PTD

Testplan

  • [ ] Compile: warningerne er væk (undtagen KEVaskIMP_NNEmner linje 158, se ovenfor)
  • [ ] Web-scanner i optællingskladde: kendt vare/lot og ukendt scanning
  • [ ] Hent placeringer til optælling: linjer oprettes/opdateres med korrekte placeringer
  • [ ] Dokumentgodkendelse: fejlbesked viser modtagerens e-mail
  • [ ] Fraværstilgang: data konverteret, koder på over 4 tegn kan registreres
  • [ ] Arbejdskort: Start/Slut viser den aktive mobilordres datoer

🤖 Generated with [Claude Code](https://claude.com/claude-code)
#1620 - Rettelser i BankPost_DKont_Foreslå og Kommentar på TRANS_OpretSForsend_* (24-09-26 09:05)

Oversigt


**BankPost_DKont_Foreslå**
  • `$NSDLen` beregnes nu ud fra `$NSDNuv` (debitornummerserien) i stedet for `$NSNuv` (fakturaserien)
  • Punktum fjernes nu fra `$FakturaMinus2B` i stedet for `$FakturaMinus1B`
  • Fakturadato-opslaget for "Faktura minus 1" bruger nu `$FakturaMinus1` i stedet for `$FakturaMinus2`, så dato og debitor slås op på samme faktura
  • Filen er konverteret fra Windows-1252 til UTF-8 (derfor de ekstra linjer med æ/ø/å i diffen)

**TRANS_OpretSForsend_***
  • Ny inputparameter `Kommentar` ("Evt note", 200 tegn), som gemmes i `SForsendelse.Kommentar`
  • Tilføjet i Debitor, IOrdre, Kreditor og SOrdre_SkrivTT (SOrdre havde den i forvejen)
  • SOrdreDirekte er bevidst ikke ændret: den kaldes direkte fra andre tasks og har heller ikke Vægt/Colli
  • IOrdre, Kreditor og SOrdre_SkrivTT er konverteret fra Windows-1252 til UTF-8

Filer

  • `TASK/BankPost_DKont_Foreslå.PTD`
  • `TASK/TRANS_OpretSForsend_Debitor.PTD`
  • `TASK/TRANS_OpretSForsend_IOrdre.PTD`
  • `TASK/TRANS_OpretSForsend_Kreditor.PTD`
  • `TASK/TRANS_OpretSForsend_SOrdre_SkrivTT.PTD`

Test

  • [ ] PR-build (KBRebuild) er grøn
  • [ ] Foreslå kontering på indbetalinger finder faktura ud fra reference med "minus 1"/"minus 2"
  • [ ] Opret forsendelse fra debitor, indkøbsordre, kreditor og salgsordre (SkrivTT) med note, og noten står i forsendelsens kommentar

🤖 Generated with [Claude Code](https://claude.com/claude-code)
#1541 - 0-fakturaer danner nu Debitor-/Kreditorposter + div. småforbedringer (15-09-26 16:00)
0-fakturaer (bruttobeløb 0) blev hidtil undertrykt og dannede hverken debitor- eller kreditorpost. De danner nu poster som alle andre fakturaer. Derudover en række mindre forbedringer.

0-fakturaer danner nu Debitor-/Kreditorposter


`FILE/SFaktura.PTD` (trigger `DSAMLEPOST`) og `FILE/IFaktura.PTD` (trigger `KSAMLEPOST`): `Brutto`-betingelsen er fjernet fra begge triggeres `CanExecute`.

```diff
  • CanExecute( Firma.AutoBogførSalgsFaktura & SFaktura.Brutto & SFaktura.NoTrigger == false & ... )
+ CanExecute( Firma.AutoBogførSalgsFaktura & SFaktura.NoTrigger == false & ... )
  • CanExecute( Firma.AutoBogførIndkøbsFaktura & IFaktura.Brutto & IFaktura.NoTrigger == false )
+ CanExecute( Firma.AutoBogførIndkøbsFaktura & IFaktura.NoTrigger == false )
```

`Brutto` er falsk ved beløb 0, så samleposten blev slet ikke dannet — fakturaen fandtes kun i fakturajournalen og var usynlig i reskontroen. Øvrige betingelser er uændrede.

Dagssaldo i bankafstemning


  • `FILE/BankkontiSaldo.ptd`: nyt felt `BankPostBevægDag` — sum for **den aktuelle dag** alene (`[UltDato]` i stedet for `[..UltDato]`). Det eksisterende akkumulerede `BankPostBevæg` har fået prompt "Bank Bevægelse" → **"Bank Bevægelse AKK"**, så de to ikke forveksles.
  • `TASK/BankPost_Saldi.ptd`: kolonnen viser nu dagsfeltet, så dagens bevægelse kan aflæses direkte pr. dato.

Valuta ved manuel import af bankposter


`TASK/Import_BankPost_Generisk.PTD`: `Valuta` blev ikke sat ved generisk import, hvilket gav poster uden valuta på valutabankkonti. Den hentes nu fra bankkontoens finanskonto via `lookup(Finans.Valuta;1;lookup(Bankkonti.Kontonr;1;#BankKonto))`. `if`-vagten sikrer, at feltet kun sættes når kontoen faktisk har en valuta — konti i systemvaluta røres ikke.

BS — tilføj ekstra bilag


  • `TASK/BS_Bilag_TilfojExBilag.PTD`: filnavnet er nu `<BSNummer>_<nextnum("BS_ExtraBilag")>_<filnavn>`. Uden tælleren fik to bilag med samme oprindelige filnavn på samme BS-nummer identisk destinationsnavn, og det ene overskrev det andet.
  • `TASK/BS_Bilag_ExtraBilag_OpenFil.PTD`: `FileNameExpr` tog før altid `"../" + DokNavn`, hvilket pegede forkert hvis stien allerede indeholdt BS-mappen. Der tjekkes nu med `strleft(DokNavn;strlen(FSetup.BS_Path)) == FSetup.BS_Path`, og `BS_Path` indsættes kun når den mangler.

Sordrekort værksted


`TASK/SORDREKORT_VÆRKS.PTD`:

  • Memofelterne "Opgave (Extern beskrivelse)" og "Intern tekst" er flyttet til en **ny fane "Tekster"** nederst, placeret side om side (`Direction = LeftRight`) og væsentligt bredere (800/700 mod ca. 200 før), så længere værkstedsnotater kan læses uden scroll.
  • Ordrelinjetabellen er rykket ned (`y` 600 → 1201) for at give plads.
  • `actSORDRE_Dokumenter` omdøbt "Old - Dokumenter" → **"Dokumenter v1"**.
  • Rettet indrykning to steder — ingen funktionel ændring.

Valgfrie tekster på arbejdskort


`TASK/UARBEJDSKORT.PTD`:

  • Ny parameter `TekstVlg` (`BChList`): **Begge** (0, default), **Kun Intern** (1), **Kun Extern** (2).
  • Overskrifter og memofelter styres nu af `Enable()` ud fra valget. "Intern tekst" var før hårdkodet `Enable( 0 )` — altså aldrig med på udskriften; den kan nu vælges til.
  • Blokhøjde 500 → 700 og teksthøjde 300 → 400, så overskrifterne ikke beskæres.
  • Nyt `LINK` fra `SOrdreLinje` til `SOrdre_Mobile` via `SOrdre.AktivSOM`.
  • Dummy-linjens `Løbenr` ændret 10 → 100001, så den ikke kolliderer med rigtige ordrelinjenumre.

Til reviewer: diff-støj i SFaktura.PTD


Filen fremstår med ca. 4.500 ændrede linjer, fordi den er EOL-normaliseret CRLF → LF ved commit (`core.autocrlf`). Indholdet er uændret bortset fra `CanExecute`-linjen ovenfor og nogle kommentarer, hvor efterstillet whitespace er brudt om på ny linje. **Slå "ignorer whitespace" til** — så er ændringen 17 linjer.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

#1514 - WEB_API_TokenGrp: AuthMode EntraID Intern / Statisk + EntraID Intern, DefaultUser required for External modes (13-09-26 19:38)

What


`FILE/WEB_API_TokenGrp.PTD` only.

  • `AuthMode` choice list gains **5 "EntraID Intern"** (Entra JWT; the UPN must match `Bruger.Email`, the call runs as that user) and **6 "Statisk + EntraID Intern"** (static token in `Authorization` + JWT in `X-KB-User-Token`, same identity rule).
  • Labels 1-4 (Statisk, EntraID, Enten, Begge) are untouched - choice-list values cannot be renamed. Their hint text now spells out that EntraID, Enten and Begge bind the JWT to an **external** identity and run the call as Default bruger / the token's Login, and that the bound user's rights apply in every EntraID mode.
  • `DefaultUser` is now `Required`, enterable and shown for EntraID, Enten and Begge. Its hint text is rewritten; the old one carried corrupted characters (`n�r`, `pr�senteret`).

Why


The server (Keybalance2018 branch `feature/apiv3-license-filter`) binds every Entra-authenticated APIv3 call to a real Bruger and enforces that user's standard access controls. External modes run as `DefaultUser`, so a group in one of those modes without it is skipped at config build. This PR makes the PTD enforce the same rule at save time and offers the two Internal modes.

Notes


  • Stored values 1-4 are unchanged; existing groups keep working.
  • `WEB_API_TokenAdgang.Kategori` (Swagger grouping) is deliberately **not** in this PR.
  • Edited at byte level to preserve the file's mixed encodings; passes the grammar stage of `KB.PTD.Parser`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
#1479 - Brug TSAkt i stedet for HRTimer (08-09-26 19:18)
Brug TSAkt i stedet for HRTimer
#1489 - Aktivitetsteksten blev hentet fra den forkerte fil og blankede feltet (08-09-26 11:23)

Resumé


I `OpdaterJobFørDag` slår opslaget aktivitetsteksten op i **`TSAktivitet`** i stedet for **`TSBCAktivitet`** — `TSBC` er faldet ud af en kopi af linjen.

Nøgle 1 i `TSAktivitet` er `KEY Kørselnr`, hvis første segment er det ulong `Kørselnr`. Opslaget søger altså på et *kørselsnummer* med et *ydelsesnummer*. Resultatet er enten en tom tekst eller en vilkårlig fremmed aktivitets tekst — hver gang `Bemærk1` er tom.

```
  • TSAktivitet2.Tekst = lookup( TSAktivitet.Tekst;1; TSAktivitet2.VNummer);
+ TSAktivitet2.Tekst = lookup( TSBCAktivitet.Tekst;1; TSAktivitet2.VNummer);
```

Den korrekte form står i samme fil 141 linjer længere oppe, i søster-tasken `OpdaterJobFørSammeDag` (linje 172), og i forældre-tasken (linje 94). `TSBCAktivitet` nøgle 1 er `KEY I_ID` med ét segment, `Navn`, `BString(10)` — samme type og længde som `VNummer`.

Fejlen har vist sig i Sentry som **Compare failed** med `TSAktivitet:Kørselnr` (B_ULONG) mod et streng-udtryk, bruger SUSANNE S, licens BTM.

Overflødig tildeling fjernet

`TSAktivitet2.Tekst = TSBCF.Bemærk1;` stod umiddelbart før `if TSBCF.Bemærk1 then TSAktivitet2.Tekst = TSBCF.Bemærk1`. Den er formentlig grunden til at fejlen har kunnet ligge upåagtet: teksten så rigtig ud så længe `Bemærk1` var udfyldt. Blokken er nu identisk med søster-taskens.

Filer


  • `TASK/TSBCUpdateJobs.PTD` — rettet opslag, fjernet dobbelt tildeling.

Filen er samtidig konverteret fra **cp1252 til UTF-8**. Det er de øvrige 19 linjer i diffen — rene `æ ø å`, ingen indholdsændring. Linjeskift (CRLF) er uændrede.

Test


  • [ ] Kør `TSBCUpdateJobs` på en registrering hvor `Bemærk1` er tom, og som rammer `OpdaterJobFørDag`-grenen (dagen før, ikke samme dag)
  • [ ] `TSAktivitet.Tekst` får aktivitetens tekst fra `TSBCAktivitet` i stedet for at blive blank
  • [ ] Kontrollér at en registrering *med* `Bemærk1` stadig får bemærkningen som tekst
  • [ ] Sentry-eventen `Compare failed / TSAktivitet:Kørselnr` holder op

🤖 Generated with [Claude Code](https://claude.com/claude-code)
#1424 - Forbedring af CRM kundeemne-kort i klient og app (08-09-26 09:58)
Forbedring af kundeemne-kortet, så det både i klienten og i app'en (WE) fremstår
som en færdig funktion frem for en demo.

Klient — `TASK/CRM_Map.PTD`


  • Dialogtitel rettet fra "KundeEmne Map Demo" til "KundeEmne Kort".
  • Pin-action omdøbt fra `actKEKort` til `actKUNDEEMNEKORT`, med teksten
"Vis emne" / "Viser alle oplysninger om emnet" i stedet for "Vis KE" /
"Viser alle oplysninger om kontoen".
  • Tilføjet `Options = [ CreateAction ]`, så handlingen også ligger i
handlingslisten og ikke kun udløses af selve pin'en.
  • Tilføjet F5-genvej (`Event { WVEvent { VK = App.VK_F5 } }`) på linje med
øvrige "vis kort"-handlinger i systemet.

App/WE — ny `TASK/CRM_Map_WE.ptd`


  • Ny task `CRM_Map_WE` med titlen "KundeEmner på Kort", bygget over samme
struktur som klientens `CRM_Map`: subtask `Points` på `KundeEmne`, filtreret
på at `AdrLat`/`AdrLng` er sat (`FromTo( [0,01..] )`).
  • Pin viser navn, adresse, postnr./by og sælger.
  • Pin-action `actKUNDEEMNEKORT` åbner `CRM_KundeEmneKort_WE` med
`KundeEmne.Kontonr` som parameter.

Menu og handlingsliste


  • `WVActionList/ActionList.PTD`: ny `actCRM_Map_WE` ("KundeEmner, Kort") med
`TaskRef = CRM_Map_WE`.
  • `WVMainMenu/WE_ALT.PTD`: menupunktet er indsat to steder, begge gange lige
efter `actCRM_AktivitetKal_WE`. Det ene sted erstatter det demo-/test-punkt,
der pegede på `actTEST_DebitorMap2_WE`.

Licens/modul — `MODULEMAIN/MODULES.PTD`


  • `CRM_Map_WE` er tilføjet til `MODULE CRM`s `TaskList` ved siden af klientens
`CRM_Map`, så app-menupunktet kommer og går sammen med CRM-licensen.
  • Bevidst **ikke** tilføjet under `MODULE KB2018`, hvor `CRM_Map` også står:
KB2018 sikrede oprindeligt, at tasken slet ikke blev vist i den gamle klient
(som ikke understøtter kontrollen). Da ribbon-menuen i dag kun kører i den
nye klient og hovedmenuen mest i den gamle, er den gating ikke relevant
længere.

Bemærkninger


  • `actTEST_DebitorMap2_WE` og `TASK/TEST_DebitorMap2_WE.ptd` er bevaret — actionen
er fortsat refereret to andre steder i `WE_ALT.PTD`, så der er ingen døde
referencer.
  • Begge `TaskRef` er verificeret: `KUNDEEMNEKORT` og `CRM_KundeEmneKort_WE`
findes begge i `TASK/`.

#1437 - Div forbedringer: POSuid på debitor, mailvalg ved nyt password, BC-ID fallback (08-09-26 09:52)
En blanding af mindre forbedringer og rettelser på tværs af debitorstamdata,
FlexPos-integrationen, bankfileksport, brugeradministration og bilagsgodkendelse.

---

Debitor — nyt felt POSuid


`FILE/Debitor.PTD`

  • Nyt felt **POSuid** (BString, længde 100) på debitoren, så en debitor kan bære
det UID, kassesystemet identificerer kunden med.
  • Ny nøgle **POSuid** med segmenterne `POSuid` + `Kontonr`, så feltet kan bruges
direkte som opslagsnøgle. `Kontonr` som andet segment gør nøglen unik, også
hvis flere debitorer skulle ende med samme POSuid.

FlexPos — UID flyttet fra Bemærk3 til POSuid


`TASK/FlexPosAPI_Customer.PTD`

FlexPos-kundens UID blev hidtil gemt i `Debitor.Bemærk3` — et generelt notatfelt,
der ligger frit redigerbart på debitorkortet sammen med Bemærk1 og Bemærk2.
Et forkert tastetryk dér kunne afkoble debitoren fra sin FlexPos-kunde.

UID'et genereres og gemmes nu i `Debitor.POSuid`, som både er dedikeret til
formålet og har en nøgle. `Bemærk3` er dermed frigivet til sit egentlige brug.

FlexPos — find debitor på POSuid


`TASK/FlexPosApi_SalgBon.PTD`

Kæden, der finder debitoren til en bon, har hidtil kun kunnet slå op i
`FlexPos_Customer`. Rammer `Customer_UID` ikke en kunde dér, blev bonnen sendt
videre til afdelingens standarddebitor, selvom kunden godt kunne findes i
KeyBalance.

Opslagsrækkefølgen er nu:

1. `FlexPos_Customer.ID1` på `Customer_UID` (uændret)
2. **`Debitor.POSuid` på `Customer_UID`** (ny)
3. `FlexPos_CUnit_ID` på ClientID + Unit_ID
4. `FlexPos_Setup.DKontonr` som sidste udvej

Fil-varianten `FlexPos_SalgBon` er bevidst ikke rørt — FlexPos uden API er
under udfasning, og ny funktionalitet lægges kun i API-varianten.

Nyt password — vælg hvordan mailen sendes


`TASK/Bruger_NytPassword.ptd`

  • Ny parameter **SendeType** med valgene *Send direkte* og *Send via Outlook*.
  • Tasken har nu to `SMTPSENDMAIL`-blokke styret af `ShouldExecute`:
direkte SMTP-afsendelse, eller `MailType = Mapi`.

Med Outlook-valget popper mailen op i et åbent Outlook-vindue i stedet for at
blive sendt afsted med det samme. Dermed kan koden læses på skærmen og
videregives ad anden vej — fx til den, der skal instruere brugeren — inden
mailen eventuelt sendes.

Tidligere kørte den eneste blok altid (`ShouldExecute( 1 )`).

Bankfileksport — Id-tag faldt tilbage til tom værdi


`TASK/EXPORT_BANK_ISO20022_Fil.PTD`

`Id`-tagget under afsenderidentifikationen blev udfyldt ud fra bankcentralen
(BANKDATA/SDC → `BC_Funktion`, BEC → `00` + SE-nr). Var det pågældende felt ikke
udfyldt — eller var bankcentralen en anden — returnerede beregningen ingenting,
og filen kom afsted med et tomt `Id`, som banken afviser.

Betingelserne kræver nu, at værdien rent faktisk findes, og der er tilføjet en
generel fallback til firmaets SE-nr, så tagget altid får indhold.

Bilagsgodkendelse — versalufølsom sammenligning


`TASK/BS_GodkendEgneUdv.PTD`

`CanEnter` sammenlignede `BS_Bilag_Godkend.Godkender` direkte med `user()`.
Er godkenderen registreret med anden bogstavskasse end brugerens login, kunne
brugeren ikke åbne sine egne bilag. Sammenligningen er nu pakket i `toupper()`
i begge sider.

Bemærk: gruppeopslaget i samme udtryk
(`lookup(Medarbejder.BS_GodkGrp;1;user()) == BS_Bilag_Godkend.Godkender`)
er stadig versalfølsomt — det er bevidst ikke rørt her, da det sammenligner en
godkendergruppe og ikke et brugernavn.

---

Til gennemsyn — eksisterende data


Flytningen af FlexPos-UID fra `Bemærk3` til `POSuid` rammer kun nye debitorer
af sig selv. Debitorer, der **allerede** er synkroniseret til FlexPos, har deres
UID liggende i `Bemærk3` og har tom `POSuid`. Kører `FlexPosAPI_Customer` på
dem, får de tildelt et nyt guid og oprettes som **nye** kunder i FlexPos ved
siden af de eksisterende.

Inden dette rulles ud på en installation med data i FlexPos, skal eksisterende
værdier derfor kopieres fra `Bemærk3` til `POSuid`.

#1454 - Outlook Plugin: skrivbare tasks til KundeEmne og KontaktPerson (01-09-26 20:16)

Formål


KB Outlook Plugin (Standard V1) kunne indtil nu kun læse stamdata på
KundeEmne og KontaktPerson via `API_OP_S1_KE` og `API_OP_S1_KP`.
Denne PR tilføjer to skrivbare søster-tasks, så stamdata kan rettes
direkte fra Outlook uden at skifte over i klienten.

TASK/API_OP_S1_KERW.ptd (ny)


Skrivbar task på `KundeEmne` — `TaskMode = Update`.

Kolonner: Kontonr, Navn, Adr1, PostNr, ByNavn, Land, Tlf, EmailDomæne.

Modsat `API_OP_S1_KE` er der ingen subtasks (Debitorpost/SFaktura),
da RW-tasken kun bruges til redigering af selve stamkortet.

TASK/API_OP_S1_KPRW.ptd (ny)


Skrivbar task på `KontaktPerson` — `TaskMode = Update`.

Kolonner: Kontonr, Initial, Navn, Titel, Email, Tlf.

`Initial` er med her, men ikke i læse-tasken `API_OP_S1_KP`. Feltet er
andet nøglesegment i primærnøglen `Kunde` (Kontonr + Initial), jf.
`FILE/KontaktPerson.PTD`, og skal derfor kunne sættes ved oprettelse.

Bemærkninger


  • Dialogens `Title` i `API_OP_S1_KPRW` var kopieret med fra KERW og stod
som `"KundeEmne"`. Rettet til `"KontaktPerson"`.
  • `API_OP_S1_KPRW` har bevidst ikke læse-taskens `SelectList` med
`Fratrådt = false`, så også fratrådte kontaktpersoner kan rettes.
  • Taskene indgår ikke i hovedmenuen og registreres derfor ikke i MODULES,
på linje med de eksisterende `API_OP_S1_*`-tasks.

#1452 - Bankafstemning: gem original bankpost + korrekt valutaindlaesning fra MIB (01-09-26 19:21)

Forbedring af bankafstemning


Original bankpost gemmes ved indlæsning, og valutaoplysninger indlæses nu korrekt fra MIB.

FILE/BankPostAfstem.PTD


  • Nyt felt `OriginalRecord` (BString, 15000) til at gemme den rå post, som den kom
fra banken (json/xml). Gør det muligt bagefter at se præcis hvad banken leverede,
når en afstemning ikke går op, uden at skulle hente posten igen.

TASK/Bank_MIB_TransHent.ptd


  • Rettet tagnavne i MIB-svaret fra camelCase til snake_case:
`currencyExchange[0].exchangeRate` → `currency_exchange[0].exchange_rate`.
De gamle navne matchede ikke MIB's faktiske JSON, så kursen blev aldrig fundet
og org.valuta-felterne forblev tomme.
  • `OrgValuta` læses nu fra `currency_exchange[0].source_currency` (med array-indeks)
og sættes inde i kurs-betingelsen. Den tidligere sti
`currencyExchange.sourceCurrency` manglede indeks og kunne derfor ikke resolve.
  • `BeløbOrgVal` ganges med 100, så beregningen følger kurskonventionen pr. 100
enheder, som `KursOrgVal` bruges med i resten af systemet.
  • Fjernet dobbelt debug-`okmsg()` på samme kurs, så der kun logges én gang.
  • Ny EXPRESSION i AfterRecord gemmer hele transaktionen i `OriginalRecord`.

TASK/Bank_Ng_TransHent.PTD


  • Ny EXPRESSION i AfterRecord gemmer hele transaktionen (`transactions.booked[n]`)
i `OriginalRecord`, svarende til MIB.

Bemærk til senere


`Bank_Ng_TransHent` bruger fortsat de gamle camelCase-tagnavne og ganger ikke med
100 ved beregning af `BeløbOrgVal`. Det er ikke ændret her, da denne PR kun
retter MIB-siden, men det bør efterprøves mod Nordeas faktiske svar.

#1451 - Udvidelse af promptexpr() hintexpr() taget fra Vitrex (01-09-26 18:20)
#1448 - Oversigt valuta sum / hvis ikke standard valuta eller "". (01-09-26 18:18)
#1379 - Peppol BIS 3: reelle EDI-ID'er og bankkonto pr. valuta, adresser på ISO20022 og Outlook API-backend (27-08-26 19:56)
Fire områder i denne PR: Peppol-eksporten er lagt om til de reelle EDI-ID'er og bankkonto pr. valuta, Debitor leverer nu rigtige Peppol-scheme-koder, modtageradressen kommer med på alle ISO20022-betalingsformater, og første step af API-backenden til Outlook-pluginnet er på plads.

PEPPOL BIS 3 (TASK/UDSKRIVFAKTURA_PEPPOL_BIS_3.ptd)


  • **Køber-ID kommer nu fra kundekortet.** `$IVSchemeVal`/`$IVSchemeId` slås op i `Debitor.EDIReeltID` og `Debitor.EDIReeltIDArt` i stedet for den lokale EAN/SE_nr-logik med hårdkodede scheme-koder pr. land. Den gamle kode sendte bl.a. det forældede 9901 for DK, og fallback-grenen havde identisk `then`/`else`.
  • **Afsender-ID uden landepræfiks.** `cbc:EndpointID`, `cac:PartyIdentification/cbc:ID` og `cac:PartyLegalEntity/cbc:CompanyID` sendes nu som rent org.nr., hvilket er det scheme 0007 (SE) og 0192 (NO) forventer. Landekoden lægges i stedet på `cac:PartyTaxScheme/cbc:CompanyID` (BT-31), hvor den hører til. Testet mod svensk validering.
  • **Ny IBAN-betalingsblok.** `cac:PaymentMeans` med kode 30 (credit transfer), `cbc:PaymentID`, IBAN, kontonavn og SWIFT. De fire gamle NO-varianter (`KontoNO`, `IBANNO_STD`, `IBANNO`, `KontoNO_ARK`) er sat til `Enable( 0 )`.
  • **Bankkonto findes ud fra valuta.** Alle opslag i Bankkonti bruger nu nøglen `Bankkonti.BTextValuta` i stedet for primærnøglen (Navn), så kontoen vælges ud fra fakturaens valuta og ikke bankkontoens navn — som feltets hjælpetekst også beskriver.
  • **Faktura og kreditnota er bragt i sync.** Begge grene har nu samme IBAN-blok og samme landekode på VAT-nummeret; tidligere afveg kreditnotaen på begge punkter.

Filen er reformateret af editoren undervejs, så langt de fleste diff-linjer er whitespace og klammer omkring enkelt-statement `if`'er uden funktionel betydning.

Debitor: Peppol-scheme-koder (FILE/Debitor.PTD)


  • `EDIReeltIDArt` returnerer nu rigtige koder for EHF3-, PEPPOL3- og OIOUBL3-kunder: **0184** for DK og **0007** for SE, hvor der før stod `"xxx"`.
  • `EDIReeltID` returnerer CVR ved 0184, og ved 0007 renses det svenske org.nr for bindestreger og `SE`-præfiks.

Også her er resten af diffen reformatering; de reelle ændringer er de to `Init`-udtryk.

ISO20022: modtageradresse på alle formater (TASK/EXPORT_BANK_ISO20022_Fil.PTD)


Gade, postnummer og bynavn på modtageren blev kun udfyldt ved IBAN-betalinger — linjerne var udkommenteret i de øvrige grene. De er nu aktive for **FIK/Giro**, **Overførsel** og **SWIFT** også, så adressen følger med uanset betalingsform.

Outlook-plugin: API-backend, første step (TASK/API_OutLook_KE.ptd, TASK/API_OutLook_KP.ptd)


To nye tasks der eksponerer de data pluginnet skal vise:

  • **API_OutLook_KE** — KundeEmne med navn, adresse, land, SE-nr., telefon, e-mail og e-maildomæne. Subtasks henter kundens fakturaer (`SalgKøbProd` 0 og 10..29) med dato, valuta, netto og brutto, samt debitorposter med dato, tekst, beløb i valuta og åbent beløb.
  • **API_OutLook_KP** — aktive kontaktpersoner (`Fratrådt = false`) med initialer, navn, e-mail, titel samt fastnet- og mobilnummer.

Test


`KBRebuild -IPTD` på alle fem ændrede filer kompilerer uden fejl (`done OK`). Peppol-outputtet er kontrolleret mod svensk validering.

#1334 - Tilføj Azure DevOps MCP-server til Claude Code (25-08-26 11:06)
Giver Claude Code direkte adgang til PR'er, kommentartråde og build-logs, så
fejlsøgning på en PR ikke kræver manuel kopiering fra webfladen.

Baggrunden er arbejdet med PR 1332: hele undersøgelsen af hvorfor review-bottens
JSON blev postet råt måtte foregå uden adgang til selve PR'en, fordi hverken
`az devops` eller anonym REST kunne læse den.

Hvad der tilføjes


`.mcp.json` i repo-roden med den officielle server `@azure-devops/mcp` (v2.9.0)
mod organisationen KeyBalance, samt en linje i `CLAUDE.md` der nævner serveren.

Valg der er truffet


**Kun tre domæner slået til:** `core`, `repositories` og `pipelines`. Serveren
loader som standard alle domæner (også work-items, wiki, search, test-plans og
advanced-security), og hvert værktøjs schema fylder i konteksten i hver eneste
session. De tre giver de 18 værktøjer vi reelt bruger — herunder
`repo_pull_request_thread` og `pipelines_build_log`. Listen kan udvides ved at
rette `args`.

**Interaktivt browser-login (serverens standard).** Ingen PAT gemmes i repoet,
og hver udvikler logger ind som sig selv første gang serveren bruges.
`-a azcli` blev fravalgt: token fra en almindelig `az login` afvises af
organisationen med TF400813.

**Ingen hemmeligheder i konfigurationen.** Eneste `env` er `ado_mcp_project`,
som blot er projektnavnet, så værktøjerne ikke behøver spørge.

For dem der henter ændringen


Serveren starter ikke af sig selv. Projekt-scopede `.mcp.json`-servere kræver
eksplicit godkendelse ved opstart af Claude Code — det er den normale
sikkerhedsspærre for MCP-konfiguration der kommer med et repo. Efter
godkendelse åbner første værktøjskald et browser-login mod
`dev.azure.com/KeyBalance`.

Verifikation


`initialize`-handshake mod serveren svarer (Azure DevOps MCP Server 2.9.0), og
de tre domæner parses som forventet. Efterfølgende brugt i praksis til at læse
review-trådene på PR 1332 og svare på dem.
#1408 - Navngivning FakturaTil (25-08-26 10:06)
#1384 - Div småting fra opgradering (21-08-26 15:11)
Div småting fra opgradering
#1332 - Claude PR review: robust JSON-parsing i stedet for raa dump i PR'en (14-08-26 12:17)
Claude PR review: robust JSON-parsing i stedet for raa dump i PR'en

Nogle PR'er (fx 1313 og 1328) fik hele review-JSON'en postet raat ind i
PR-kommentaren i stedet for den formaterede opsummering.

Aarsagen var oprydningen foer ConvertFrom-Json: den strippede kun en
markdown-fence der laa PRAECIS i start og slut af svaret. Skrev modellen
en indledning ("Her er reviewet:") eller en afsluttende bemaerkning, slog
parsingen fejl, og fallbacken postede $raw direkte. Samme udfald ved
afkortede svar og ved trailing comma. Reproduceret under PowerShell 5.1.

Vaerst af alt gjorde fallbacken "exit 0" med en lukket traad: ingen
inline-fund, ingen impact-vurdering, og PR'en gled igennem porten uden at
nogen havde set paa den.

Aendringer:

  • Get-ReviewJson: proever flere kandidater - hele svaret, indhold i
```json-fences uanset placering, og foerste balancerede {...}-blok med
en scanner der ignorerer klammer inde i strenge. Trailing comma
ryddes kun op som sidste udvej, saa strenge ikke korrumperes.
  • Invoke-Claude: --output-format json giver en fast envelope, saa stoej
paa CLI'ens stdout ikke kan blande sig ind i review-teksten. Logger
samtidig subtype, is_error, stop_reason og afviste tool-kald.
  • Ét reparationsforsoeg med haiku naar udtraekket fejler - daekker
afkortede svar, som ingen udtraeksregel kan redde.
  • Uparsbart svar dumpes ikke laengere raat. Der postes en kort besked i
en AKTIV traad, saa PR'en holdes tilbage til manuel gennemgang. Det
raa svar vises afkortet i en kodeblok og ligger som artefakt.
  • Get-Content laeser eksplicit med -Encoding UTF8.
  • prompt.md: bed om maks. 12 findings og korte bodies for at mindske
risikoen for afkortede svar.

Verificeret under Windows PowerShell 5.1: alle steps parser, 10
udtraeks-cases giver forventet resultat, og et rigtigt CLI-kald med
prosa foer og efter fencen parses nu korrekt.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
#1328 - Små rettelser Indkøb / bilag (14-08-26 10:34)
Kontroller flyttet til task, der kan udvides - på sigt evt. ændres til system opsætning.
Kørt og testet hos Helsinge (m. Gitte).
#1322 - Div småting opsamlet ved opgradering (14-08-26 07:59)
Div småting opsamlet ved opgradering
#1313 - ISO20022 PAIN.001 export som manuel fil (uden BankConnect) + 2026 adresseformat (13-08-26 11:27)

ISO20022 PAIN.001 export som manuel fil (uden BankConnect)


Hovedformålet er at gøre det muligt at danne en ISO20022 PAIN.001-betalingsfil **manuelt** — dvs. filen gemmes lokalt på pc'en og indlæses selv i netbanken — i stedet for kun at kunne sendes via BankConnect. Samtidig er adresseblokkene bragt på det format bankerne kræver fra 2026 (struktureret adresse).

EXPORT_BANK_ISO20022_Fil
  • Ny parameter `Lokalt` (BBool). Når den er sat, skrives filen client-side (`FilesServerSide` returnerer false) i stedet for på serveren. `Path` og `Fil` er nu synlige i startdialogen.
  • Formularlog er omlagt: `FormularerLog` oprettes nu via ny subtask `CreateFormuarLog` i AfterLast i stedet for via `Links`/`LinkMode = Create`. Logteksten bygges i `$FormularTxt` (MsgId, kontrolantal, kontrolbeløb).
  • Ved manuel kørsel (uden indgående `#FormularLøbenr`) oprettes formularen som afsluttet med teksten `(Lukket) Betalingsforslag - ISO20022 PAIN01 Fil`, og `KBHYdre.ErOverførtTilBank` sættes.
  • Rettet `ShouldExecute( !#FormularLøbenr )` → `!$FormularLøbenr` på kaldet til `CreateFormuar`.

**Adresser (2026-format):**
  • `$ModtAdr1`/`$ModtAdr2` er erstattet af struktureret `$ModtGade`, `$ModtPostNr`, `$ModtByNavn` → `PstCd`, `TwnNm`, `Ctry`, `AdrLine`.
  • Modtagerens `PstlAdr` udfyldes kun hvis adressen faktisk findes (`Enable( $ModtByNavn )`), og kun for udenlandske betalingsformer (IBAN og Swift). For FIK/Giro og indenlandsk overførsel udelades adresseblokken.
  • Afsender (`InitgPty` / debitor) får nu fuld `PstlAdr` med `PstCd`, `TwnNm`, `Ctry` og `AdrLine` fra FSetup/Firma. Den overflødige `PstlAdr` under bankens `FinInstnId` er fjernet begge steder.

**Valuta:**
  • `$BetalValISO` slås nu op som `lookup(Valuta.ISO4217_A3; 1; KBetForHistLinier.Valuta)` i stedet for at bruge den interne valutakode direkte — filen indeholdt før en kode banken ikke kunne godtage.

KBetForHistHeadDlg
  • Ny handling **"> ISO20022 (FIL)"**, der kalder `EXPORT_BANK_ISO20022_Fil` med path `Export\Bank\`, filnavn `<løbenr>.xml` og `Lokalt = true`. `CanExecute` blokerer, hvis betalingsforslaget allerede er eksporteret.

EXPORT_TILBANK
  • ISO20022 (format 20) er fjernet fra det gamle CSV-eksportvalg sammen med parameteren `FileMappe` — ISO20022 køres nu enten via BankConnect eller via den nye filhandling. Beskrivelsen præciserer, at de gamle CSV-formater er på vej ud hos bankerne.

EXPORT_BANK_ISO20022_Samlet
  • Sender `false` med som ny `Lokalt`-parameter, så BankConnect-flowet uændret gemmer serverside.

Øvrige rettelser i denne branch
  • **Import_BankConnect_camt_053_001**: fakturanr udtrækkes nu efter samme strategi som FIK og accepterer både `71`- og `75`-præfiks; udtrækket er forenklet til `substring()`.
  • **MailF_SendAbn**: tomme eller ugyldige medarbejder-mailadresser falder tilbage til firmaets e-mail (`emailcheck`), i stedet for at fejle med "ingen modtager".
  • **BS_AF_IOrdreTotal**: bedre logtekst med brutto-beløb fra BS_Bilag og indkøbsordre.
  • Rettet manglende afsluttende `}` i den nye WVAction, som ville have brudt buildet.

#1311 - Rettelser fra Lasses noter (13-08-26 10:01)