template A
with
p : Party
where
signatory p
nonconsuming choice CreateB : ContractId B
controller p
do
create B with
a = this
template B
with
a : A
where
signatory (signatory a)
I suppose it could be refactored like this?
template A2
with
unique : Text
p : Party
where
key (p, unique) : (Party, Text)
maintainer key._1
signatory p
nonconsuming choice CreateB2 : ContractId B2
controller p
do
create B2 with
a2Id = (this.p, this.unique)
template B2
with
a2Id : (Party, Text)
where
signatory a2Id._1
Or ever CreateB2 could be replaced by a separate API call IE:
demo : Script()
demo = script do
alice <- allocatePartyWithHint "Alice" (PartyIdHint "Alice")
submit alice do
createCmd A2 with
unique = "UNIQUE"
p = alice
submit alice do
createCmd B2 with
a2Id = (alice, "UNIQUE")
pure()
This last method might create the scenario where you have instances of B2 that don’t actually refer to any existing A2s, however this might be ok for some use cases.
@tiw
I would suggest first clearly defining the workflow you’d like to facilitate. Based on the example you quoted at the beginning of your post, I suppose the workflow you’re interested in can be defined as follows. Given the contract for a department you’d like to be able to fetch from the ledger the contract for associated organization. This capability should persist when the data in the organization (e.g. the organization name) is modified (which in Daml means archiving the organization contract and recreating it with new values for the fields).
If this is indeed the workflow you’re after, your first example (with templates A and B respectively representing organization and department) cannot facilitate it. The template B stores the data in the contract created from template A, but it doesn’t store any reference to the contract. Suppose we modify template A by adding the field “orgname”. Then we create a contract from template A with orgname = “BadlySpelledOrgName”. Then we exercise CreateB choice on this contract. The resulting contract B will contain the data from contract A including the value of orgname field set to “BadlySpelledOrgName”. Now suppose we archive contract A and recreate it with orgname = “CorrectlySpelledOrgName”. Now the data in contract B and contract A are out of sync. In this design, if you have contract B, you have no means of fetching contract A from the ledger because contract B has no reference to contract A. All it has is the data (the values of the fields) that contract A had at the time CreateB choice was exercised.
In your second example you do have a link between contract B and contract A in the form of a key from contract A stored in contract B. Since contract key provides a persistent link to the contract, given contract B you can always fetch associated contract A using the key. In other words, the second example can very well facilitate the desired workflow.
In both examples it’s perfectly possible to create contract B without associated contract A. If this is undesirable for your workflow, to prevent this you would need to introduce requirement for additional authority.