@hyperscale0/hsx 1.0.222 → 1.0.235

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,18 +1,18 @@
1
1
  export const examples = [
2
- { "id": "cards", "title": "Team expense cards", "summary": "A company issues expense cards to employees and reserves each supplier payment before capture.", "headers": ["cards"], "source": "// A company issues expense cards to employees and reserves each supplier payment before capture.\nprogram team_expense_cards \"Team expense cards\"\nuse cards\n// supplier is a business this program declares, so plan needs {\"partyBindings\":{\"supplier\":\"<partyId>\"}}.\n// That partyId is an organization customer's: create the Product from this source without the payment\n// and receipt attachments, add the customer with customer.create, activate its access, open its\n// customer_balance account, then compose this source with the binding.\nparty supplier: business\n\nobject employee \"Employee card\" {\n fields { employeeName: text, department: text }\n columns: [employeeName, department]\n attach holder = cards.cardholder {\n expose create as create_holder\n holder: owner\n expose activate as activate_employee\n expose suspend as suspend_employee\n }\n attach card = cards.card {\n expose create as create_card\n holder: holder, person: owner, spend_limit: 5000 SAR\n expose activate as activate_card\n expose freeze as freeze_card\n expose unfreeze as unfreeze_card\n expose issuer_freeze as block_card\n expose issuer_unfreeze as unblock_card\n }\n attach payment = cards.authorization {\n expose create as create_payment\n card: card, merchant: supplier\n expose approve as approve_payment\n expose capture as capture_payment\n expose reverse as reverse_payment\n }\n attach receipt = cards.transaction {\n expose create as create_receipt\n authorization: payment\n expose refund as refund_payment\n }\n}\n" },
3
- { "id": "collections", "title": "Small business collections", "summary": "A business lender refers overdue instalments to an agency with limits on collection contacts.", "headers": ["collections", "financing"], "source": "// A business lender refers overdue instalments to an agency with limits on collection contacts.\nprogram business_collections \"Small business collections\"\nuse collections\nuse financing\n// agency is a business this program declares, so plan needs {\"partyBindings\":{\"agency\":\"<partyId>\"}}.\n// That partyId is an organization customer's: create the Product from this source without the recovery\n// and contact attachments, add the customer with customer.create, activate its access, open its\n// customer_balance account, then compose this source with the binding.\nparty agency: business\n\nobject facility \"Business loan\" {\n fields { businessName: text, purpose: text, price: money }\n columns: [businessName, purpose, price]\n attach allowance = financing.limits { expose create as create_allowance, expose approve as approve_borrower, borrower: owner, per_borrower: 100000 SAR }\n attach budget = financing.portfolio_limit { expose create as create_budget, expose approve as approve_budget, limit: 2000000 SAR }\n attach loan = financing.installments {\n expose create as create_loan\n borrower: owner, capital: operator\n months: 12, pricing: amortizing, profit_rate: 6%, disburse_to: borrower\n limits: allowance, portfolio: budget\n expose sign as sign_loan\n expose disburse as release_loan\n expose payoff as repay_early\n }\n attach recovery = collections.case {\n expose create as create_recovery\n on: loan, agency: agency\n expose assign as assign_case\n expose recover as recover_payment\n expose recall as recall_case\n }\n attach contact = collections.contact {\n expose create as create_contact\n case: recovery, agency: agency\n }\n}\n\nexpose facility.loan.payment.create as create_payment\nexpose facility.loan.payment.pay as pay_instalment\nexpose facility.loan.payment.refund as refund_payment\nexpose facility.loan.payoff_quote.create as request_payoff_quote\n" },
4
- { "id": "escrow", "title": "Used device sales", "summary": "Buyers fund a used device purchase, then accept delivery or raise a dispute before release.", "headers": ["escrow"], "source": "// Buyers fund a used device purchase, then accept delivery or raise a dispute before release.\nprogram used_device_sales \"Used device sales\"\nuse escrow\n\nobject device \"Device\" {\n fields {\n model: text\n condition: text\n serialNumber: text\n price: money\n }\n columns: [model, condition, price]\n attach sale = escrow.hold {\n expose create as create_sale\n payer: actor, payee: owner\n expose fund as pay_for_device\n expose deliver as confirm_delivery\n expose accept as accept_device\n expose dispute as report_problem\n expose verify_return as verify_return\n expose refund as refund_buyer\n expose cancel as cancel_sale\n }\n}\n" },
5
- { "id": "financing", "title": "Tuition instalments", "summary": "A tuition lender funds a student's fees over three interest-free instalments with borrowing limits.", "headers": ["financing"], "source": "// A tuition lender funds a student's fees over three interest-free instalments with borrowing limits.\nprogram tuition_instalments \"Tuition instalments\"\nuse financing\n\nobject enrolment \"Enrolment\" {\n fields { student: text, course: text, price: money }\n columns: [student, course, price]\n attach allowance = financing.limits {\n expose create as create_allowance\n borrower: owner, per_borrower: 12000 SAR\n expose approve as approve_student\n }\n attach budget = financing.portfolio_limit {\n expose create as create_budget\n limit: 500000 SAR\n expose approve as approve_budget\n }\n attach tuition = financing.installments {\n expose create as create_tuition\n borrower: owner, capital: operator\n months: 3, pricing: flat_total, profit_rate: 0%, disburse_to: borrower\n limits: allowance, portfolio: budget\n expose sign as sign_tuition_plan\n expose disburse as fund_tuition\n expose payoff as repay_early\n }\n}\n\nexpose enrolment.tuition.payment.create as create_payment\nexpose enrolment.tuition.payment.pay as pay_instalment\nexpose enrolment.tuition.payment.refund as refund_payment\nexpose enrolment.tuition.payoff_quote.create as request_payoff_quote\n" },
6
- { "id": "insurance", "title": "Device insurance", "summary": "A device retailer collects the purchase price and attaches cover with a claim review process.", "headers": ["insurance", "money"], "source": "// A device retailer collects the purchase price and attaches cover with a claim review process.\nprogram device_insurance \"Device insurance\"\nuse insurance\nuse money\n\nobject device \"Insured device\" {\n fields { model: text, serialNumber: text, purchaseDate: date }\n columns: [model, serialNumber, purchaseDate]\n attach purchase = money.transfer {\n expose create as create_purchase\n payer: owner, payee: operator\n economics pay { purpose: earning, sourceParty: owner }\n expose pay as pay_for_device\n }\n // conformance_boundary is the sandbox insurer adapter; swap in the insurer's registered adapter to go live.\n // Premiums net of commission go to its account. The default broker is the retailer, which keeps the commission.\n // claim_limit is the sum insured, set per cover at creation.\n attach protection = insurance.cover {\n expose create as create_protection\n holder: owner, adapter: \"conformance_boundary\", commission: 10%, covers: purchase\n expose activate as activate_cover\n expose cancel as cancel_cover\n }\n attach claim = insurance.claim {\n expose create as create_claim\n cover: protection, inspector: operator\n expose approve as approve_claim\n expose deny as deny_claim\n expose pay as pay_claim\n }\n}\n" },
7
- { "id": "lending", "title": "Community business lending", "summary": "A lending composition with limit approvals, wallet commitments and cash distribution transitions.", "headers": ["lending", "financing", "wallet"], "source": "// A lending composition with limit approvals, wallet commitments and cash distribution transitions.\nprogram community_business_lending \"Community business lending\"\nuse lending\nuse financing\nuse wallet\n\nobject business \"Business funding\" {\n fields { businessName: text, purpose: text, price: money }\n columns: [businessName, purpose, price]\n attach allowance = financing.limits {\n expose create as create_allowance\n borrower: owner, per_borrower: 100000 SAR\n expose approve as approve_borrower\n }\n attach budget = financing.portfolio_limit {\n expose create as create_budget\n limit: 2000000 SAR\n expose approve as approve_budget\n }\n attach loan = financing.installments {\n expose create as create_loan\n borrower: owner, capital: operator\n months: 12, pricing: amortizing, profit_rate: 6%, disburse_to: borrower\n limits: allowance, portfolio: budget\n expose sign as sign_loan\n expose disburse as release_loan\n expose payoff as repay_early\n }\n attach investor_balance = wallet.balance {\n expose create as create_investor_balance\n holder: actor\n expose activate as open_wallet\n expose topup as add_funds\n }\n attach funding = lending.round {\n borrower: owner, plan: loan\n expose create as open_funding\n expose close as close_funding\n }\n attach investment = lending.commitment {\n round: funding, wallet: investor_balance, investor: actor\n expose create as invest\n expose withdraw as withdraw_investment\n }\n attach returns = lending.distribution {\n expose create as create_returns\n round: funding, receipt: loan.settlement\n expose prepare_cash as prepare_returns\n expose distribute_cash as distribute_returns\n }\n}\n\nexpose business.loan.payment.create as create_payment\nexpose business.loan.payment.pay as pay_instalment\nexpose business.loan.payment.refund as refund_payment\nexpose business.loan.payoff_quote.create as request_payoff_quote\nexpose business.returns.share.create as create_return_share\n" },
8
- { "id": "library", "title": "Financed car sales", "summary": "A minimal financed car sale connects escrow to a three-instalment plan and lending limits.", "headers": ["escrow", "financing"], "source": "// A minimal financed car sale connects escrow to a three-instalment plan and lending limits.\nprogram cars \"Financed car sales\"\nuse escrow\nuse financing\nobject car \"Cars\" {\n fields { make: text, model: text, year: integer }\n attach sale = escrow.hold { expose create as create_sale, payer: actor, payee: owner, expose fund as sell }\n attach limits = financing.limits { expose create as create_limits, borrower: actor, per_borrower: 60000 SAR }\n attach ceiling = financing.portfolio_limit { expose create as create_ceiling, limit: 1500000 SAR }\n attach plan = financing.installments {\n borrower: actor, capital: operator, share: 25%\n months: 3, pricing: flat_total, profit_rate: 2.5%, funds: sale, limits: limits, portfolio: ceiling\n expose create as finance\n }\n}\n" },
9
- { "id": "marketplace", "title": "Freelance marketplace", "summary": "Freelancers publish offers and clients place orders with funds held until work is accepted.", "headers": ["marketplace", "escrow"], "source": "// Freelancers publish offers and clients place orders with funds held until work is accepted.\nprogram freelance_marketplace \"Freelance marketplace\"\nuse marketplace\nuse escrow\n\nobject project \"Project\" {\n fields { brief: text, deliverable: text, price: money }\n columns: [brief, deliverable, price]\n attach offer = marketplace.listing {\n rename { price: price }\n expose create as create_offer\n seller: owner\n expose publish as publish_offer\n expose withdraw as withdraw_offer\n }\n attach order = marketplace.order {\n rename { price: price }\n expose create as create_order\n listing: offer, buyer: actor, fulfiller: owner\n expose commit as place_order\n expose fulfill as finish_order\n }\n attach payment = escrow.hold {\n expose create as create_payment\n payer: actor, payee: owner\n expose fund as fund_project\n expose deliver as submit_work\n expose accept as accept_work\n expose dispute as dispute_work\n expose verify_return as verify_return\n expose refund as refund_client\n expose cancel as cancel_payment\n }\n}\n" },
10
- { "id": "money", "title": "Tutoring studio", "summary": "A tutoring studio collects a fixed fee for each lesson and can cancel unpaid bookings.", "headers": ["money"], "source": "// A tutoring studio collects a fixed fee for each lesson and can cancel unpaid bookings.\nprogram tutoring_studio \"Tutoring studio\"\nuse money\n\nobject lesson \"Lesson\" {\n fields {\n student: text\n tutor: text\n startsAt: date\n }\n columns: [student, tutor, startsAt]\n attach payment = money.transfer {\n expose create as create_payment\n payer: actor, payee: operator, amount: 150 SAR\n economics pay { purpose: earning, sourceParty: actor }\n expose pay as pay_for_lesson\n expose cancel as cancel_payment\n }\n}\n" },
11
- { "id": "rental-deposit", "title": "Equipment rental", "summary": "A business rents equipment with a 1,000 riyal deposit and a single 50 riyal late fee. On-time return refunds 1,000 riyals; late return pays the operator 50 riyals and refunds 950 riyals.", "headers": [], "source": "// A business rents equipment with a 1,000 riyal deposit and a single 50 riyal late fee.\n// On-time return refunds 1,000 riyals; late return pays the operator 50 riyals and refunds 950 riyals.\nprogram equipment_rental \"Equipment rental\"\nparty renter: business\n\n// The renter is one declared business, so this instrument takes no parameters.\ninstrument deposit {\n summary: \"Hold a rental deposit, then return it less any fixed late fee.\"\n fields {\n renter: account of renter\n held: account of self\n amount: money = 1000 SAR\n lateFee: money = 50 SAR\n dueAt: date\n refund: money?\n }\n lifecycle { states: [pending, funded, returned, cancelled], initial: pending }\n action create {\n actor: { party: renter }\n requires self.dueAt > self.now\n }\n action fund {\n from: pending, to: funded, actor: { party: renter }\n deadline: { at: self.dueAt }\n moves self.amount from self.renter to self.held\n }\n action return_on_time {\n from: funded, to: returned, actor: { party: programOperator }\n deadline: { at: self.dueAt }\n subject { returnReference: text }\n moves self.held.balance from self.held to self.renter\n }\n action return_late {\n from: funded, to: returned, actor: { party: programOperator }\n due: { at: self.dueAt }\n subject { returnReference: text }\n calculate: [{ target: refund, op: subtract, base: { field: self.held.balance }, subtract: [{ field: self.lateFee }] }]\n moves self.lateFee from self.held to programOperator\n moves self.refund from self.held to self.renter\n }\n action cancel { from: pending, to: cancelled, actor: { party: renter } }\n}\n\nobject rental \"Equipment rental\" {\n fields { equipment: text }\n columns: [equipment, dueAt]\n attach security = deposit {\n // dueAt is a column, so it stays shared object metadata.\n rename { dueAt: dueAt }\n expose create as agree_rental\n expose fund as pay_deposit\n expose return_on_time as return_equipment\n expose return_late as return_equipment_late\n expose cancel as cancel_rental\n }\n}\n\nhide deposit.create\nhide deposit.fund\nhide deposit.return_on_time\nhide deposit.return_late\nhide deposit.cancel\n" },
12
- { "id": "repair-approval", "title": "Repair approvals", "summary": "A repair shop records inspection and approval evidence before it can complete a job.", "headers": [], "source": "// A repair shop records inspection and approval evidence before it can complete a job.\nprogram repair_shop \"Repair approvals\"\n\ninstrument assessment {\n summary: \"Inspect the repair, collect approval, then record completion.\"\n fields { inspectedAt: date?, approvedAt: date? }\n lifecycle { states: [submitted, inspected, approved, completed, rejected], initial: submitted }\n action create {}\n action inspect {\n from: submitted, to: inspected, actor: { party: programOperator }\n subject { inspectionNotes: text }\n set: { inspectedAt: { field: self.now } }\n }\n action approve {\n from: inspected, to: approved, actor: { party: programOperator }\n subject { approvalReference: text }\n set: { approvedAt: { field: self.now } }\n }\n action reject {\n from: inspected, to: rejected, actor: { party: programOperator }\n }\n action complete {\n from: approved, to: completed, actor: { party: programOperator }\n subject { completionNotes: text }\n }\n}\n\nobject repair \"Repair\" {\n fields { item: text, problem: text }\n columns: [item, problem]\n attach review = assessment {\n expose create as create_review\n expose inspect as inspect_repair\n expose approve as approve_repair\n expose reject as reject_repair\n expose complete as complete_repair\n }\n}\n\nhide assessment.create\nhide assessment.inspect\nhide assessment.approve\nhide assessment.reject\nhide assessment.complete\n" },
13
- { "id": "reporting", "title": "Equipment loan reports", "summary": "An equipment lender keeps an ageing report over its financed purchases and recorded repayments.", "headers": ["reporting", "financing"], "source": "// An equipment lender keeps an ageing report over its financed purchases and recorded repayments.\nprogram equipment_loan_reports \"Equipment loan reports\"\nuse reporting\nuse financing\n\nobject purchase \"Equipment loan\" {\n fields { businessName: text, equipment: text, price: money }\n columns: [businessName, equipment, price]\n attach allowance = financing.limits {\n expose create as create_allowance\n borrower: owner, per_borrower: 200000 SAR\n expose approve as approve_business\n }\n attach budget = financing.portfolio_limit {\n expose create as create_budget\n limit: 5000000 SAR\n expose approve as approve_budget\n }\n attach loan = financing.installments {\n expose create as create_loan\n borrower: owner, capital: operator\n months: 12, pricing: amortizing, profit_rate: 6%, disburse_to: borrower\n limits: allowance, portfolio: budget\n expose sign as sign_purchase_loan\n expose disburse as fund_purchase\n }\n attach reports = reporting.portfolio { expose create as create_reports, on: loan }\n}\n" },
14
- { "id": "savings", "title": "Savings circle", "summary": "Six members contribute to a shared pot and receive it in their agreed calendar order.", "headers": ["savings"], "source": "// Six members contribute to a shared pot and receive it in their agreed calendar order.\nprogram neighbourhood_savings \"Savings circle\"\nuse savings\n\nobject group \"Savings group\" {\n fields { groupName: text, purpose: text }\n columns: [groupName, purpose]\n attach circle = savings.circle {\n expose create as create_circle\n contribution: 500 SAR, members: 6, starts: 2027-01-01\n expose disband as disband_circle\n expose close as close_circle\n }\n attach membership = savings.membership {\n expose create as create_membership\n circle: circle, member: actor\n expose activate as confirm_membership\n expose withdraw as leave_circle\n }\n // Contributions and each member's payout follow the declared calendar.\n}\n" },
15
- { "id": "serviced", "title": "Car financing", "summary": "A car finance company services loans with late charges, payment reminders and early repayment.", "headers": ["escrow", "financing", "collections"], "source": "// A car finance company services loans with late charges, payment reminders and early repayment.\nprogram car_financing \"Car financing\"\nuse escrow\nuse financing\nuse collections\nobject car \"Car\" {\n fields { make: text, model: text, year: integer, vin: text, price: money }\n columns: [make, model, year, vin, price]\n attach sale = escrow.hold { expose create as create_sale, payer: actor, payee: operator, expose fund as purchase }\n attach limits = financing.limits { expose create as create_limits, borrower: actor, per_borrower: 250000 SAR }\n attach ceiling = financing.portfolio_limit { expose create as create_ceiling, limit: 10000000 SAR }\n attach plan = financing.installments {\n borrower: actor, capital: operator\n months: 36, pricing: flat_total, profit_rate: 8.5%, down_payment: 10%\n apply: fines_profit_principal, payoff_rebate: 100%, write_off_after: 90d\n funds: sale, limits: limits, portfolio: ceiling\n expose create as finance, expose sign as sign_contract, expose payoff as payoff\n }\n attach late = financing.late_charge {\n expose create as create_late\n on: plan, grace: 3d, fine: 50 SAR, cap: 25 SAR\n fines_to: operator, costs_to: operator, borrower: actor\n }\n attach reminders = collections.reminder { expose create as create_reminders, on: plan, operator: operator, before_days: 3, overdue_days: 1 }\n}\n" },
16
- { "id": "wallet", "title": "Workshop credits", "summary": "Members prepay for workshop visits and the studio reserves each spend before charging it.", "headers": ["wallet"], "source": "// Members prepay for workshop visits and the studio reserves each spend before charging it.\nprogram workshop_credits \"Workshop credits\"\nuse wallet\n\nobject membership \"Membership\" {\n fields { memberName: text, membershipNumber: text }\n columns: [memberName, membershipNumber]\n attach balance = wallet.balance {\n expose create as create_balance\n holder: owner\n expose activate as open_balance\n expose topup as add_credit\n expose withdraw as withdraw_credit\n expose close as close_balance\n }\n attach visit = wallet.spend {\n expose create as create_visit\n wallet: balance, payee: operator, holder: owner\n economics pay { purpose: earning, sourceParty: owner }\n expose reserve as reserve_visit\n expose pay as charge_visit\n expose cancel as cancel_visit\n }\n}\n" },
2
+ { "id": "cards", "title": "Riyadh catering cards", "summary": "Riyadh catering cards lets staff reserve supplier purchases up to 5,000 SAR each. Supplier cancellation releases the reservation; captured purchases support a full refund or a reviewed dispute.", "headers": ["cards"], "source": "// Riyadh catering cards lets staff reserve supplier purchases up to 5,000 SAR each.\n// Supplier cancellation releases the reservation; captured purchases support a full refund or a reviewed dispute.\nprogram team_expense_cards \"Riyadh catering cards\"\nuse cards\nparty supplier: business\n\n// Bind supplier to the food wholesaler. Staff customers own their card records.\n// Card fee: 0%, tax: 0% on card access because the caterer charges staff nothing.\n// A supplier invoice might be 2,000 SAR plus 15% VAT, paid as one 2,300 SAR\n// authorization. cards does not calculate or remit the supplier's invoice VAT.\nobject employee \"Catering expense card\" {\n fields { employeeName: text, department: text }\n columns: [employeeName, department]\n attach holder = cards.cardholder {\n holder: owner\n expose create as enrol_employee\n expose activate as activate_employee\n expose suspend as suspend_employee\n expose resume as restore_employee\n expose close as close_employee_access\n expose operator_close as remove_employee_access\n }\n attach card = cards.card {\n holder: holder, person: owner, issuer: operator, spend_limit: 5000 SAR\n expose create as issue_card\n expose activate as activate_card\n expose freeze as freeze_lost_card\n expose unfreeze as restore_found_card\n expose issuer_freeze as block_card\n expose issuer_unfreeze as unblock_card\n expose cancel as cancel_card\n expose issuer_cancel as retire_employee_card\n }\n // Supply the gross invoice amount and expiresAt, such as 24 hours after\n // ordering. Pending and approved authorizations expire without capture.\n attach payment = cards.authorization {\n card: card, merchant: supplier, issuer: operator\n expose create as request_supplier_payment\n expose approve as approve_payment\n expose decline as decline_payment\n expose capture as capture_delivered_order\n expose reverse as cancel_supplier_reservation\n }\n attach receipt = cards.transaction {\n authorization: payment\n expose create as record_captured_purchase\n expose refund as refund_supplier_purchase\n }\n attach complaint = cards.dispute {\n transaction: receipt, issuer: operator, within: 30d\n expose create as dispute_supplier_purchase\n expose review as review_purchase_dispute\n expose win as uphold_dispute_and_refund\n }\n // A dispute unresolved after 30 days becomes lost. A refund always needs\n // the supplier's funds; the card header does not prove card-network settlement.\n}\n" },
3
+ { "id": "collections", "title": "Jeddah cafe equipment finance", "summary": "Jeddah cafe equipment finance lends 24,000 SAR over 12 months and refers debt seven days overdue. Its agency earns 10% of each recovery from the lender, with at most four contacts per 30 days.", "headers": ["collections", "financing"], "source": "// Jeddah cafe equipment finance lends 24,000 SAR over 12 months and refers debt seven days overdue.\n// Its agency earns 10% of each recovery from the lender, with at most four contacts per 30 days.\nprogram business_collections \"Jeddah cafe equipment finance\"\nuse collections\nuse financing\nparty agency: business\n\n// Bind agency to the collector. The cafe owns the facility. Set price to\n// 24,000 SAR: 6% flat profit is 1,440 SAR, repaid in twelve 2,120 SAR payments.\n// Loan fee: 0%, tax: 0% on principal. The agency invoices 15% VAT on its\n// recovery service outside collections.case, which posts only the 10% fee.\nobject facility \"Cafe equipment facility\" {\n fields { businessName: text, purpose: text, price: money }\n columns: [businessName, purpose, price]\n attach allowance = financing.limits {\n borrower: owner, per_borrower: 100000 SAR\n expose create as request_borrower_limit\n expose approve as approve_borrower\n }\n attach budget = financing.portfolio_limit {\n limit: 2000000 SAR\n expose create as create_lending_budget\n expose approve as approve_budget\n }\n // Approve both limits and provide twelve future due dates before disbursement.\n attach loan = financing.installments {\n borrower: owner, capital: operator, share: 0%\n months: 12, pricing: flat_total, profit_rate: 6%, disburse_to: borrower\n payoff_rebate: 100%, refund_within: 30d, write_off_after: 90d\n limits: allowance, portfolio: budget\n expose create as quote_equipment_loan\n expose sign as sign_loan\n expose disburse as release_loan\n expose cancel as decline_loan_quote\n expose void as cancel_unfunded_loan\n expose payoff as repay_early\n expose complete as close_repaid_loan\n }\n // Select matching plan, overdue slice and pending payment when opening.\n // Recovery pays that payment, not necessarily the whole remaining debt.\n attach recovery = collections.case {\n on: loan, agency: agency, capital: operator, overdue: 7d, fee: 10%\n expose create as refer_overdue_instalment\n expose assign as assign_agency\n expose recover as collect_referred_payment\n expose recall as recall_collection_case\n expose return_uncollected as return_uncollected_case\n }\n attach contact = collections.contact {\n case: recovery, agency: agency\n max_contacts: 4, window: 30d, contact_from: 9, contact_until: 18\n timezone: \"Asia/Riyadh\"\n expose create as record_collection_contact\n }\n}\n\nexpose facility.contact.outcome.create as record_contact_outcome\nexpose facility.loan.payment.create as record_repayment\nexpose facility.loan.payment.pay as pay_instalment\nexpose facility.loan.payment.refund as refund_mistaken_repayment\nexpose facility.loan.payoff_quote.create as request_payoff_quote\n// A disputed contact can be recorded, then capital can recall the case.\n// Uncollectible principal needs a separate capital decision after 90 days.\nexpose facility.loan.write_off_request.create as request_overdue_write_off\nexpose facility.loan.write_off_request.apply as approve_overdue_write_off\nexpose facility.loan.write_off_request.cancel as cancel_write_off_request\n" },
4
+ { "id": "escrow", "title": "Khobar used laptops", "summary": "Khobar used laptops holds a buyer's 2,300 SAR until the laptop arrives and passes inspection. Delivery has seven days; the buyer has 48 hours to accept or dispute before the operator reviews the sale.", "headers": ["escrow"], "source": "// Khobar used laptops holds a buyer's 2,300 SAR until the laptop arrives and passes inspection.\n// Delivery has seven days; the buyer has 48 hours to accept or dispute before the operator reviews the sale.\nprogram used_device_sales \"Khobar used laptops\"\nuse escrow\nparty seller: business\n\n// Bind seller to the refurbisher. Set price to the agreed gross invoice, for\n// example 2,300 SAR. The company keeps 5%, 115 SAR, plus 15% VAT on that fee.\n// Seller receives 2,167.75 SAR. Any VAT on the laptop is on the seller's invoice.\nobject device \"Laptop purchase\" {\n fields { model: text, condition: text, serialNumber: text, price: money }\n columns: [model, condition, serialNumber, price]\n attach sale = escrow.hold {\n payer: owner, payee: seller\n fee: { seller: 5%, tax: 15% }\n deliver_within: 7d, accept_within: 48h\n dispute: { refund_after: return_verified }\n expose create as agree_purchase\n expose fund as pay_for_laptop\n expose deliver as confirm_delivery\n expose accept as accept_laptop\n expose dispute as report_problem\n expose verify_return as verify_returned_laptop\n expose refund as refund_buyer\n expose refund_undelivered as refund_missing_delivery\n expose settle_release as resolve_in_seller_favour\n expose settle_return as resolve_in_buyer_favour\n expose settle_refund as finish_buyer_refund\n expose cancel as cancel_unpaid_purchase\n }\n}\n" },
5
+ { "id": "financing", "title": "Riyadh language academy finance", "summary": "Riyadh language academy finance pays 6,900 SAR tuition to the academy at enrolment. The student repays three monthly instalments of 2,300 SAR with no financing profit or late fee.", "headers": ["financing"], "source": "// Riyadh language academy finance pays 6,900 SAR tuition to the academy at enrolment.\n// The student repays three monthly instalments of 2,300 SAR with no financing profit or late fee.\nprogram tuition_instalments \"Riyadh language academy finance\"\nuse financing\nparty academy: business\n\n// Bind academy to the training business. Its 6,000 SAR course plus 15% VAT\n// is invoiced outside this plan. Set price to the gross 6,900 SAR invoice.\n// Financing fee: 0%, tax: 0% on principal repayments; no separate service is sold.\nobject enrolment \"Language course finance\" {\n fields { student: text, course: text, price: money }\n columns: [student, course, price]\n attach allowance = financing.limits {\n borrower: owner, per_borrower: 12000 SAR\n expose create as request_student_allowance\n expose approve as approve_student\n }\n attach budget = financing.portfolio_limit {\n limit: 500000 SAR\n expose create as create_tuition_budget\n expose approve as approve_budget\n }\n // Approve both limits before funding. Supply three future monthly dates\n // and a unique settlementIdentity. Funding must precede the first due date.\n attach tuition = financing.installments {\n borrower: owner, capital: operator, seller: academy\n months: 3, pricing: flat_total, profit_rate: 0%, share: 0%\n disburse_to: seller, limits: allowance, portfolio: budget\n payoff_rebate: 100%, refund_within: 30d, write_off_after: 90d\n max_extension: 30d, max_amendments: 1, amendment_expiry: 7d\n expose create as quote_tuition_plan\n expose sign as sign_tuition_plan\n expose disburse as pay_academy\n expose cancel as decline_tuition_quote\n expose void as cancel_unfunded_plan\n expose payoff as repay_early\n expose complete as close_repaid_plan\n }\n}\n\nexpose enrolment.tuition.payment.create as record_student_payment\nexpose enrolment.tuition.payment.pay as pay_instalment\nexpose enrolment.tuition.payment.refund as refund_mistaken_payment\nexpose enrolment.tuition.payoff_quote.create as request_payoff_quote\n// A hardship extension adds no profit and needs the student's acceptance.\nexpose enrolment.tuition.amendment.create as propose_payment_extension\nexpose enrolment.tuition.amendment.accept as accept_payment_extension\nexpose enrolment.tuition.amendment.decline as decline_payment_extension\nexpose enrolment.tuition.amendment.withdraw as withdraw_payment_extension\nexpose enrolment.tuition.write_off_request.create as request_overdue_write_off\nexpose enrolment.tuition.write_off_request.apply as approve_overdue_write_off\nexpose enrolment.tuition.write_off_request.cancel as cancel_write_off_request\n" },
6
+ { "id": "insurance", "title": "Jeddah device cover", "summary": "Jeddah device cover sells a 1,725 SAR tablet and a 115 SAR annual protection period. The retailer keeps 10% of each premium; cancelled future periods reverse that commission and the insurer's portion.", "headers": ["insurance", "money"], "source": "// Jeddah device cover sells a 1,725 SAR tablet and a 115 SAR annual protection period.\n// The retailer keeps 10% of each premium; cancelled future periods reverse that commission and the insurer's portion.\nprogram device_insurance \"Jeddah device cover\"\nuse insurance\nuse money\n\n// The retailer invoices the tablet at 1,500 SAR plus 15% VAT outside\n// money.transfer. Purchase fee: 0%. The transfer pays the gross 1,725 SAR.\n// The insurer invoices 100 SAR plus 15% VAT for the premium outside\n// insurance.cover, which has no tax setting.\n// At 115 SAR premium, commission is 11.50 SAR and insurer cash is 103.50 SAR.\nobject device \"Insured tablet\" {\n fields { model: text, serialNumber: text, purchaseDate: date }\n columns: [model, serialNumber, purchaseDate, coverExpiresAt]\n attach purchase = money.transfer {\n payer: owner, payee: operator, amount: 1725 SAR\n economics pay { purpose: earning, sourceParty: owner }\n expose create as create_purchase\n expose pay as pay_for_tablet\n expose cancel as cancel_unpaid_purchase\n }\n // Bind the insurer's registered adapter before launch. conformance_boundary\n // is only the sandbox adapter. Set the cover expiry to the policy end date.\n attach protection = insurance.cover {\n holder: owner, broker: operator, adapter: \"conformance_boundary\"\n covers: purchase, premium: 115 SAR, commission: 10%, claim_limit: 1500 SAR\n rename { expiresAt: coverExpiresAt }\n expose create as request_cover\n expose activate as activate_cover\n expose cancel as cancel_and_refund_future_cover\n }\n // Supply loss evidence, the claim amount and its decision expiry.\n // The 1,500 SAR limit applies to all approved and paid claims on the cover.\n attach claim = insurance.claim {\n cover: protection, inspector: operator\n expose create as report_damage\n expose approve as approve_claim\n expose deny as deny_claim\n expose pay as pay_claim\n }\n}\n\n// Create the annual period with startsAt and endsAt, then collect its premium.\n// Cancelling cover refunds only paid periods that have not started.\nexpose device.protection.slice.create as create_premium_period\nexpose device.protection.slice.collect as pay_cover_premium\n" },
7
+ { "id": "lending", "title": "Qassim bakery funding", "summary": "Qassim bakery funding raises 30,000 SAR for ovens from investors who commit at least 1,000 SAR each. An unclosed round refunds its wallets at expiry; funded loans distribute repayments or record investor losses.", "headers": ["lending", "financing", "wallet"], "source": "// Qassim bakery funding raises 30,000 SAR for ovens from investors who commit at least 1,000 SAR each.\n// An unclosed round refunds its wallets at expiry; funded loans distribute repayments or record investor losses.\nprogram community_business_lending \"Qassim bakery funding\"\nuse lending\nuse financing\nuse wallet\n\n// Set price to 30,000 SAR. The bakery owns the record; investors act as actor.\n// Company fee: 5% of collected profit, with 15% VAT on that fee, at distribution.\n// Principal and wallet loads have fee 0% and tax 0%; no service is sold there.\nobject business \"Bakery oven funding\" {\n fields { businessName: text, purpose: text, price: money }\n columns: [businessName, purpose, price, fundingClosesAt]\n attach allowance = financing.limits {\n borrower: owner, per_borrower: 100000 SAR\n expose create as request_bakery_limit\n expose approve as approve_borrower\n }\n attach budget = financing.portfolio_limit {\n limit: 2000000 SAR\n expose create as create_funding_budget\n expose approve as approve_budget\n }\n // Twelve future monthly dates, 6% annual profit on the declining balance.\n // Close the fully subscribed round before separately disbursing the loan.\n attach loan = financing.installments {\n borrower: owner, capital: operator, share: 0%\n months: 12, pricing: amortizing, profit_rate: 6%, disburse_to: borrower\n payoff_rebate: 100%, refund_within: 30d, write_off_after: 90d\n limits: allowance, portfolio: budget\n expose create as quote_bakery_loan\n expose sign as sign_loan\n expose disburse as release_loan\n expose cancel as decline_loan_quote\n expose void as cancel_unfunded_loan\n expose payoff as repay_early\n expose complete as close_repaid_loan\n }\n attach investor_balance = wallet.balance {\n holder: actor, spend_limit: 7500 SAR, topup_fee: 0%\n expose create as create_investor_balance\n expose activate as open_wallet\n expose topup as add_funds\n expose withdraw as withdraw_available_funds\n expose close as close_empty_wallet\n }\n attach funding = lending.round {\n borrower: owner, plan: loan, minimum_ticket: 1000 SAR, investor_cap: 25%\n rename { closesAt: fundingClosesAt }\n expose create as open_funding_round\n expose close as close_fully_funded_round\n }\n attach investment = lending.commitment {\n round: funding, wallet: investor_balance, investor: actor\n expose create as commit_investment\n expose withdraw as withdraw_before_close\n }\n // For each recorded cash settlement, prepare once and create one share per\n // funded commitment. The fee applies to profit, never returned principal.\n attach returns = lending.distribution {\n round: funding, receipt: loan.settlement, mode: cash, fee: 5%, tax: 15%\n expose create as record_cash_settlement\n expose prepare_cash as calculate_investor_returns\n expose distribute_cash as pay_investor_wallets\n }\n // Loss distribution moves claims only. It does not debit another cash fee.\n attach losses = lending.distribution {\n round: funding, receipt: loan.settlement, mode: loss, fee: 0%, tax: 0%\n expose create as record_loss_settlement\n expose prepare_loss as calculate_investor_losses\n expose distribute_loss as allocate_investor_losses\n }\n}\n\nexpose business.loan.payment.create as record_repayment\nexpose business.loan.payment.pay as pay_instalment\nexpose business.loan.payment.refund as refund_mistaken_repayment\nexpose business.loan.payoff_quote.create as request_payoff_quote\nexpose business.loan.write_off_request.create as request_overdue_write_off\nexpose business.loan.write_off_request.apply as approve_overdue_write_off\nexpose business.loan.write_off_request.cancel as cancel_write_off_request\nexpose business.returns.share.create as create_return_share\nexpose business.losses.share.create as create_loss_share\n" },
8
+ { "id": "library", "title": "Riyadh used van finance", "summary": "Riyadh used van finance funds a 34,500 SAR van over three monthly instalments. The dealer is paid after delivery and acceptance; a verified return unwinds financing before the buyer gets a refund.", "headers": ["escrow", "financing"], "source": "// Riyadh used van finance funds a 34,500 SAR van over three monthly instalments.\n// The dealer is paid after delivery and acceptance; a verified return unwinds financing before the buyer gets a refund.\nprogram cars \"Riyadh used van finance\"\nuse escrow\nuse financing\nparty dealer: business\n\n// Bind dealer to the vehicle seller. Set price to its gross 34,500 SAR invoice;\n// vehicle VAT stays on that invoice. The platform fee is 2% plus 15% VAT\n// on the fee: 690 SAR and 103.50 SAR. The dealer receives 33,706.50 SAR.\nobject car \"Financed van purchase\" {\n fields { make: text, model: text, year: integer, vin: text, price: money }\n columns: [make, model, year, vin, price]\n attach sale = escrow.hold {\n payer: actor, payee: dealer\n fee: { seller: 2%, tax: 15% }\n deliver_within: 7d, accept_within: 3d\n expose create as agree_van_purchase\n expose fund as pay_cash_instead\n expose deliver as confirm_van_delivery\n expose accept as accept_van\n expose dispute as dispute_van_condition\n expose verify_return as verify_returned_van\n expose refund as refund_buyer_after_unwind\n expose refund_undelivered as refund_undelivered_cash_purchase\n expose settle_release as resolve_for_dealer\n expose settle_return as resolve_for_buyer\n expose settle_refund as finish_buyer_refund\n expose cancel as cancel_unfunded_purchase\n }\n // Limits are shared across purchases. Approve each once before disbursement.\n attach limits = financing.limits {\n borrower: actor, per_borrower: 60000 SAR\n expose create as request_borrower_limit\n expose approve as approve_borrower_limit\n }\n attach ceiling = financing.portfolio_limit {\n limit: 1500000 SAR\n expose create as create_lending_budget\n expose approve as approve_lending_budget\n }\n // At 34,500 SAR, 2.5% flat profit is 862.50 SAR for the whole term.\n // Financing fee: 0%, tax: 0% on principal; no separate financing service fee.\n // Supply three future monthly dates and a unique settlementIdentity.\n attach plan = financing.installments {\n borrower: actor, capital: operator, share: 0%\n months: 3, pricing: flat_total, profit_rate: 2.5%\n funds: sale, limits: limits, portfolio: ceiling\n returned_goods: refund_all, refund_within: 30d, write_off_after: 90d\n expose create as finance\n expose sign as sign_finance_agreement\n expose disburse as fund_van_escrow\n expose cancel as decline_finance_quote\n expose void as cancel_signed_finance\n expose payoff as repay_early\n expose complete as close_repaid_finance\n // Refund paid instalments before unwinding an active plan. Then refund\n // the escrow remainder. A live plan blocks the escrow's direct refund.\n expose unwind as unwind_returned_van_finance\n expose unwind_undelivered as unwind_missing_van_finance\n expose unwind_paid as unwind_repaid_van_finance\n }\n}\n\nexpose car.plan.payment.create as record_repayment\nexpose car.plan.payment.pay as pay_instalment\nexpose car.plan.payment.refund as refund_mistaken_repayment\nexpose car.plan.payoff_quote.create as request_payoff_quote\nexpose car.plan.write_off_request.create as request_overdue_write_off\nexpose car.plan.write_off_request.apply as approve_overdue_write_off\nexpose car.plan.write_off_request.cancel as cancel_write_off_request\n" },
9
+ { "id": "marketplace", "title": "Riyadh design market", "summary": "Riyadh design market sells a 2,000 SAR restaurant menu project with delivery in seven days. The company keeps 10% plus 15% VAT on its fee; the designer receives 1,770 SAR after client acceptance.", "headers": ["marketplace", "escrow"], "source": "// Riyadh design market sells a 2,000 SAR restaurant menu project with delivery in seven days.\n// The company keeps 10% plus 15% VAT on its fee; the designer receives 1,770 SAR after client acceptance.\nprogram freelance_marketplace \"Riyadh design market\"\nuse marketplace\nuse escrow\nparty designer: business\n\n// Bind designer to the design studio. The client owns the project record.\n// Set price to 2,000 SAR and use the same field for offer, order and escrow.\n// Any VAT on the designer's work belongs on its own invoice.\nobject project \"Menu design project\" {\n fields { brief: text, deliverable: text, price: money }\n columns: [brief, deliverable, price]\n attach offer = marketplace.listing {\n seller: designer\n rename { title: deliverable, price: price }\n expose create as draft_offer\n expose publish as publish_offer\n expose withdraw as withdraw_offer\n expose sell as close_sold_offer\n }\n attach order = marketplace.order {\n listing: offer, buyer: owner, fulfiller: designer\n rename { price: price }\n expose create as request_design\n expose commit as place_order\n expose fulfill as finish_order\n expose cancel as cancel_order\n }\n // Finishing the order does not release money. Run the payment actions too.\n attach payment = escrow.hold {\n payer: owner, payee: designer\n fee: { seller: 10%, tax: 15% }\n deliver_within: 7d, accept_within: 3d\n dispute: { refund_after: return_verified }\n expose create as create_payment\n expose fund as fund_project\n expose deliver as submit_work\n expose accept as accept_work\n expose dispute as dispute_work\n expose verify_return as verify_rejected_work\n expose refund as refund_client\n expose refund_undelivered as refund_missed_delivery\n expose settle_release as resolve_for_designer\n expose settle_return as resolve_for_client\n expose settle_refund as finish_client_refund\n expose cancel as cancel_unpaid_project\n }\n}\n" },
10
+ { "id": "money", "title": "Riyadh tutoring studio", "summary": "Riyadh tutoring studio charges 172.50 SAR for a private Arabic lesson. A paid booking can be refunded before the lesson or if the tutor cannot teach.", "headers": ["money"], "source": "// Riyadh tutoring studio charges 172.50 SAR for a private Arabic lesson.\n// A paid booking can be refunded before the lesson or if the tutor cannot teach.\nprogram tutoring_studio \"Riyadh tutoring studio\"\nuse money\n\n// The customer is the object's owner. Fee: 0% on top of the lesson price.\n// The studio invoices 150 SAR plus 15% VAT, 22.50 SAR, outside this transfer.\n// money.transfer sends the gross price to the studio without splitting VAT.\ninstrument lesson_booking(payment: ref<money.transfer>, student: party) {\n summary: \"Confirm a paid lesson, record teaching or refund the student.\"\n fields { payment: ref<payment>, startsAt: date }\n lifecycle { states: [booked, taught, refunded], initial: booked }\n action create {\n actor: { party: student }\n requires self.payment in [paid]\n requires unique \"paid_lesson\" on [self.payment]\n requires self.startsAt > self.now\n }\n action teach {\n from: booked, to: taught, actor: { party: programOperator }\n due: { at: self.startsAt }\n subject { lessonNotes: text }\n }\n action cancel {\n from: booked, to: refunded, actor: { party: student }\n deadline: { at: self.startsAt }\n moves self.payment.amount from programOperator to student\n }\n action tutor_unavailable {\n from: booked, to: refunded, actor: { party: programOperator }\n subject { cancellationReason: text }\n moves self.payment.amount from programOperator to student\n }\n}\n\nobject lesson \"Arabic lesson\" {\n fields { student: text, tutor: text, startsAt: date }\n columns: [student, tutor, startsAt]\n attach payment = money.transfer {\n payer: owner, payee: operator, amount: 172.50 SAR\n economics pay { purpose: earning, sourceParty: owner }\n expose create as create_payment\n expose pay as pay_for_lesson\n expose cancel as cancel_unpaid_lesson\n }\n attach booking = lesson_booking {\n payment: payment, student: owner\n rename { startsAt: startsAt }\n expose create as confirm_paid_lesson\n expose teach as record_lesson_taught\n expose cancel as cancel_and_refund_lesson\n expose tutor_unavailable as refund_cancelled_lesson\n }\n}\n" },
11
+ { "id": "rental-deposit", "title": "Dammam equipment hire", "summary": "Dammam equipment hire holds a 1,000 SAR deposit for a business renter. Return the deposit in full, or deduct a single 50 SAR late charge plus 7.50 SAR VAT.", "headers": [], "source": "// Dammam equipment hire holds a 1,000 SAR deposit for a business renter.\n// Return the deposit in full, or deduct a single 50 SAR late charge plus 7.50 SAR VAT.\nprogram equipment_rental \"Dammam equipment hire\"\nparty renter: business\n\n// Bind renter to the business hiring the equipment. The deposit has fee 0%\n// and tax 0% because it stays refundable principal. The late service has 15% VAT.\ninstrument deposit {\n summary: \"Hold security until return, with one disclosed late charge.\"\n fields {\n renter: account of renter\n held: account of self\n amount: money = 1000 SAR\n lateFee: money = 50 SAR\n lateTax: money = rate(self.lateFee, 15%)\n startsAt: date\n dueAt: date\n refund: money?\n }\n lifecycle { states: [pending, funded, returned, cancelled], initial: pending }\n action create {\n actor: { party: renter }\n requires self.dueAt > self.now\n requires self.startsAt > self.now\n requires self.dueAt > self.startsAt\n }\n action fund {\n from: pending, to: funded, actor: { party: renter }\n deadline: { at: self.startsAt }\n moves self.amount from self.renter to self.held\n }\n action return_on_time {\n from: funded, to: returned, actor: { party: programOperator }\n deadline: { at: self.dueAt }\n subject { returnReference: text }\n moves self.held.balance from self.held to self.renter\n }\n action return_late {\n from: funded, to: returned, actor: { party: programOperator }\n due: { at: self.dueAt }\n subject { returnReference: text }\n calculate: [{ target: refund, op: subtract, base: { field: self.held.balance }, subtract: [{ field: self.lateFee }, { field: self.lateTax }] }]\n moves self.lateFee from self.held to programOperator\n moves self.lateTax from self.held to programTax\n moves self.refund from self.held to self.renter\n }\n action refund_before_pickup {\n from: funded, to: cancelled, actor: { party: renter }\n deadline: { at: self.startsAt }\n moves self.held.balance from self.held to self.renter\n }\n action cancel { from: pending, to: cancelled, actor: { party: renter } }\n}\n\nobject rental \"Equipment deposit\" {\n fields { equipment: text, serialNumber: text, renterName: text }\n columns: [equipment, serialNumber, renterName, startsAt, dueAt]\n attach security = deposit {\n rename { startsAt: startsAt, dueAt: dueAt }\n expose create as agree_rental\n expose fund as pay_deposit\n expose return_on_time as return_equipment\n expose return_late as return_equipment_late\n expose refund_before_pickup as cancel_before_pickup\n expose cancel as cancel_unpaid_rental\n }\n}\n\nhide deposit.create\nhide deposit.fund\nhide deposit.return_on_time\nhide deposit.return_late\nhide deposit.refund_before_pickup\nhide deposit.cancel\n" },
12
+ { "id": "repair-approval", "title": "Jeddah phone repair", "summary": "Jeddah phone repair quotes 350 SAR plus 52.50 SAR VAT for a screen replacement. The customer approves and funds the repair; acceptance pays the shop, while a failed repair returns all 402.50 SAR.", "headers": [], "source": "// Jeddah phone repair quotes 350 SAR plus 52.50 SAR VAT for a screen replacement.\n// The customer approves and funds the repair; acceptance pays the shop, while a failed repair returns all 402.50 SAR.\nprogram repair_shop \"Jeddah phone repair\"\n\n// Fee: 0% beyond the repair price. The shop keeps 350 SAR and posts 15% VAT.\ninstrument assessment(customer: party) {\n summary: \"Inspect, approve, hold payment and settle a screen repair.\"\n fields {\n held: account of self\n price: money = 350 SAR\n vat: money = rate(self.price, 15%)\n total: money = sum(self.price, self.vat)\n quoteExpiresAt: date\n repairDueAt: date\n inspectedAt: date?\n approvedAt: date?\n }\n lifecycle { states: [submitted, inspected, approved, ready_for_collection, disputed, completed, refunded, rejected, expired], initial: submitted }\n action create {\n actor: { party: customer }\n requires self.quoteExpiresAt > self.now\n requires self.repairDueAt > self.quoteExpiresAt\n }\n action inspect {\n from: submitted, to: inspected, actor: { party: programOperator }\n deadline: { at: self.quoteExpiresAt }\n subject { inspectionNotes: text }\n set: { inspectedAt: { field: self.now } }\n }\n action approve {\n from: inspected, to: approved, actor: { party: customer }\n deadline: { at: self.quoteExpiresAt }\n subject { approvalReference: text }\n set: { approvedAt: { field: self.now } }\n moves self.total from customer to self.held\n }\n action reject { from: [submitted, inspected], to: rejected, actor: { party: customer } }\n action expire { from: [submitted, inspected], to: expired, actor: clock, due: { at: self.quoteExpiresAt } }\n action complete {\n from: approved, to: ready_for_collection, actor: { party: programOperator }\n deadline: { at: self.repairDueAt }\n subject { completionNotes: text }\n }\n action accept {\n from: ready_for_collection, to: completed, actor: { party: customer }\n moves self.price from self.held to programOperator\n moves self.vat from self.held to programTax\n }\n action dispute {\n from: ready_for_collection, to: disputed, actor: { party: customer }\n subject { faultDescription: text }\n }\n action refund {\n from: [approved, ready_for_collection, disputed], to: refunded, actor: { party: programOperator }\n subject { refundReason: text }\n moves self.held.balance from self.held to customer\n }\n action refund_overdue {\n from: approved, to: refunded, actor: { party: customer }\n due: { at: self.repairDueAt }\n moves self.held.balance from self.held to customer\n }\n action accept_resolution {\n from: disputed, to: completed, actor: { party: customer }\n subject { resolutionReference: text }\n moves self.price from self.held to programOperator\n moves self.vat from self.held to programTax\n }\n}\n\nobject repair \"Screen repair\" {\n fields { item: text, serialNumber: text, problem: text }\n columns: [item, serialNumber, problem, quoteExpiresAt, repairDueAt]\n attach review = assessment {\n customer: owner\n rename { quoteExpiresAt: quoteExpiresAt, repairDueAt: repairDueAt }\n expose create as request_repair\n expose inspect as inspect_repair\n expose approve as approve_and_pay\n expose reject as decline_quote\n expose complete as mark_ready_for_collection\n expose accept as accept_repair\n expose dispute as report_failed_repair\n expose refund as refund_repair\n expose refund_overdue as refund_missed_deadline\n expose accept_resolution as accept_repair_resolution\n }\n}\n" },
13
+ { "id": "reporting", "title": "Tabuk workshop equipment finance", "summary": "Tabuk workshop equipment finance lends 46,000 SAR and reports monthly repayments and arrears. Ageing bands at 30, 60 and 90 days distinguish overdue balances from loans written off after 90 days.", "headers": ["reporting", "financing"], "source": "// Tabuk workshop equipment finance lends 46,000 SAR and reports monthly repayments and arrears.\n// Ageing bands at 30, 60 and 90 days distinguish overdue balances from loans written off after 90 days.\nprogram equipment_loan_reports \"Tabuk workshop equipment finance\"\nuse reporting\nuse financing\n\n// Set price to 46,000 SAR, the workshop's 40,000 SAR equipment invoice plus\n// 15% VAT charged by its supplier outside this loan. Profit is 6% annually on\n// the declining balance. Loan fee: 0%, tax: 0% on principal repayments.\n// Reports have no customer fee or tax; they are the lender's internal records.\nobject purchase \"Workshop equipment loan\" {\n fields { businessName: text, equipment: text, invoiceReference: text, price: money }\n columns: [businessName, equipment, invoiceReference, price]\n attach allowance = financing.limits {\n borrower: owner, per_borrower: 200000 SAR\n expose create as request_workshop_limit\n expose approve as approve_business\n }\n attach budget = financing.portfolio_limit {\n limit: 5000000 SAR\n expose create as create_lending_budget\n expose approve as approve_budget\n }\n // Create twelve future monthly dates and approve both limits before funding.\n attach loan = financing.installments {\n borrower: owner, capital: operator, share: 0%\n months: 12, pricing: amortizing, profit_rate: 6%, disburse_to: borrower\n payoff_rebate: 100%, refund_within: 30d, write_off_after: 90d\n limits: allowance, portfolio: budget\n expose create as quote_equipment_loan\n expose sign as sign_purchase_loan\n expose disburse as fund_purchase\n expose cancel as decline_loan_quote\n expose void as cancel_unfunded_loan\n expose payoff as repay_early\n expose complete as close_repaid_loan\n }\n // Report requests use reporting routes. This attachment declares their\n // datasets and retention; it neither collects money nor sends a reminder.\n attach reports = reporting.portfolio {\n on: loan, default_days: 90, retention_years: 10\n aging_first_days: 30, aging_second_days: 60, aging_third_days: 90\n expose create as enable_portfolio_reports\n }\n}\n\nexpose purchase.loan.payment.create as record_repayment\nexpose purchase.loan.payment.pay as pay_instalment\nexpose purchase.loan.payment.refund as refund_mistaken_repayment\nexpose purchase.loan.payoff_quote.create as request_payoff_quote\n// Write-off is a capital decision, not an automatic consequence of a report.\nexpose purchase.loan.write_off_request.create as request_overdue_write_off\nexpose purchase.loan.write_off_request.apply as approve_overdue_write_off\nexpose purchase.loan.write_off_request.cancel as cancel_write_off_request\n" },
14
+ { "id": "savings", "title": "Al Khobar shopkeepers circle", "summary": "Al Khobar shopkeepers circle collects 500 SAR from each of six members every month. Each member receives one 3,000 SAR pot in order; missed contributions remain payable and an unfunded pot waits.", "headers": ["savings"], "source": "// Al Khobar shopkeepers circle collects 500 SAR from each of six members every month.\n// Each member receives one 3,000 SAR pot in order; missed contributions remain payable and an unfunded pot waits.\nprogram neighbourhood_savings \"Al Khobar shopkeepers circle\"\nuse savings\n\n// Fee: 0%. Tax: 0% because this circle only returns members' principal and\n// charges no service. The organiser keeps none of the 18,000 SAR contributed.\nobject group \"Shopkeepers savings circle\" {\n fields { groupName: text, purpose: text }\n columns: [groupName, purpose]\n attach circle = savings.circle {\n contribution: 500 SAR, members: 6, starts: 2027-01-01\n // At creation supply circleDates: the first of January through June 2027.\n expose create as agree_circle_calendar\n expose disband as cancel_unstarted_circle\n expose close as close_completed_circle\n }\n attach membership = savings.membership {\n circle: circle, member: actor\n // Assign a distinct seat from 1 to 6 to each member at creation.\n expose create as join_circle\n expose activate as confirm_membership_schedule\n expose withdraw as leave_cancelled_circle\n }\n}\n\n// Create periods 1 through 6 for EVERY member before activating membership.\n// The clock activates the circle when all six have joined. Then confirm each\n// membership. Contributions and payouts run on that calendar, including after\n// a member has received their pot. A missed collection is not a promised retry.\nexpose group.membership.contribution.create as schedule_member_contribution\n" },
15
+ { "id": "serviced", "title": "Dammam delivery van finance", "summary": "Dammam delivery van finance funds a 69,000 SAR van with 10% down and 36 monthly instalments. It records reminders, late charges, hardship extensions, early repayment and financed returns.", "headers": ["escrow", "financing", "collections"], "source": "// Dammam delivery van finance funds a 69,000 SAR van with 10% down and 36 monthly instalments.\n// It records reminders, late charges, hardship extensions, early repayment and financed returns.\nprogram car_financing \"Dammam delivery van finance\"\nuse escrow\nuse financing\nuse collections\nparty dealer: business\n\n// The dealer invoices 60,000 SAR plus 15% VAT. Set price to 69,000 SAR.\n// The company keeps a 1% dealer fee, 690 SAR, with 103.50 SAR VAT on that fee.\nobject car \"Delivery van finance\" {\n fields { make: text, model: text, year: integer, vin: text, price: money }\n columns: [make, model, year, vin, price]\n attach sale = escrow.hold {\n payer: actor, payee: dealer\n fee: { seller: 1%, tax: 15% }, deliver_within: 14d, accept_within: 3d\n expose create as agree_van_purchase\n expose fund as pay_cash_instead\n expose deliver as confirm_delivery\n expose accept as accept_van\n expose dispute as dispute_van\n expose verify_return as verify_returned_van\n expose refund as refund_after_finance_unwind\n expose refund_undelivered as refund_missing_cash_purchase\n expose settle_release as resolve_for_dealer\n expose settle_return as resolve_for_buyer\n expose settle_refund as finish_buyer_refund\n expose cancel as cancel_and_return_down_payment\n }\n attach limits = financing.limits {\n borrower: actor, per_borrower: 250000 SAR\n expose create as request_borrower_limit\n expose approve as approve_borrower_limit\n }\n attach ceiling = financing.portfolio_limit {\n limit: 10000000 SAR\n expose create as create_lending_budget\n expose approve as approve_lending_budget\n }\n // Down payment is 6,900 SAR. Capital is 62,100 SAR; total flat profit is\n // 5,278.50 SAR. Financing service fee: 0%, tax: 0% on principal repayments.\n // Supply 36 future monthly dates. Approve limits before collecting and funding.\n attach plan = financing.installments {\n borrower: actor, capital: operator, share: 0%\n months: 36, pricing: flat_total, profit_rate: 8.5%, down_payment: 10%\n apply: fines_profit_principal, payoff_rebate: 100%, write_off_after: 90d\n refund_within: 30d, payoff_quote_expiry: 1h, returned_goods: refund_all\n max_extension: 60d, max_amendments: 2, amendment_expiry: 7d\n funds: sale, limits: limits, portfolio: ceiling\n expose create as finance\n expose sign as sign_contract\n expose collect_down_payment as pay_down_payment\n expose disburse as fund_van_escrow\n expose cancel as decline_finance_quote\n expose void as cancel_signed_finance\n expose payoff as repay_early\n expose complete as close_repaid_finance\n // Before an active-plan unwind, refund collected payments and fines,\n // and waive assessed fines. Then refund any remaining escrow balance.\n expose unwind as unwind_returned_van_finance\n expose unwind_undelivered as unwind_missing_van_finance\n expose unwind_paid as unwind_repaid_van_finance\n }\n // Create one assessment against the overdue slice. The clock assesses after\n // three days; repayments collect it. cap bounds evidenced recovery COSTS,\n // not the 50 SAR fine. Any charge VAT is invoiced outside this header.\n attach late = financing.late_charge {\n on: plan, grace: 3d, fine: 50 SAR, cap: 25 SAR\n fines_to: operator, costs_to: operator, borrower: actor\n expose create as record_late_assessment\n expose cancel as cancel_proposed_assessment\n expose refund as refund_collected_fine\n }\n attach reminders = collections.reminder {\n on: plan, operator: operator, before_days: 3, overdue_days: 1\n max_per_day: 1, send_from: 9, send_until: 18, timezone: \"Asia/Riyadh\"\n expose create as schedule_instalment_reminders\n expose dispatch as send_payment_reminder\n }\n}\n\nexpose car.plan.payment.create as record_repayment\nexpose car.plan.payment.pay as pay_instalment\nexpose car.plan.payment.refund as refund_mistaken_repayment\nexpose car.plan.payoff_quote.create as request_payoff_quote\nexpose car.plan.amendment.create as propose_hardship_extension\nexpose car.plan.amendment.accept as accept_hardship_extension\nexpose car.plan.amendment.decline as decline_hardship_extension\nexpose car.plan.amendment.withdraw as withdraw_hardship_extension\nexpose car.plan.write_off_request.create as request_overdue_write_off\nexpose car.plan.write_off_request.apply as approve_overdue_write_off\nexpose car.plan.write_off_request.cancel as cancel_write_off_request\nexpose car.late.waiver_request.create as request_fine_waiver\nexpose car.late.waiver_request.apply as approve_fine_waiver\nexpose car.late.waiver_request.cancel as cancel_fine_waiver\n" },
16
+ { "id": "wallet", "title": "Madinah pottery studio", "summary": "Madinah pottery studio lets members prepay for visits at 172.50 SAR each. A reserved visit can be charged, cancelled or released at expiry; unused credit can be withdrawn.", "headers": ["wallet"], "source": "// Madinah pottery studio lets members prepay for visits at 172.50 SAR each.\n// A reserved visit can be charged, cancelled or released at expiry; unused credit can be withdrawn.\nprogram workshop_credits \"Madinah pottery studio\"\nuse wallet\n\n// Top-up fee: 0%. Loading and withdrawing credit have tax 0% here because\n// they do not sell a visit. Each visit is 150 SAR plus 15% VAT, invoiced by\n// the studio outside wallet.spend, which posts the gross amount to the studio.\nobject membership \"Pottery membership\" {\n fields { memberName: text, membershipNumber: text }\n columns: [memberName, membershipNumber]\n attach balance = wallet.balance {\n holder: owner, spend_limit: 172.50 SAR, topup_fee: 0%\n expose create as create_balance\n expose activate as open_balance\n // For example, top up 690 SAR for four visits.\n expose topup as add_credit\n expose withdraw as withdraw_unused_credit\n expose freeze as freeze_balance\n expose unfreeze as restore_balance\n expose close as close_empty_balance\n expose operator_close as close_empty_membership\n }\n // Supply amount: 172.50 SAR and expiresAt: the booked visit time.\n // Each spend has its own inputs; a second visit cannot inherit the first.\n attach visit = wallet.spend {\n wallet: balance, payee: operator, holder: owner\n economics pay { purpose: earning, sourceParty: owner }\n expose create as book_visit\n expose reserve as reserve_visit_credit\n expose pay as charge_visit\n expose cancel as cancel_reserved_visit\n }\n // Expiry returns a reservation to the wallet. A paid spend has no refund\n // action in this header; resolve cancellations before charging the visit.\n}\n" },
17
17
  ];
