Package Manager
De Package Manager is het versiebeheer- en distributiemechanisme voor alle UCT-aanpassingen. Pakketten worden gebruikt om configuratiewijzigingen te transporteren tussen Ultimo-omgevingen in een OTAP-straat (Ontwikkeling, Test, Acceptatie, Productie).
Gerelateerd: uct-overzicht, screens, workflows/workflow-engine
Locatie in UCTbewerken
UCT > Package Manager
Schermindelingbewerken
Navigatieboom (links)bewerken
Categorieën: Entities, Workflows, Business Rules, System Configuration, Agenda Integration, Development.
Pakkettenlijst (midden)bewerken
| Kolom | Beschrijving |
|---|---|
| Name | Bestandsnaam (vaak met datumprefix) |
| Valid | Of het pakket geldig/gevalideerd is |
| Title | Korte beschrijving van het pakketdoel |
| Description | Uitgebreidere beschrijving |
| Revision | Revisienummer |
| Merged | Of het pakket is samengevoegd met de omgeving |
| Custom code | Of het pakket aangepaste code bevat |
| Date | Aanmaak-/uploaddatum |
Detailpaneel (rechts)bewerken
- General tab — Name, Description, Ultimo Revision Base, Custom code, notities
- Info tab — Technische bestandsgegevens
Werkwijzebewerken
Pakket aanmakenbewerken
- Maak configuratiewijzigingen in de UCT (O-omgeving)
- Exporteer de wijzigingen als pakket via Package Manager
- Geef het pakket een beschrijvende naam en titel
Pakket importerenbewerken
- Upload het pakket naar de doelomgeving (T/A/P)
- Controleer de Ultimo Revision Base — deze moet overeenkomen met de doelomgeving
- Importeer en controleer de Merged-status
Praktische tipsbewerken
- Naamgeving: Gebruik altijd een beschrijvende naam (bijv.
2026-03-15_JobScreenAanpassing_KlantX) - Revision Base: Als de revisie van de doelomgeving afwijkt van de pakketbasis, kunnen er conflicten ontstaan
- Controleer na import: Verifieer altijd de Merged-status
- Custom code: Pakketten met custom code vereisen extra aandacht bij upgrades
- Documenteer: Leg vast welke pakketten naar welke omgevingen zijn gepromoveerd
Valkuil: Importeer nooit een pakket rechtstreeks naar productie zonder eerst te testen in acceptatie. De OTAP-straat bestaat niet voor niets.
Stap-voor-stap: Pakket aanmaken en opnemenbewerken
1. Nieuw pakket aanmakenbewerken
- Open Package Manager via het UCT-hoofdmenu
- Klik Add (Ctrl+Alt+N) in de toolbar boven de pakkettenlijst
- Klik Edit (Ctrl+Alt+E) in het detailpaneel
- Vul de velden in:
- Title — Beschrijvende naam (bijv. "JobScreenAanpassing_KlantX")
- Customer reference — Referentie van de klant
- Ultimo reference — Referentie van Ultimo
- Remarks — Aanvullende opmerkingen
- Klik Save (Ctrl+Alt+S)
2. Opname starten (recording)bewerken
- Selecteer het pakket in de lijst
- Klik Start recording — het rode opname-icoon verschijnt rechtsboven in de navigatiebalk
- De pakketregel krijgt een rode balk aan de linkerzijde en vetgedrukte tekst
- Voer nu configuratiewijzigingen uit in de UCT
Acties die automatisch worden opgenomen:
- Gebruikers aanmaken/wijzigen (scherm Users)
- Groepen aanmaken/wijzigen (scherm Groups)
- Wijzigingen aan de Application Element Tree
- Menuwijzigingen (Menu Designer)
- Schermregistraties toevoegen/wijzigen (Screens)
- Explorers en Explorer Links wijzigen
- Master Data Setup kopieeracties
- Text Templates wijzigen
- Workflow Scheduler wijzigingen
Bestanden die handmatig worden toegevoegd:
- Screen files — bij het publiceren van een scherm in de Screen Designer
- Workflow files — bij het publiceren van een workflow in de Workflow Designer
Let op: Nieuwe workflows of wijzigingen aan bestaande workflows worden NIET automatisch opgenomen. Je moet de workflow-bestanden apart overdragen of ze publiceren naar het pakket.
3. Opname pauzeren/hervattenbewerken
- Klik Pause recording om tijdelijk te stoppen (icoon verandert)
- Klik Resume recording om door te gaan
- Je kunt ook via het rode icoon rechtsboven in de navigatiebalk pauzeren/hervatten
4. Opname stoppenbewerken
- Open de Package Manager
- Selecteer het opnamepakket
- Klik Stop recording
- Als bestanden out-of-sync zijn verschijnt een dialoog; klik Synchronise om bij te werken
5. Bestanden in het pakket controlerenbewerken
- Ga naar het tabblad Files in het detailpaneel
- Klik Validate files om te controleren of bestanden in het pakket overeenkomen met de omgeving
- Bij een afwijking verschijnt het icoon "Out of sync" — klik Synchronise om bij te werken
Stap-voor-stap: Pakket transporterenbewerken
Downloadenbewerken
- Selecteer het pakket in de Package Manager
- Klik Download (Ctrl+Alt+D) — het .up-bestand wordt gedownload
- Bewaar het bestand op een veilige locatie
Let op: Wijzig nooit de extensie (.up) van het pakketbestand.
Uploadenbewerken
- Open de Package Manager in de doelomgeving
- Klik Upload (Ctrl+Alt+U)
- Klik Select en kies het .up-bestand
- Klik OK — het pakket verschijnt in de lijst
Stap-voor-stap: Pakket validerenbewerken
- Selecteer het pakket (moet een opname bevatten en Revertible zijn)
- Klik Validate in het detailpaneel
- Bij succes: melding "validation succeeded without conflicts"
- Bij conflicten: waarschuwing met de specifieke issues
Tip: Valideer altijd voor het toepassen. Conflicten kunnen optreden bij afwijkende databasestructuren of ontbrekende afhankelijkheden.
Stap-voor-stap: Pakket toepassen (Apply)bewerken
- Selecteer het pakket
- Klik Apply in het detailpaneel
- Bij succes: bevestigingsdialoog
- Bij fouten: foutmelding met details
- Na toepassen wordt de knop Revert beschikbaar
Stap-voor-stap: Pakket terugdraaien (Revert)bewerken
- Selecteer het toegepaste pakket
- Klik Revert in het detailpaneel
- Alle acties worden ongedaan gemaakt
Waarschuwing: Als het pakket de bestanden
applicationelement.appelenapplicationstructure.appstrubevat, wordt de AET naar de factory default teruggezet!
Pakketten samenvoegen (Merge)bewerken
- Selecteer meerdere pakketten (Ctrl+klik)
- Klik Merge selected packages
- Controleer de volgorde (de selectievolgorde bepaalt de mergevolgorde)
- Klik OK
Het samengevoegde pakket bevat de acties van alle bronpakketten in de opgegeven volgorde.
Pakketbestandenbewerken
Elk pakket bestaat uit twee bestanden in de map FileServiceData/Packages:
| Extensie | Beschrijving |
|---|---|
| .up | Pakketinhoud die kan worden toegepast |
| .rup | Rollback-bestand voor het terugdraaien |
Het .rup-bestand wordt aangemaakt bij opname of bij het toepassen van een geupload pakket.
Technische structuur van een .up-bestandbewerken
Een .up-bestand is een standaard ZIP-archief met de volgende structuur:
PackageDefinition.xml
FileServiceData/
Mobile/TechnicalService/Menu/UserContent_Menu.mnm
Mobile/TechnicalService/Screens/UserContent_Job.scm
Workflows/UserContent_MyWorkflow_Pre.wfl
...
PackageDefinition.xmlbewerken
Het manifestbestand dat de package beschrijft. Moet beginnen met een UTF-8 BOM (EF BB BF), anders weigert Ultimo de import met de fout: "Invalid BOM for package definition".
Minimaal voorbeeld (alleen bestanden transporteren):
<Package Id="UNIEKE-ID" Customer="Klantnaam" OriginLocation="https://env.ultimo.net" OriginDTAP="Development" CreateDate="2026-04-14 13:00:00Z" UserId="gebruiker" EmployeeDescription="omschrijving" Title="pakkettitel" Owner="EIGENAAR">
<Section Id="1000" Description="Beschrijving" CreateDate="2026-04-14T13:00:00" />
</Package>
De PackageDefinition kan ook acties bevatten, zoals gebruikerswijzigingen of parametersettings:
<Section Id="1000" Description="Default" CreateDate="2026-04-14T13:00:00">
<User BlockNumber="1" Action="Update" Id="USERID">
<Authorization Action="Remove" Id="GROEPID" />
</User>
<Parameters BlockNumber="2" Scope="Group:GROEP">
<Parameter Action="Set" Id="Ultimo.GoPlus" Value="True" />
</Parameters>
</Section>
Beperkingenbewerken
| Beperking | Waarde | Foutmelding |
|---|---|---|
Bestandsnaam .up |
Max 34 tekens | "Input string too long for column 'pacfilename'" |
| BOM op PackageDefinition.xml | UTF-8 BOM verplicht | "Invalid BOM for package definition" |
Hash-attribuut op <Workflow> |
Verplicht, SHA1 over content zonder BOM en zonder Hash-attribuut | "Workflow ' |
FileServiceData mapstructuurbewerken
Bestanden in FileServiceData/ worden bij import naar de Ultimo File Service geschreven. De mapnamen gebruiken PascalCase:
| Pad | Inhoud |
|---|---|
Mobile/<App>/Menu/ |
Go menu-bestanden (.mnm) |
Mobile/<App>/Screens/ |
Go schermbestanden (.scm) |
Mobile/<App>/Dataset/ |
Go datasets (.lsm) |
Mobile/<App>/Entity/ |
Go entity templates (.ety) |
Workflows/ |
Workflow-bestanden (.wfl) |
Waarbij <App> bijvoorbeeld TechnicalService, SelfService, InformationTechnology of Default is.
Workflow hash-attribuutbewerken
Elke .wfl in een package moet op de <Workflow>-root een Hash="..."-attribuut bevatten met een SHA1 over de eigen content. Klopt dit niet, dan weigert Ultimo het bestand zowel bij import als bij openen in de Workflow Designer met:
WorkflowException (0x10005013): Workflow_RunDesigner ... Workflow '<naam>' was edited with an unauthorized tool
Algoritme (reverse-engineered, round-trip geverifieerd op 2026-05-19):
- SHA1 van de UTF-8 bytes van het
.wfl-bestand - zonder BOM — de eerste drie bytes (
EF BB BF) overslaan vóór hashen - zonder het
Hash="..."-attribuut zelf — patroonHash="[^"]*"\s+één keer verwijderen vóór hashen (inclusief de spatie erna) - Resultaat: 40-character hex, uppercase
PowerShell-implementatie:
function Get-WorkflowHash {
param([string]$Path)
$bytes = [System.IO.File]::ReadAllBytes($Path)
if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) {
$bytes = $bytes[3..($bytes.Length - 1)]
}
$content = [System.Text.Encoding]::UTF8.GetString($bytes)
$contentNoHash = [regex]::Replace($content, 'Hash="[^"]*"\s+', '', 1)
$sha1 = [System.Security.Cryptography.SHA1]::Create()
$hashBytes = $sha1.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($contentNoHash))
return ($hashBytes | ForEach-Object { $_.ToString("X2") }) -join ""
}
Werkwijze voor een nieuwe of buiten-Ultimo bewerkte .wfl:
- Schrijf het bestand met
<Workflow Hash="" Version="..." ...>(lege placeholder; spatie erna behouden zodat de regex blijft kloppen na injectie). - Bereken de hash met de functie hierboven.
- Vervang
Hash=""doorHash="<computed>". - Schrijf terug met UTF-8 BOM en CRLF line-endings (consistent met de Workflow Designer-output).
- Round-trip-test: hash opnieuw berekenen → moet exact gelijk zijn aan het opgeslagen
Hash-attribuut. Slaagt deze niet, dan staat de spatie na het Hash-attribuut waarschijnlijk verkeerd, of zit er een BOM-byte mee in de hash-input.
Wanneer is dit nodig? Workflows die je via de Workflow Designer in UCT publiceert krijgen automatisch een geldige hash — daar hoef je niets te doen. Het algoritme hierboven is alleen relevant wanneer je workflow-XML buiten Ultimo om aanmaakt of bewerkt (bv. via scripting, templating of het samenstellen van een
.up-package zonder UCT in de loop).
PackageDefinition.xmlbewerken
Het manifestbestand dat de package beschrijft. Moet beginnen met een UTF-8 BOM (EF BB BF), anders weigert Ultimo de import met de fout: "Invalid BOM for package definition".
Minimaal voorbeeld (alleen bestanden transporteren):
<Package Id="UNIEKE-ID" Customer="Klantnaam" OriginLocation="https://env.ultimo.net" OriginDTAP="Development" CreateDate="2026-04-14 13:00:00Z" UserId="gebruiker" EmployeeDescription="omschrijving" Title="pakkettitel" Owner="EIGENAAR">
<Section Id="1000" Description="Beschrijving" CreateDate="2026-04-14T13:00:00" />
</Package>
De PackageDefinition kan ook acties bevatten, zoals gebruikerswijzigingen of parametersettings:
<Section Id="1000" Description="Default" CreateDate="2026-04-14T13:00:00">
<User BlockNumber="1" Action="Update" Id="USERID">
<Authorization Action="Remove" Id="GROEPID" />
</User>
<Parameters BlockNumber="2" Scope="Group:GROEP">
<Parameter Action="Set" Id="Ultimo.GoPlus" Value="True" />
</Parameters>
</Section>
Beperkingenbewerken
| Beperking | Waarde | Foutmelding |
|---|---|---|
Bestandsnaam .up |
Max 34 tekens | "Input string too long for column 'pacfilename'" |
| BOM op PackageDefinition.xml | UTF-8 BOM verplicht | "Invalid BOM for package definition" |
FileServiceData mapstructuurbewerken
Bestanden in FileServiceData/ worden bij import naar de Ultimo File Service geschreven. De mapnamen gebruiken PascalCase:
| Pad | Inhoud |
|---|---|
Mobile/<App>/Menu/ |
Go menu-bestanden (.mnm) |
Mobile/<App>/Screens/ |
Go schermbestanden (.scm) |
Mobile/<App>/Dataset/ |
Go datasets (.lsm) |
Mobile/<App>/Entity/ |
Go entity templates (.ety) |
Workflows/ |
Workflow-bestanden (.wfl) |
Waarbij <App> bijvoorbeeld TechnicalService, SelfService, InformationTechnology of Default is.
ApiKey-permissies in PackageDefinition.xmlbewerken
Een <ApiKey>-block in PackageDefinition.xml configureert REST-API-rechten zonder ze handmatig in UCT te hoeven prikken. Onderliggende <Resource>-blokken sturen de ApiKeyEntityPermission-records aan, en geneste <Property>-elementen de ApiKeyPropertyPermission-records.
Voorbeeldbewerken
<ApiKey Action="Insert" Id="ESKMAIL" UserId="US0000004" CompanyId="000001"
Status="2" DailyRateLimit="0" DataProvider=""
Description="Eska Inkoop Mail Agent"
CreateDate="2026-04-28T12:00:00" ExpiryDate="2099-01-01"
IsCustom="True" Multilingual="True">
<Resource EntityName="Purchase" AuthorizationLevel="Read">
<Property PropertyName="Description" />
<Property PropertyName="Vendor" />
<Property PropertyName="DeliveryDate" />
</Resource>
<Resource EntityName="PurchaseLine" AuthorizationLevel="Update">
<Property PropertyName="Article" />
<Property PropertyName="DeliveryDate" />
<Property PropertyName="_ConfirmedRecieptDate" />
</Resource>
</ApiKey>
AuthorizationLevel — geldige waardenbewerken
| Waarde | Betekenis |
|---|---|
Read |
Alleen lezen (GET) |
Add |
Read + records aanmaken (POST) |
Update |
Add + records wijzigen (PATCH/PUT) |
Delete |
Update + records verwijderen (DELETE) |
Let op:
ViewenModifywerken niet — geven "Requested value 'View' was not found" / "Requested value 'Modify' was not found". GebruikReadresp.Update.
Implicit properties — NIET listenbewerken
Sommige properties krijg je automatisch met de Resource-permissie en mogen niet expliciet in een <Property>-element staan, anders faalt de import met "Cannot find property with the name 'X' in entity 'Y'".
| Implicit | Voorbeeld |
|---|---|
Id (single primary key) |
Purchase.Id, Vendor.Id, Article.Id |
Id.X (composite-key sub-properties) |
PurchaseLine.Id.LineId, PurchaseLine.Id.Purchase, ReceiptLine.Id.LineId, ReceiptLine.Id.Receipt |
Composite-key Ids verschijnen in lookup_entity() als losse properties (Id.LineId, Id.Purchase), maar in package-XML gelden ze als deel van de primary key — dus listen van Purchase op PurchaseLine of Receipt op ReceiptLine faalt.
Tenant-afhankelijke propertiesbewerken
Niet elke property die lookup_entity() toont bestaat ook in elke tenant. Deze zijn afhankelijk van UCT-instellingen op tabel-niveau:
| Property | Voorwaarde |
|---|---|
RecordChangeDate |
"Track changes" voor die tabel staat aan |
RecordCreateDate |
Idem (vrijwel altijd aan, maar verifieer) |
Bij een tenant waar dit uitstaat: foutmelding "Cannot find property with the name 'RecordChangeDate' in entity 'X'". Verwijder het property-element of zet change-tracking aan in UCT.
ApiKey Id moet uniek zijn per tenantbewerken
Het Id-attribuut op <ApiKey Action="Insert"> moet uniek zijn binnen de doelomgeving. Bij een conflict (vaak met de standaard 0001): "Section 1000 | Block #1 - ApiKey '0001' already exists". Kies een beschrijvende prefix zoals ESKMAIL of ITSM01 om botsing te voorkomen.
Workflow- en filter-permissiesbewerken
Naast <Resource> kent het ApiKey-block ook:
<Workflow WorkflowId="GUID"/>— toegang tot specifieke workflows (ApiKeyWorkflowPermission)<Filter ...>binnen een Resource — record-level filters (ApiKeyEntityFilter)
Pakketindicatorenbewerken
| Kolom | Beschrijving |
|---|---|
| Auto | Automatisch aangemaakt (geen actieve opname) of handmatig opgenomen |
| Revertible | Kan worden teruggedraaid (vinkje) |
| State | Recording-status: Started, Paused, Stopped |
| Current user | Gebruiker die momenteel opneemt |
- Rode balk links = jouw actieve opname
- Oranje balk links = opname door andere gebruiker
Tip: Je kunt een opname van een andere gebruiker overnemen door Start recording te klikken op hun pakket en "Yes" te bevestigen.
Brondatabewerken
Dit artikel is consultant-synthese. Voor ground-truth data over specifieke Ultimo-objecten gebruik de onderstaande tools.
- Entiteit-data —
lookup_entity("<Name>")·lookup_table_schema("<Name>")Alle properties, DB-kolomnamen, triggers en computed columns. Bronnen:Entities.xml,database-schema.json. - Workflows per entiteit —
find_workflows("", entity="<Name>")Alle Before/After Save events en andere ActionFields voor een entiteit. Bron:workflows.xml. - Schermen —
lookup_screen("<ScreenName>")· Schermen index Schermdefinities incl. tabel, autorisatielevel, screen-level. Bron:ultimo_screens_names.xml. - AET-settings / feature toggles —
find_aet_settings(query)· AET index Feature toggles en systeem-configuratie. Bron:ApplicationElementTreeData.json. - Kennisbank-breed zoeken —
search(query)Doorzoekt alle wiki-artikelen, entities, workflows, schermen, templates en ActionFields tegelijk.
Zie ookbewerken
- uct-overzicht — Overzicht van alle UCT-onderdelen
- workflows/workflow-engine — Workflows in pakketten
- screens — Schermpublicaties in pakketten