Deep dive · Semco Maritime × QAECY

Buy the commodity,
build the essentials,
own the model

What to do when the ERP reaches end of support, without buying the next lock-in.

Semco Maritime×CuebyQAECY
01 ERP deep dive · The situation

The ERP is reaching end of support

The usual answer is a new ERP suite. Here is the path that answer takes.

Support endsNo more updates, security fixes or new legal formats.
Select a suiteLong RFP, demos, a shortlist of large vendors.
Fit-gap & customiseProcesses bent to the vendor's model. Gaps closed with custom code.
Migrate & go liveOpen items move. History often stays behind in an archive.
Locked in againThe vendor's data model is now Semco's model, until the next end of support.
…and the cycle starts again

Every customisation is code to redo at the next upgrade, and a reason not to leave.

Engineering, the yard and the field still live outside it. The suite doesn't model a substation.

Your data leaves on the vendor's terms: their export, their format, their price.

01 ERP deep dive · The choice

Two ways out

Replace like for like

  • One vendor's data model becomes Semco's model again
  • Fit-gap, customisation and migration, run as one programme
  • Customisations redone at every major upgrade
  • Exit costs grow every year you stay

Split by what each function is

  • Regulated, standard functions: small tools, kept standard, replaceable
  • What makes Semco money: built on Semco's own model
  • One semantic model connects them, and Semco owns it
  • Replace any piece without touching the rest
The biggest cost isn't the licence. It's being locked in again for the next decade.
01 ERP deep dive · The rule

Buy, build, integrate

Buy

Regulated and standard

Bookkeeping, payroll, VAT, e-invoicing. The law or the market defines how it works, and many vendors sell it. Doing it differently has no upside.

Would an auditor or a tax authority care how you did it? Buy it.

Build

How Semco makes money

Change impact, interfaces, weight, park takeovers, work packs. Specific to substations and O&M, and spread across systems no vendor connects.

Would a competitor pay to know how you do it? Build it.

Integrate

Everything in between

Each tool keeps its job. The model connects them: one identifier per thing, one master system per fact.

Does the fact live in one tool and matter in another? Model it.
Keep bought tools as standard as possible. Every customisation is a future migration.
01 ERP deep dive · Function by function

What goes where

FunctionChoiceWhyExample tools
Finance & bookkeepingBuyStatutory and audited. Same rules for everyone.Business Central, e-conomic, Uniconta
PayrollBuyTax law and collective agreements, per countryZenegy, Danløn (DK); local providers elsewhere
ExpensesBuyStandard flow: cards, receipts, approvalPleo, or the finance tool's own module
E-invoicing NemHandel · PeppolBuyRegulated formats and networksBuilt into most Nordic finance tools
PurchasingBuy · integrateStandard PO flow; POs link to equipment and zonesThe finance tool's purchasing module
CRMBuy · integrateStandard pipeline; contracts and CRs feed the modelHubSpot, Dynamics 365
Document controlBuy · integrateRevisions and transmittals are standard; content isn'tAconex, SharePoint-based DMS
Engineering / CADBuy · integrateSpecialist tools; the model reads their listsAVEVA and discipline tools
PlanningBuy · integrateScheduling engines are maturePrimavera P6
CMMSBuy · integrateWork orders are standard; work packs are notIFS, Maximo
HR & competenceBuy · integrateContracts are HR; competence per task is Semco'sThe HR tool, plus matching built on the model
QHSEBuy · integrateNCRs and incidents are standard; briefings are builtStandard QHSE suites
SCADA / CMSIntegrateOwned by the park owner or the OEM; read the signalsPower Factors (Greenbyte), OEM portals
Yard progressBuildPer location, specific to how Semco buildsBuilt on the model
Weight controlBuildReconciles model, vendor data and reportsBuilt on the model

Payroll and finance tools must be checked for every country Semco employs people in (DK, NO, UK…).

Examples, not recommendations. We don't know which tools Semco uses.

ERP deep dive · Part 2

The model in the middle

One identifier per thing, one master per fact, and what it looks like in Turtle.

01 ERP deep dive · Architecture

Bought tools below, Semco's model in the middle

