# Kanban model in a console A console program that uses `TAtlasKanbanModel` without any window, to show that the Kanban data model is independent of the board control. It: 1. builds a board of four columns, one of them with a work-in-progress limit of 2, and four cards, and counts the `OnChange` notifications; 2. shows that duplicate ids, a full column, a destination index out of range and an unknown card are all refused with `EAtlasKanban`, and that the board is unchanged afterwards; 3. moves cards with a `BeforeMove` rule (cards enter Done only from Review), shows a vetoed move returning `False`, reorders a card inside its column with an explicit index, and shows that the callback cannot change the board while a move is in progress; 4. saves the board with `ToJSON`, loads it into a second model, and shows that a wrong schema, text that is not JSON and a card without a `detail` field are refused without touching the existing board; 5. replaces a card to change its title (there is no rename), removes a card, and clears the board by loading an empty document. Every step checks its own result. The program prints what it did and exits with code 0 when all checks pass, or prints the failed check and exits with code 1. It needs no input, files or network. ## Build and run Open `KanbanModelConsole.dpr` in Delphi 13; the IDE creates the project file. Add the Atlas UI `src` folder and the Atlas VCL `src` folder to the project's search path, then build and run for Win32 or Win64. No packages need to be installed. The program needs no input. It checks its own results and stops with an error if any of them differs from the output below. Only `Atlas.Kanban` is used; the model itself needs no form, although the unit links the VCL because the board control lives in the same unit. ## Expected output ``` Building the board To do (2) order-42: Prepare customer order invoice-7: Send invoice 7 In progress (2/2) audit: Stock audit catalog: Update the catalog Review (0) Done (0) ok: four columns, two cards waiting ok: OnChange fired once per column and card Validation ok: duplicate column id refused ok: duplicate card id refused ok: work limit refuses a third card ok: work limit refuses a move into a full column ok: destination index out of range ok: unknown card refused ok: refused operations leave the board unchanged Moving cards ok: audit goes to review ok: BeforeMove cannot mutate the board ok: the freed slot accepts order-42 ok: veto: catalog cannot skip review ok: vetoed card stays where it was ok: audit may finish from review ok: explicit index reorders inside a column ok: order-42 is first in progress ok: a move to the same place succeeds ok: only real moves fire OnChange To do (1) invoice-7: Send invoice 7 In progress (2/2) order-42: Prepare customer order catalog: Update the catalog Review (0) Done (1) audit: Stock audit JSON round trip {"schema":1,"columns":[{"id":"todo","title":"To do","limit":0,"cards":[{"id":"invoice-7","title":"Send invoice 7","detail":""}]},{"id":"active","title":"In progress","limit":2,"cards":[{"id":"order-42","title":"Prepare customer order","detail":"Pick, pack and label"},{"id":"catalog","title":"Update the catalog","detail":""}]},{"id":"review","title":"Review","limit":0,"cards":[]},{"id":"done","title":"Done","limit":0,"cards":[{"id":"audit","title":"Stock audit","detail":""}]}]} ok: a second model loads the same board ok: unknown schema refused ok: invalid text refused ok: a card without "detail" fails in the JSON reader ok: failed imports leave the board intact Editing and clearing ok: the replacement goes back to the top ok: same id, new title and detail ok: removed card is gone ok: loading an empty document clears the board All checks passed. ``` Six moves are attempted in "Moving cards" but only four fire `OnChange`: the vetoed move changes nothing, and the last move puts `order-42` where it already is, which `MoveCard` reports as success without a notification. A missing JSON field raises the RTL's `EJSONException` rather than `EAtlasKanban`, so code that loads boards from files should catch both. ## Adapting it - Replace `TRules.BeforeMove` with your own rule. It must only read the model: adding, removing or moving cards there raises `EAtlasKanban` (`Cannot mutate the board during a move callback`). - Save `ToJSON` to a file or a database column and restore it with `LoadJSON`; the text is plain UTF-16 in memory, so choose the encoding when you write it (UTF-8 is a good default). - To show the same model on screen, assign it to a `TAtlasKanban` board's `Model`; see the [Kanban board](https://youseful.software/delphi/projects/atlas-ui-kanbanboard.html) sample.