Guides
Let customers take an action
Let a customer accept their quote, or do one other specific thing their write rule would not allow, without letting them edit the record.
A customer's write rule usually stops them changing a job: you don't want them editing the price. But some things they should be able to do, such as accept the quote. A write recipe opened to their role lets them do exactly that and nothing more.
1. Write the recipe
A recipe is up to ten steps that run in one transaction: each writes a record or archives one. {"$param": "<name>"} takes the caller's value; every other value is fixed when you save it.
This one marks the job booked and posts a message to the team. Save it with Claude Code (awesomate_crm_recipes), or from a script with the server client:
await db.saveRecipe({
key: 'accept_quote',
label: 'Accept the quote',
params: [{ name: 'job', type: 'uuid', required: true }],
steps: [
{ op: 'write_record', kind: 'job', id: { $param: 'job' }, data: { status: 'booked' } },
{ op: 'write_record', kind: 'message', data: { body: 'I accept the quote. Please go ahead and book it in.' }, links: { job: { $param: 'job' } } },
],
});2. Open it to your customers
Recipes run only for the account until you name the roles that may run them:
Let members of the Brightwater portal run the accept_quote recipe.
Claude uses awesomate_crm_recipes with action run_by. You can also switch it on the app's page in the hub, under Things customers can do. Opening it to no roles closes it again, and so does archiving the recipe.
3. Call it from the page
async function acceptQuote(jobId: string) {
try {
await app.call('accept_quote', { job: jobId });
} catch (err) {
if (err instanceof AwesomateError && err.code === 'not_found') showMessage('That quote is no longer open to accept.');
else throw err;
}
}Your live lists update by themselves: the job shows as booked and the message appears in the conversation.
What the database checks
When a customer runs a recipe, the database checks every step against the recipe as it was saved, not as the page sent it:
- the person's role is one the recipe is open to;
- only the
$parampositions take their values: they cannot change the status written, add a step or touch another kind; - a record a step changes, and any record a step links to, must be one they can already read, so a customer can only accept a quote on their own job;
- every step commits, or none does.
A recipe they may not run reads as not_found, the same as one that does not exist.
Changing a recipe that customers can run changes what they can do. Check with whoever owns the app before you edit one.
Recipes for your own systems
The account's token can run any recipe whether or not it is open to a role, and an app server key any recipe whose steps stay inside the key's kinds: db.call('accept_quote', { job: jobId }). See Saved queries and recipes.