connectorconnectorconnectorconnectorconnectorconnectorconnectorconnector Finance toolPayrollExpensesCRMPlanning · P6Doc. controlCMMSHR tool BoughtBoughtBoughtBoughtBoughtBoughtBoughtBought Kept standard, each one replaceable. Connectors read APIs, webhooks and exports, and map them to the model. Cue Index the semantic model Semco owns Semantic model One identifier per thing Provenance Permissions Validation · SHACL Orchestration RDF · OWL · SPARQL open standards, portable MCP · SDK · SPARQL Built on the model apps and agents, small and many Change impact Interface register Requirements traceability Weight & CoG AI agents Park takeover due diligence Work packs Procedure briefings Progress per location PO variation CR status work order
read into the model write-back, only through the tool's own API, after validation
01 ERP deep dive · Identity

One identifier per thing

SystemSupplierProjectTechnician
Finance toolV-10318P-2026-014–
CRMACC-5521OPP-0881–
P6–OSS2-EPCAKR
Doc. controlVND-TRA-01––
HR tool––E-1187
Semco:sup-0042:OSS-2:anna-k
  • Connectors resolve external IDs on the way in
  • Apps and agents only ever use the Semco identifier
  • Replace a tool: add its new IDs, nothing else changes
@prefix : <https://example.org/semco#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

:sup-0042 a :Supplier ;
    rdfs:label "Transformer supplier A" ;
    :knownAs [ :inSystem :FinanceTool ; :id "V-10318" ] ,
             [ :inSystem :CRM         ; :id "ACC-5521" ] ,
             [ :inSystem :DMS         ; :id "VND-TRA-01" ] .

:OSS-2 a :Project ;
    :knownAs [ :inSystem :FinanceTool ; :id "P-2026-014" ] ,
             [ :inSystem :P6          ; :id "OSS2-EPC" ] ,
             [ :inSystem :CRM         ; :id "OPP-0881" ] .

:anna-k a :Technician ;
    :knownAs [ :inSystem :HRTool ; :id "E-1187" ] ,
             [ :inSystem :P6     ; :id "AKR" ] .

Illustrative IDs · valid Turtle

01 ERP deep dive · Ownership

One master system per fact

FactMasterEveryone else
PO amount and linesFinance toolRead it, link it to equipment and zones
Customer contactCRMRead it
Baseline dateP6Read it, flag conflicts
Document revisionDoc. controlRead it, link it to requirements
Certificate expiryHR toolRead it, match it to planned tasks
Requirement statusGraphBuilt app writes it; tools may read it
Equipment ↔ requirement linkGraphNo tool holds it today
Weight and CoG per itemGraphReconciled from model, vendor data and reports
The rule

No two-way sync. The graph orchestrates.

Each fact is written in one place. When it must change, the graph asks the master to change it through its API, then reads the result back.

Two-way sync between tools breaks quietly: two masters, conflicting edits, nobody knows which one is right.

01 ERP deep dive · Modelling example 1

Commercial: change requests and purchase orders

raisedBy underContract varies deliveredUnder issuedTo bookedTo Customercust-07 ChangeRequestCR-031 Contractctr-OSS2 PurchaseOrderPO 4500-1832 EquipmentT1 · substation model Suppliersup-0042 CostCodecc-2140
Vocabulary
:ChangeRequest a owl:Class .   :PurchaseOrder a owl:Class .
:raisedBy       rdfs:domain :ChangeRequest ; rdfs:range :Customer .
:underContract  rdfs:domain :ChangeRequest ; rdfs:range :Contract .
:varies         rdfs:domain :ChangeRequest ; rdfs:range :PurchaseOrder .
:issuedTo       rdfs:domain :PurchaseOrder ; rdfs:range :Supplier .
:bookedTo       rdfs:domain :PurchaseOrder ; rdfs:range :CostCode .
:costEstimate   rdfs:domain :ChangeRequest ; rdfs:range xsd:decimal .
Facts
:CR-031 a :ChangeRequest ;
    rdfs:label "+10 % transformer rating" ;
    :raisedBy :cust-07 ;  :underContract :ctr-OSS2 ;
    :varies :PO-4500-1832 ;
    :costEstimate 420000.00 .
:PO-4500-1832 a :PurchaseOrder ;
    :issuedTo :sup-0042 ;  :bookedTo :cc-2140 .

Illustrative · valid Turtle, prefixes omitted

01 ERP deep dive · Modelling example 2

