Create a command
Updated
A document command is the only user entry into a subtype change. After Save,
the card does not let the user pick a subtype. The button checks, then sets
the target Subtype; the engine replaces movements (Mix) and runs the posting
scripts of the target only.
Note
Without that command the document stays a draft in the UI, however many scripts hang on "Posted". Events (
OnBeforePostAsync, …) still run for any transition, including API. The command is what the user presses.
How to#
Three files in Commands/Document/<Name>/:
<Name>.json— the command (kind: "DocumentCommand") andsubtypeBindings(the subtype it is available from). An empty bindings array means every subtype — almost never what a guarded transition wants.<Name>Script.script.json—scriptType: "DocumentCommand",objectMetaId= the command'smetaId.<Name>Script.cs— the platform generates the baseDocumentCommandBase<Document>:
public partial class ApproveOrderCommand
{
public override async Task ExecuteAsync(SalesOrder document, CommandContext context)
{
var error = await context.GetService<ISalesOrderService>()
.ValidateForApproveAsync(document.MetaId);
if (error != null)
{
CreateUserMessage(error);
return;
}
document.Subtype = SalesOrder.Subtypes.Confirmed;
await DocumentManager.SaveDocumentAsync(document);
}
}
Check first. Transition only when the check passed. On failure,
CreateUserMessage (a resource, not a literal) and
return without changing the subtype.
Use <Document>.Subtypes.<Name>, never the string "Posted".
Commands that do not change subtype (fill prices, explode a BOM) are fine. They do not post the document.
A dictionary command is the same trio under Commands/Dictionary/<Name>/,
with dictionaryMetaId instead of subtypeBindings. No menu item — the
button appears on the dictionary card.
Tip
Apply the script file before the command file. The command points at
scriptMetaId; the other order hitsFOREIGN KEY … MetaScripts.
Do not copy somebody else's command "next to it". Wrap it with
Chain of Command (nextAsync<CommandResult>). A missing
next on a wrap is ZOCOC003.
A static "Are you sure?" is requiresConfirmation on the json. A question
that depends on data is context.Confirm(…) —
Ask from a command. The two-run contract is
Asking the user from a command.
What's not there yet#
document.Subtype = … from a service or a test is for system transitions, not
a substitute for the button.