GraphQL Server for Visma Business

Processings and reports

Run Visma Business processings and fetch reports as PDF from the mutation root.

Visma’s own operations, exposed on the mutation root:

mutation { order_processings { confirmed(orderNo: 512) { succeeded succeededCount } } }
mutation { order_reports { orderConfirmations(orderNo: 512) { succeeded fileName fileBytes } } }

<table>_processings exists for every table with a processing that can run - 101 of them, 457 processings in all. <table>_reports for the 11 tables that have reports, 38 in all.

Reports return documents

A report prints to PDF and hands back the bytes, base64 encoded, with the file name Visma gave it. It has no other result: the model declares result fields for processings and none for any of the 38 reports.

mutation {
  order_reports {
    orderConfirmations(orderNo: 512, date: 20260901, pageBreakPerOrder: true) {
      succeeded
      fileName   # "200008.pdf"
      fileBytes  # "JVBERi0xLjQK..." - %PDF-1.4
    }
  }
}

Document copies come back the same way, from the document tables rather than by reprinting the order:

mutation {
  orderDocument_reports {
    orderDocumentCopy(orderDocumentNo: 347) { succeeded fileName fileBytes }
  }
}

customerDocument_reports { customerDocumentCopy } is the same for customer documents. Note that running a report does not archive a copy unless the firm is set up to - the copy is fetched from a document that already exists.

Everything is taken from the model

Not from the name of anything. The model gives every parameter, result and column a domain, and the domain is what says what it is:

Type The domain’s storage type. A date is a date, not a String
Boolean The domain the model calls Boolean, so overwriteNonBlankDates: true rather than 1
Enumeration The domain’s own name, which names the client’s generated enum for it
Executable ExecutionAccess and CloudExecutionAccess, the same convention the columns use

The difference is not cosmetic. Matching on a value’s own name instead:

  • typed the order confirmation’s confirmedDate as a String, because no rule covers that name;
  • left 192 parameters as integers the caller had to know to set to 1;
  • left 168 columns as plain Int although the model enumerates them, and gave 13 more a less specific enum than their domain’s - origin as OriginEnum where the model says AccountStatementOrigin;
  • typed the file download result FileBytes as a byte array on the strength of its name, where the model puts it on the UnlimitedString domain. That one took the entire schema down at startup with The type 'System.Void*' may not be used as a type argument, naming neither the field nor the type.

What the model will not let you run

65 of the 522 processings are marked as not executable here, and are not offered. Visma refuses them at the far end anyway:

  • ExecutionAccess - “Execute access to processing dedicated to manufacturer”
  • CloudExecutionAccess - “This processing is not exposed to Visma Business Services”, which is what this server talks to

OrderDocument.downloadPdf and OrderDocument.viewDocumentCopy are two of them; the report above is the way to get that document.

Parameters

Only the ones you pass are sent. An omitted parameter is left out rather than sent as nought, which a processing cannot tell from a deliberate nought - before, every optional parameter was mandatory with a silent default. An explicit null is left out too.

Three processings name a parameter after their own table’s primary key - VudNewCompany takes a CompanyNo, InstallReport a ReportNo, CreateAppointment an AssociateNo. The key wins, since it selects the row the processing runs on, and the duplicate is logged.