18
18
  //# sourceMappingURL=examples-bundle.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"examples-bundle.js","sourceRoot":"","sources":["../../src/examples-bundle.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"examples-bundle.js","sourceRoot":"","sources":["../../src/examples-bundle.ts"],"names":[],"mappings":"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"}
@@ -1,40 +1,57 @@
1
- // A company issues expense cards to employees and reserves each supplier payment before capture.
2
- program team_expense_cards "Team expense cards"
1
+ // Riyadh catering cards lets staff reserve supplier purchases up to 5,000 SAR each.
2
+ // Supplier cancellation releases the reservation; captured purchases support a full refund or a reviewed dispute.
3
+ program team_expense_cards "Riyadh catering cards"
3
4
  use cards
4
- // supplier is a business this program declares, so plan needs {"partyBindings":{"supplier":"<partyId>"}}.
5
- // That partyId is an organization customer's: create the Product from this source without the payment
6
- // and receipt attachments, add the customer with customer.create, activate its access, open its
7
- // customer_balance account, then compose this source with the binding.
8
5
  party supplier: business
9
6
 
10
- object employee "Employee card" {
7
+ // Bind supplier to the food wholesaler. Staff customers own their card records.
8
+ // Card fee: 0%, tax: 0% on card access because the caterer charges staff nothing.
9
+ // A supplier invoice might be 2,000 SAR plus 15% VAT, paid as one 2,300 SAR
10
+ // authorization. cards does not calculate or remit the supplier's invoice VAT.
11
+ object employee "Catering expense card" {
11
12
  fields { employeeName: text, department: text }
12
13
  columns: [employeeName, department]
13
14
  attach holder = cards.cardholder {
14
- expose create as create_holder
15
15
  holder: owner
16
+ expose create as enrol_employee
16
17
  expose activate as activate_employee
17
18
  expose suspend as suspend_employee
19
+ expose resume as restore_employee
20
+ expose close as close_employee_access
21
+ expose operator_close as remove_employee_access
18
22
  }
19
23
  attach card = cards.card {
20
- expose create as create_card
21
- holder: holder, person: owner, spend_limit: 5000 SAR
24
+ holder: holder, person: owner, issuer: operator, spend_limit: 5000 SAR
25
+ expose create as issue_card
22
26
  expose activate as activate_card
23
- expose freeze as freeze_card
24
- expose unfreeze as unfreeze_card
27
+ expose freeze as freeze_lost_card
28
+ expose unfreeze as restore_found_card
25
29
  expose issuer_freeze as block_card
26
30
  expose issuer_unfreeze as unblock_card
31
+ expose cancel as cancel_card
32
+ expose issuer_cancel as retire_employee_card
27
33
  }
34
+ // Supply the gross invoice amount and expiresAt, such as 24 hours after
35
+ // ordering. Pending and approved authorizations expire without capture.
28
36
  attach payment = cards.authorization {
29
- expose create as create_payment
30
- card: card, merchant: supplier
37
+ card: card, merchant: supplier, issuer: operator
38
+ expose create as request_supplier_payment
31
39
  expose approve as approve_payment
32
- expose capture as capture_payment
33
- expose reverse as reverse_payment
40
+ expose decline as decline_payment
41
+ expose capture as capture_delivered_order
42
+ expose reverse as cancel_supplier_reservation
34
43
  }
35
44
  attach receipt = cards.transaction {
36
- expose create as create_receipt
37
45
  authorization: payment
38
- expose refund as refund_payment
46
+ expose create as record_captured_purchase
47
+ expose refund as refund_supplier_purchase
39
48
  }
49
+ attach complaint = cards.dispute {
50
+ transaction: receipt, issuer: operator, within: 30d
51
+ expose create as dispute_supplier_purchase
52
+ expose review as review_purchase_dispute
53
+ expose win as uphold_dispute_and_refund
54
+ }
55
+ // A dispute unresolved after 30 days becomes lost. A refund always needs
56
+ // the supplier's funds; the card header does not prove card-network settlement.
40
57
  }
@@ -1,41 +1,66 @@
1
- // A business lender refers overdue instalments to an agency with limits on collection contacts.
2
- program business_collections "Small business collections"
1
+ // Jeddah cafe equipment finance lends 24,000 SAR over 12 months and refers debt seven days overdue.
2
+ // Its agency earns 10% of each recovery from the lender, with at most four contacts per 30 days.
3
+ program business_collections "Jeddah cafe equipment finance"
3
4
  use collections
4
5
  use financing
5
- // agency is a business this program declares, so plan needs {"partyBindings":{"agency":"<partyId>"}}.
6
- // That partyId is an organization customer's: create the Product from this source without the recovery
7
- // and contact attachments, add the customer with customer.create, activate its access, open its
8
- // customer_balance account, then compose this source with the binding.
9
6
  party agency: business
10
7
 
11
- object facility "Business loan" {
8
+ // Bind agency to the collector. The cafe owns the facility. Set price to
9
+ // 24,000 SAR: 6% flat profit is 1,440 SAR, repaid in twelve 2,120 SAR payments.
10
+ // Loan fee: 0%, tax: 0% on principal. The agency invoices 15% VAT on its
11
+ // recovery service outside collections.case, which posts only the 10% fee.
12
+ object facility "Cafe equipment facility" {
12
13
  fields { businessName: text, purpose: text, price: money }
13
14
  columns: [businessName, purpose, price]
14
- attach allowance = financing.limits { expose create as create_allowance, expose approve as approve_borrower, borrower: owner, per_borrower: 100000 SAR }
15
- attach budget = financing.portfolio_limit { expose create as create_budget, expose approve as approve_budget, limit: 2000000 SAR }
15
+ attach allowance = financing.limits {
16
+ borrower: owner, per_borrower: 100000 SAR
17
+ expose create as request_borrower_limit
18
+ expose approve as approve_borrower
19
+ }
20
+ attach budget = financing.portfolio_limit {
21
+ limit: 2000000 SAR
22
+ expose create as create_lending_budget
23
+ expose approve as approve_budget
24
+ }
25
+ // Approve both limits and provide twelve future due dates before disbursement.
16
26
  attach loan = financing.installments {
17
- expose create as create_loan
18
- borrower: owner, capital: operator
19
- months: 12, pricing: amortizing, profit_rate: 6%, disburse_to: borrower
27
+ borrower: owner, capital: operator, share: 0%
28
+ months: 12, pricing: flat_total, profit_rate: 6%, disburse_to: borrower
29
+ payoff_rebate: 100%, refund_within: 30d, write_off_after: 90d
20
30
  limits: allowance, portfolio: budget
31
+ expose create as quote_equipment_loan
21
32
  expose sign as sign_loan
22
33
  expose disburse as release_loan
34
+ expose cancel as decline_loan_quote
35
+ expose void as cancel_unfunded_loan
23
36
  expose payoff as repay_early
37
+ expose complete as close_repaid_loan
24
38
  }
39
+ // Select matching plan, overdue slice and pending payment when opening.
40
+ // Recovery pays that payment, not necessarily the whole remaining debt.
25
41
  attach recovery = collections.case {
26
- expose create as create_recovery
27
- on: loan, agency: agency
28
- expose assign as assign_case
29
- expose recover as recover_payment
30
- expose recall as recall_case
42
+ on: loan, agency: agency, capital: operator, overdue: 7d, fee: 10%
43
+ expose create as refer_overdue_instalment
44
+ expose assign as assign_agency
45
+ expose recover as collect_referred_payment
46
+ expose recall as recall_collection_case
47
+ expose return_uncollected as return_uncollected_case
31
48
  }
32
49
  attach contact = collections.contact {
33
- expose create as create_contact
34
50
  case: recovery, agency: agency
51
+ max_contacts: 4, window: 30d, contact_from: 9, contact_until: 18
52
+ timezone: "Asia/Riyadh"
53
+ expose create as record_collection_contact
35
54
  }
36
55
  }
37
56
 
38
- expose facility.loan.payment.create as create_payment
57
+ expose facility.contact.outcome.create as record_contact_outcome
58
+ expose facility.loan.payment.create as record_repayment
39
59
  expose facility.loan.payment.pay as pay_instalment
40
- expose facility.loan.payment.refund as refund_payment
60
+ expose facility.loan.payment.refund as refund_mistaken_repayment
41
61
  expose facility.loan.payoff_quote.create as request_payoff_quote
62
+ // A disputed contact can be recorded, then capital can recall the case.
63
+ // Uncollectible principal needs a separate capital decision after 90 days.
64
+ expose facility.loan.write_off_request.create as request_overdue_write_off
65
+ expose facility.loan.write_off_request.apply as approve_overdue_write_off
66
+ expose facility.loan.write_off_request.cancel as cancel_write_off_request
@@ -1,24 +1,31 @@
1
- // Buyers fund a used device purchase, then accept delivery or raise a dispute before release.
2
- program used_device_sales "Used device sales"
1
+ // Khobar used laptops holds a buyer's 2,300 SAR until the laptop arrives and passes inspection.
2
+ // Delivery has seven days; the buyer has 48 hours to accept or dispute before the operator reviews the sale.
3
+ program used_device_sales "Khobar used laptops"
3
4
  use escrow
5
+ party seller: business
4
6
 
5
- object device "Device" {
6
- fields {
7
- model: text
8
- condition: text
9
- serialNumber: text
10
- price: money
11
- }
12
- columns: [model, condition, price]
7
+ // Bind seller to the refurbisher. Set price to the agreed gross invoice, for
8
+ // example 2,300 SAR. The company keeps 5%, 115 SAR, plus 15% VAT on that fee.
9
+ // Seller receives 2,167.75 SAR. Any VAT on the laptop is on the seller's invoice.
10
+ object device "Laptop purchase" {
11
+ fields { model: text, condition: text, serialNumber: text, price: money }
12
+ columns: [model, condition, serialNumber, price]
13
13
  attach sale = escrow.hold {
14
- expose create as create_sale
15
- payer: actor, payee: owner
16
- expose fund as pay_for_device
14
+ payer: owner, payee: seller
15
+ fee: { seller: 5%, tax: 15% }
16
+ deliver_within: 7d, accept_within: 48h
17
+ dispute: { refund_after: return_verified }
18
+ expose create as agree_purchase
19
+ expose fund as pay_for_laptop
17
20
  expose deliver as confirm_delivery
18
- expose accept as accept_device
21
+ expose accept as accept_laptop
19
22
  expose dispute as report_problem
20
- expose verify_return as verify_return
23
+ expose verify_return as verify_returned_laptop
21
24
  expose refund as refund_buyer
22
- expose cancel as cancel_sale
25
+ expose refund_undelivered as refund_missing_delivery
26
+ expose settle_release as resolve_in_seller_favour
27
+ expose settle_return as resolve_in_buyer_favour
28
+ expose settle_refund as finish_buyer_refund
29
+ expose cancel as cancel_unpaid_purchase
23
30
  }
24
31
  }
@@ -1,32 +1,52 @@
1
- // A tuition lender funds a student's fees over three interest-free instalments with borrowing limits.
2
- program tuition_instalments "Tuition instalments"
1
+ // Riyadh language academy finance pays 6,900 SAR tuition to the academy at enrolment.
2
+ // The student repays three monthly instalments of 2,300 SAR with no financing profit or late fee.
3
+ program tuition_instalments "Riyadh language academy finance"
3
4
  use financing
5
+ party academy: business
4
6
 
5
- object enrolment "Enrolment" {
7
+ // Bind academy to the training business. Its 6,000 SAR course plus 15% VAT
8
+ // is invoiced outside this plan. Set price to the gross 6,900 SAR invoice.
9
+ // Financing fee: 0%, tax: 0% on principal repayments; no separate service is sold.
10
+ object enrolment "Language course finance" {
6
11
  fields { student: text, course: text, price: money }
7
12
  columns: [student, course, price]
8
13
  attach allowance = financing.limits {
9
- expose create as create_allowance
10
14
  borrower: owner, per_borrower: 12000 SAR
15
+ expose create as request_student_allowance
11
16
  expose approve as approve_student
12
17
  }
13
18
  attach budget = financing.portfolio_limit {
14
- expose create as create_budget
15
19
  limit: 500000 SAR
20
+ expose create as create_tuition_budget
16
21
  expose approve as approve_budget
17
22
  }
23
+ // Approve both limits before funding. Supply three future monthly dates
24
+ // and a unique settlementIdentity. Funding must precede the first due date.
18
25
  attach tuition = financing.installments {
19
- expose create as create_tuition
20
- borrower: owner, capital: operator
21
- months: 3, pricing: flat_total, profit_rate: 0%, disburse_to: borrower
22
- limits: allowance, portfolio: budget
26
+ borrower: owner, capital: operator, seller: academy
27
+ months: 3, pricing: flat_total, profit_rate: 0%, share: 0%
28
+ disburse_to: seller, limits: allowance, portfolio: budget
29
+ payoff_rebate: 100%, refund_within: 30d, write_off_after: 90d
30
+ max_extension: 30d, max_amendments: 1, amendment_expiry: 7d
31
+ expose create as quote_tuition_plan
23
32
  expose sign as sign_tuition_plan
24
- expose disburse as fund_tuition
33
+ expose disburse as pay_academy
34
+ expose cancel as decline_tuition_quote
35
+ expose void as cancel_unfunded_plan
25
36
  expose payoff as repay_early
37
+ expose complete as close_repaid_plan
26
38
  }
27
39
  }
28
40
 
29
- expose enrolment.tuition.payment.create as create_payment
41
+ expose enrolment.tuition.payment.create as record_student_payment
30
42
  expose enrolment.tuition.payment.pay as pay_instalment
31
- expose enrolment.tuition.payment.refund as refund_payment
43
+ expose enrolment.tuition.payment.refund as refund_mistaken_payment
32
44
  expose enrolment.tuition.payoff_quote.create as request_payoff_quote
45
+ // A hardship extension adds no profit and needs the student's acceptance.
46
+ expose enrolment.tuition.amendment.create as propose_payment_extension
47
+ expose enrolment.tuition.amendment.accept as accept_payment_extension
48
+ expose enrolment.tuition.amendment.decline as decline_payment_extension
49
+ expose enrolment.tuition.amendment.withdraw as withdraw_payment_extension
50
+ expose enrolment.tuition.write_off_request.create as request_overdue_write_off
51
+ expose enrolment.tuition.write_off_request.apply as approve_overdue_write_off
52
+ expose enrolment.tuition.write_off_request.cancel as cancel_write_off_request
@@ -1,31 +1,46 @@
1
- // A device retailer collects the purchase price and attaches cover with a claim review process.
2
- program device_insurance "Device insurance"
1
+ // Jeddah device cover sells a 1,725 SAR tablet and a 115 SAR annual protection period.
2
+ // The retailer keeps 10% of each premium; cancelled future periods reverse that commission and the insurer's portion.
3
+ program device_insurance "Jeddah device cover"
3
4
  use insurance
4
5
  use money
5
6
 
6
- object device "Insured device" {
7
+ // The retailer invoices the tablet at 1,500 SAR plus 15% VAT outside
8
+ // money.transfer. Purchase fee: 0%. The transfer pays the gross 1,725 SAR.
9
+ // The insurer invoices 100 SAR plus 15% VAT for the premium outside
10
+ // insurance.cover, which has no tax setting.
11
+ // At 115 SAR premium, commission is 11.50 SAR and insurer cash is 103.50 SAR.
12
+ object device "Insured tablet" {
7
13
  fields { model: text, serialNumber: text, purchaseDate: date }
8
- columns: [model, serialNumber, purchaseDate]
14
+ columns: [model, serialNumber, purchaseDate, coverExpiresAt]
9
15
  attach purchase = money.transfer {
10
- expose create as create_purchase
11
- payer: owner, payee: operator
16
+ payer: owner, payee: operator, amount: 1725 SAR
12
17
  economics pay { purpose: earning, sourceParty: owner }
13
- expose pay as pay_for_device
18
+ expose create as create_purchase
19
+ expose pay as pay_for_tablet
20
+ expose cancel as cancel_unpaid_purchase
14
21
  }
15
- // conformance_boundary is the sandbox insurer adapter; swap in the insurer's registered adapter to go live.
16
- // Premiums net of commission go to its account. The default broker is the retailer, which keeps the commission.
17
- // claim_limit is the sum insured, set per cover at creation.
22
+ // Bind the insurer's registered adapter before launch. conformance_boundary
23
+ // is only the sandbox adapter. Set the cover expiry to the policy end date.
18
24
  attach protection = insurance.cover {
19
- expose create as create_protection
20
- holder: owner, adapter: "conformance_boundary", commission: 10%, covers: purchase
25
+ holder: owner, broker: operator, adapter: "conformance_boundary"
26
+ covers: purchase, premium: 115 SAR, commission: 10%, claim_limit: 1500 SAR
27
+ rename { expiresAt: coverExpiresAt }
28
+ expose create as request_cover
21
29
  expose activate as activate_cover
22
- expose cancel as cancel_cover
30
+ expose cancel as cancel_and_refund_future_cover
23
31
  }
32
+ // Supply loss evidence, the claim amount and its decision expiry.
33
+ // The 1,500 SAR limit applies to all approved and paid claims on the cover.
24
34
  attach claim = insurance.claim {
25
- expose create as create_claim
26
35
  cover: protection, inspector: operator
36
+ expose create as report_damage
27
37
  expose approve as approve_claim
28
38
  expose deny as deny_claim
29
39
  expose pay as pay_claim
30
40
  }
31
41
  }
42
+
43
+ // Create the annual period with startsAt and endsAt, then collect its premium.
44
+ // Cancelling cover refunds only paid periods that have not started.
45
+ expose device.protection.slice.create as create_premium_period
46
+ expose device.protection.slice.collect as pay_cover_premium