Substation: from module to requirement and zone

hasModule contains mustSatisfy statedIn locatedIn coversZone installs deliveredUnder SubstationOSS-2 ModuleM3 EquipmentT1 ZoneL2-B PurchaseOrdercommercial model DocumentSPEC rev 4 RequirementREQ-0412 WorkPackageWP-214
Vocabulary
:Equipment a owl:Class .   :Requirement a owl:Class .
:hasModule      rdfs:domain :Substation  ; rdfs:range :Module .
:contains       rdfs:domain :Module      ; rdfs:range :Equipment .
:mustSatisfy    rdfs:domain :Equipment   ; rdfs:range :Requirement .
:statedIn       rdfs:domain :Requirement ; rdfs:range :Document .
:locatedIn      rdfs:domain :Equipment   ; rdfs:range :Zone .
:coversZone     rdfs:domain :WorkPackage ; rdfs:range :Zone .
:installs       rdfs:domain :WorkPackage ; rdfs:range :Equipment .
Facts
:OSS-2  a :Substation ;  :hasModule :M3 .
:M3     a :Module ;      :contains :T1 .
:T1     a :Equipment ;   :mustSatisfy :REQ-0412 ;
        :locatedIn :L2-B ;  :deliveredUnder :PO-4500-1832 .
:REQ-0412 a :Requirement ;  :statedIn :SPEC-rev4 .
:WP-214 a :WorkPackage ;  :coversZone :L2-B ;  :installs :T1 .

Illustrative · valid Turtle, prefixes omitted

01 ERP deep dive · Modelling example 3

O&M: from bulletin to technician

inFarm partOf fromBatch appliesTo onComponent inOrder assignedTo holds follows revisionOf WindFarmPark A TurbineWTG C03 ComponentPitch bearing B Batch7731 BulletinSB-2026-14 CertificateGWO-BST-1187 TechnicianAnna K. WorkOrderWO-88140 TaskInspect bearing B ProcedureRevisionPR-118 rev 8 ProcedurePR-118
Vocabulary
:inFarm      rdfs:domain :Turbine   ; rdfs:range :WindFarm .
:partOf      rdfs:domain :Component ; rdfs:range :Turbine .
:fromBatch   rdfs:domain :Component ; rdfs:range :Batch .
:appliesTo   rdfs:domain :Bulletin  ; rdfs:range :Batch .
:revisionOf  rdfs:domain :ProcedureRevision ; rdfs:range :Procedure .
:follows     rdfs:domain :Task      ; rdfs:range :ProcedureRevision .
:onComponent rdfs:domain :Task      ; rdfs:range :Component .
:inOrder     rdfs:domain :Task      ; rdfs:range :WorkOrder .
:assignedTo  rdfs:domain :WorkOrder ; rdfs:range :Technician .
:holds       rdfs:domain :Technician ; rdfs:range :Certificate .
Facts
:C03 a :Turbine ;  :inFarm :park-A .
:C03-PB-B a :Component ;  :partOf :C03 ;  :fromBatch :batch-7731 .
:SB-2026-14 a :Bulletin ;  :appliesTo :batch-7731 .
:PR-118-r8 a :ProcedureRevision ;  :revisionOf :PR-118 .
:task-1 a :Task ;  :onComponent :C03-PB-B ;
    :follows :PR-118-r8 ;  :inOrder :WO-88140 .
:WO-88140 a :WorkOrder ;  :assignedTo :anna-k .
:anna-k :holds :GWO-BST-1187 .
:GWO-BST-1187 :validUntil "2027-02-28"^^xsd:date .

Illustrative · valid Turtle, prefixes omitted

01 ERP deep dive · From a tool to the graph

One PO line, from an API to the model

Finance tool API · JSON
{
  "documentNo": "4500-1832",
  "lineNo": 10,
  "vendorNo": "V-10318",
  "jobNo": "P-2026-014",
  "description": "Main power transformer T1",
  "quantity": 1,
  "amount": 3950000.00,
  "currency": "EUR",
  "promisedReceiptDate": "2027-03-15",
  "lastModified": "2026-10-14T09:12:44Z"
}
In the model · Turtle
:PO-4500-1832-L10 a :PurchaseOrderLine ;
    :lineOf       :PO-4500-1832 ;
    :issuedTo     :sup-0042 ;       # from V-10318
    :forProject   :OSS-2 ;          # from P-2026-014
    :supplies     :T1 ;
    :amount       "3950000.00"^^xsd:decimal ;
    :currency     "EUR" ;
    :promisedDate "2027-03-15"^^xsd:date ;
    prov:wasDerivedFrom :rec-fin-4500-1832-10 .

