# Synthetic Avouch example for Avouch Studio: a small lending library. # All names and quotes are invented; the file is also the test fixture. formatVersion: 1 contexts: Lending: Borrowing and returns Catalog: Books and shelves infrastructureStores: [audit_log] permission_rows_not_commands: - name: Export loan report reason: Back-office report action; not an ontology command cite: { doc: 'spec#permissions', quote: Exporting the loan report needs report:export } knownSourceGaps: - id: G1 rule: R6 kind: effect_unspecified keys: ['CHECKOUT_ITEM:loan_guarantor'] doc_line: 'spec#checkout' conflict: The doc does not say when the guarantor is created proposed: State in spec#checkout when the guarantor is created outOfScopeObjectTypes: Donor: Donors are managed by an external system; not modeled here objectTypes: Member: context: Lending datasource: members doc: 'spec#member' properties: status: class: canonical cite: { doc: 'spec#member', quote: Member status is maintained by hand at the front desk } Loan: context: Lending datasource: loans doc: 'spec#loan' properties: status: class: canonical cite: { doc: 'spec#loan', quote: Loan status is changed only by loan commands } due_at: class: canonical cite: { doc: 'spec#loan', quote: The due date is set at checkout } overdue_days: class: derived cite: { doc: 'spec#loan', quote: Days overdue are computed from the due date } materializedFrom: reads: [Loan.due_at] cites: - cite: { doc: 'spec#loan', quote: Changing the due date recomputes days overdue in the same batch } Item: context: Catalog datasource: items doc: 'spec#item' properties: condition: class: canonical cite: { doc: 'spec#item', quote: Condition is recorded by the librarian } on_loan: class: canonical cite: { doc: 'spec#item', quote: The checked-out flag changes in the same batch as the loan } non_link_fields: isbn_id: reason: External catalog number; not a link in this library cite: { doc: 'spec#item', quote: isbn_id comes from the external catalog system } Shelf: context: Catalog datasource: shelves doc: 'spec#shelf' properties: {} stateMachines: Loan: doc: 'spec#loan-states' initial: REQUESTED terminal: [CHECKED_IN, VOIDED, LOST] transitions: - { from: REQUESTED, to: ACTIVE, by: [CHECKOUT_ITEM] } - { from: ACTIVE, to: CHECKED_IN, by: [RETURN_ITEM] } - { from: REQUESTED, to: VOIDED, by: [CANCEL_LOAN] } - { from: ACTIVE, to: VOIDED, by: [CANCEL_LOAN] } - { from: ACTIVE, to: LOST, by: [], out_of_scope: Loss is handled by hand at the yearly inventory } Item: doc: 'spec#item-states' initial: ON_SHELF terminal: [WITHDRAWN] transitions: - { from: ON_SHELF, to: ON_LOAN, by: [CHECKOUT_ITEM] } - { from: ON_LOAN, to: ON_SHELF, by: [RETURN_ITEM] } - { from: ON_SHELF, to: WITHDRAWN, by: [], out_of_scope: Withdrawal is handled by hand at the yearly catalog review } linkTypes: - { id: loan_member, from: Loan, to: Member, cardinality: 'N:1', via: member_id, doc: 'spec#loan' } - { id: loan_guarantor, from: Loan, to: Member, cardinality: 'N:1', via: guarantor_id, doc: 'spec#loan' } - { id: loan_item, from: Loan, to: Item, cardinality: 'N:1', via: item_id, doc: 'spec#loan' } - { id: item_shelf, from: Item, to: Shelf, cardinality: 'N:1', via: shelf_id, doc: 'spec#item' } - { id: item_parent, from: Item, to: Item, cardinality: 'N:1', via: parent_item_id, doc: 'spec#item' } - id: member_holds from: Member to: Item cardinality: 'N:M' via: holds doc: 'spec#holds' table: holds create_rule: context: Lending with_creates: [Member] cite: { doc: 'spec#holds', quote: Holds can be created only by the lending context } exceptions: commands: [ACCEPT_DONATION] cite: { doc: 'spec#holds', quote: On donation intake a hold may be kept for the donor } derivedProperties: member_has_overdue: of: Member doc: 'spec#member' doc_term: Has overdue loan reads: [Loan.status, Loan.due_at] actionTypes: CHECKOUT_ITEM: context: Lending doc: 'spec#checkout' doc_term: Check out permission: keys: ['loan:create'] cite: { doc: 'spec#permissions', quote: Checkout needs loan:create } submissionCriteria: - id: item_available reads: - { prop: Item.condition, values: [GOOD, FAIR] } - Item.on_loan cite: { doc: 'spec#checkout', quote: Only a book in good condition and on the shelf can be checked out } scenarios: [LND-01.S1] - id: no_overdue reads: [member_has_overdue] cite: { doc: 'spec#checkout', quote: A member with an overdue loan cannot borrow again } creates: [Loan] edits: [Item.on_loan] crossContext: via: preassembled_sql cite: { doc: 'spec#checkout', quote: Checkout marks the item as checked out in the same batch } link_effects: loan_member: effect: The new loan points to the borrowing member cite: { doc: 'spec#checkout', quote: The loan records the borrowing member } scenarios: [LND-01.S1] item_shelf: none: Checkout does not change the shelf loan_guarantor: unspecified: The doc does not say when the guarantor is created cite: { doc: 'spec#checkout', quote: A guarantor can be named if needed } loan_item: effect: The new loan points to the borrowed book cite: { doc: 'spec#checkout', quote: The loan records the borrowed book } emits: [LoanStarted] evidence: checkoutItem RETURN_ITEM: context: Lending doc: 'spec#return' doc_term: Return permission: none: The member returns the book at the self-service kiosk cite: { doc: 'spec#permissions', quote: Self-service return has no permission key } submissionCriteria: - id: loan_active reads: [Loan.status] cite: { doc: 'spec#return', quote: Only a loan that is checked out can be returned } - id: member_present reads: [Member.status] cite: { doc: 'spec#return', quote: A deactivated member can also return a book } edits: [Loan.status, Item.on_loan] link_effects: loan_member: { none: Return does not change the borrowing member } loan_item: { none: Return does not change the borrowed book } emits: [LoanReturned] CANCEL_LOAN: context: Lending doc: 'spec#cancel' doc_term: Cancel loan permission: keys: ['loan:cancel'] conditional_keys: ['loan:override'] cite: { doc: 'spec#permissions', quote: Cancelling a loan needs loan:cancel } conditional_cite: { doc: 'spec#permissions', quote: A loan already checked out also needs loan:override } submissionCriteria: - id: loan_open reads: [Loan.status] cite: { doc: 'spec#cancel', quote: A returned loan cannot be cancelled } edits: [Loan.status] link_effects: {} emits: [LoanVoided] ACCEPT_DONATION: context: Catalog doc: 'spec#donation' doc_term: Receive donation permission: unknown submissionCriteria: - id: donor_known reads: [] reads_unspecified: The doc does not say which attributes the donor registration reads cite: { doc: 'spec#donation', quote: The donor must be registered } creates: [Item, Donor] edits: [] link_effects: item_shelf: effect: The new book goes on the default shelf cite: { doc: 'spec#donation', quote: A donated book first goes on the to-be-cataloged shelf } emits: [] evidence: acceptDonation