:rec-fin-4500-1832-10 a prov:Entity ;
    :sourceSystem :FinanceTool ;
    :recordId     "4500-1832/10" ;
    prov:generatedAtTime "2026-10-19T06:00:03Z"^^xsd:dateTime .
1Map fields to the vocabulary
2Resolve IDs: V-10318 → :sup-0042
3Stamp provenance: system, record, time

Illustrative · field names generic, not a specific vendor's API

01 ERP deep dive · Validation

Check the model before anything is written

The rule, as a SHACL shape
:VariationReadyShape a sh:NodeShape ;
    sh:targetClass :ChangeRequest ;
    sh:property [
        sh:path :approvedBy ;
        sh:minCount 1 ; sh:class :Person ;
        sh:message "No approver: PO variation blocked" ] ;
    sh:property [
        sh:path :costEstimate ;
        sh:minCount 1 ; sh:datatype xsd:decimal ;
        sh:message "No cost estimate: PO variation blocked" ] .

"A change request needs an approver and a cost estimate before a PO variation can be created."

The data
:CR-031 a :ChangeRequest ;
    :approvedBy :lars-m .
:lars-m a :Person .
Validation report · conforms: false
Focus node
:CR-031
Path
:costEstimate
Constraint
sh:minCount 1
Severity
sh:Violation
Message
No cost estimate: PO variation blocked
Estimate added · conforms: true · variation may go ahead

Output from pyshacl, trimmed · illustrative IDs

ERP deep dive · Part 3

The integration layer
in practice

Write-back, keeping current, what we build, and one change request end to end.

01 ERP deep dive · Write-back

CR-031 approved: who does what, in which order

CRMBought Cue IndexModel Orchestration agentBuilt Finance tool APIBought Planner · P6Person · bought 1 · CR-031 approved (webhook) 2 · event: change request approved 3 · validate VariationReadyShape conforms ✓ · approver, estimate 4 · POST PO variation 4500-1832 201 Created · change no. 2 5 · record variation + provenance 6 · flag: new promised date moves T1 set-in to week 40. Planner decides, P6 stays master

Illustrative

01 ERP deep dive · Keeping current

Events in, agents react

Webhooks

The tool pushes an event when a record changes. Preferred.

Polling

Ask for "changed since" every few minutes when there are no webhooks.

Nightly reconciliation

A full comparison catches whatever events missed.

EventFromAn agent…
PO promised date slipsFinance toolFinds the equipment, zone and work package, and flags the planner
New procedure revisionDoc. controlDiffs the revisions, finds affected tasks and technicians, queues briefings
Certificate expires in 60 daysHR toolChecks planned work orders, notifies the crew lead
Change request approvedCRMValidates it and proposes the PO variation
Vendor datasheet revisedDoc. controlRe-checks linked requirements and weight
New OEM bulletinOEM portalFinds components from the named batch, across all parks
Agents propose. People approve anything that writes to a master system.
01 ERP deep dive · What Semco builds

The gap apps, and the model they use

Change impact

A CR in, weight, documents, POs and schedule out.

ChangeRequestEquipmentPurchaseOrder

Interface register

Every interface with an owner, a status and the correspondence.

InterfacePartyDocument

Requirements traceability

Clause to item to evidence, with status.

RequirementEquipmentDocument

Weight & CoG

Model, vendor data and weight reports, reconciled continuously.

EquipmentModuleDatasheet

Park takeover DD

The data room, read into one history per turbine.

TurbineBatchBulletin

Work-pack preparation

Everything for one task on one turbine, before the boat leaves.

WorkOrderTaskTechnician

Procedure briefings

What changed, for whom, in a format they use.

ProcedureRevisionCertificate

Progress per location

Plan vs. reality per zone, with reasons from other systems.

ZoneWorkPackagePurchaseOrder
Eight apps, one model. Each new app starts where the last one ended.
01 ERP deep dive · End to end

CR-031 through bought and built tools

1Request
2Impact
3Approve
4Vary the PO
5Re-plan
6Revise & report
CRMBought
CR-031 logged: +10 % transformer rating
Estimate sent; customer approves
Status shared with the customer
Change impactBuilt
+18 t, CoG +0.6 m, 11 documents, PO, WP-214
Estimate added from the impact
Set-in at risk: flag to planner
Cue IndexModel
Linked to OSS-2 and T1
Traverses T1 → docs, PO, zone
Shape check passes
Variation recorded, with source
Reads the new baseline
Tracks revisions to closure
Finance toolBought
PO 4500-1832 varied via API (+9 weeks)
P6Bought
Planner moves set-in to week 40
Doc. controlBought
11 revisions raised and tracked

Illustrative

01 ERP deep dive · When the ERP is no longer maintained

The exit plan

Get the data out first, then move the regulated functions. Rebuild nothing without a shadow run.

1

Freeze

No new customisation. Agree the end date and what stays read-only.

2

Extract

Everything, history included: ledgers, POs, suppliers, projects, hours, into the graph with provenance.

3

Regulated first

Finance, payroll and e-invoicing to bought tools. Opening balances from the extract.

4

Shadow-run

Anything rebuilt runs next to the old system, reconciled every period.

5

Switch per entity

Entity by entity, after a clean year-end close. Archive the old system read-only.

Why extract first: the history is the asset. In the graph it stays queryable after the old system is switched off, whichever tools come next.

Why per entity: one company, one country at a time. A problem stops one entity, not the group.

Illustrative sequence; timing depends on Semco's entities and year-end

01 ERP deep dive · New buying criteria

Score the exit, not the demo

Must have

  • An open, documented API, for reading and writing
  • Full data export, history and attachments included, in open formats
  • Webhooks, or at least a "changed since" query
  • A contract clause: Semco owns its data, export at no extra cost on exit
  • Works in standard configuration, in every country Semco needs

Matters less than it used to

  • A nice interface: agents build the screens each team needs
  • Breadth of modules: we only buy the commodity
  • Built-in analytics and AI: they run on the model instead
  • Customisation options: we don't plan to use them
01 ERP deep dive · Running it

A small team, plus agents

Model owner

Owns the vocabulary and the shapes. Approves new classes and rules.

Integration engineer

Connectors, write-back, monitoring. Owns the APIs of the bought tools.

Controller / domain expert

Decides which system is master. Reconciles, closes, and signs off.

Agents

Draft mappings, build apps, watch events. A person approves every write.

The integration layer becomes critical. Run it like it is.

On-call owner
Connector health Lag per source Validation violations Failed write-backs Identity conflicts Nightly reconciliation diff
01 ERP deep dive · Phasing

Three steps. Each pays off on its own.

1

Read

Connect the existing tools read-only, the old ERP included. One identifier per thing. First apps that only read: traceability, change impact, progress.

Answers across systems, with no change to any of them
2

Write back, selectively

A few objects, through the tools' APIs, with validation and approval: PO variations, CR status, work orders.

Less re-keying, fewer errors between systems
3

Replace pieces

When support ends, move one function at a time to a bought tool. The model and the apps stay.

No big bang. No new lock-in.
Step 1 can start before the ERP decision is made, and makes that decision easier.
01 ERP deep dive · Honest caveats

What this doesn't solve

Don't build these

  • Payroll
  • Statutory bookkeeping and VAT
  • E-invoicing network access
  • Bank integration

Trust takes calendar time

A clean year-end close on the new setup. An audit that accepts it. People who trust the numbers. None of that goes faster because the code was written faster.

New responsibilities

The integration layer is critical. The model needs an owner and discipline. Bad data in the old ERP comes along until someone cleans it.

Coding is fast now. Trust is not. Plan for closes and audits, not sprints.
01 ERP deep dive · Your turn

Questions for Semco

Which systems do you run?

Per business, per country. Which are customised, and who maintains them?

Which touch the outside world?

Bank, tax, payroll, e-invoicing. These carry the legal risk and move first.

Which is no longer maintained?

When does support end, and what has already been decided or budgeted?

Who would own the model?

And which use case from today would you connect first?

Answers feed the pilot proposal in the main deck.← Back to the workshop deck