On the 3rd of each month, emails you last month's profit and loss for each department, or for the whole business, with AI commentary.
Uses
Claude
Gmail
Google Sheets
Email last month's profit and loss for each department
financeSheetUrl to blank.Set financeSheetUrl to blank.transactionsTab to Transactions.Set transactionsTab to Transactions.reportEmail to blank.Set reportEmail to blank.reportMonth to blank.Set reportMonth to blank.onlyCostCenters to an empty list.Set onlyCostCenters to an empty list.positiveAmountsAre to income.Set positiveAmountsAre to income.datesAreDayFirst to false.Set datesAreDayFirst to false.fiscalYearStartMonth to 1.Set fiscalYearStartMonth to 1.maxCostCenters to 25.Set maxCostCenters to 25.financeSheetUrl. Save it as financialData.Read the rows of financeSheetUrl. Save it as financialData.financialData.rows is emptyIf financialData.rows is emptyYes
No
No steps
reportPlan to an empty record.Set reportPlan to an empty record.planFailedIf a step below fails, save the error as planFailedTry
rows, headers, today, tab_name, report_email, report_month, only_cost_centers, positive_amounts_are, dates_are_day_first, fiscal_year_start_month, and max_cost_centers and save it as reportPlan.Run Python code on rows, headers, today, tab_name, report_email, report_month, only_cost_centers, positive_amounts_are, dates_are_day_first, fiscal_year_start_month, and max_cost_centers and save it as reportPlan.On error
planFailed.message contains inputs are too largeIf planFailed.message contains inputs are too largeYes
The ', transactionsTab, ' tab holds more than one run can read at once (, the length of financialData.rows, rows), so nothing was sent. Move the transactions from earlier financial years into another tab - the reports only use this financial year and the month before it - then run it again.] joined by nothing.Stop and report a problem: [The ', transactionsTab, ' tab holds more than one run can read at once (, the length of financialData.rows, rows), so nothing was sent. Move the transactions from earlier financial years into another tab - the reports only use this financial year and the month before it - then run it again.] joined by nothing.No
No steps
planFailed.message.Stop and report a problem: The transactions could not be read, so nothing was sent: planFailed.message.reportPlan.error isn't emptyIf reportPlan.error isn't emptyYes
reportPlan.error.Stop and report a problem: reportPlan.error.No
No steps
sentReports to an empty list.Set sentReports to an empty list.figuresOnly to an empty list.Set figuresOnly to an empty list.failedReports to an empty list.Set failedReports to an empty list.costCenter in reportPlan.cost_centers:For each costCenter in reportPlan.cost_centers:centerFigures to an empty record.Set centerFigures to an empty record.figuresFailedIf a step below fails, save the error as figuresFailedTry
rows, center, and plan and save it as centerFigures.Run Python code on rows, center, and plan and save it as centerFigures.On error
figuresFailed.message to 300 characters and save it as figuresProblem.Shorten figuresFailed.message to 300 characters and save it as figuresProblem.costCenter.name (its figures could not be worked out: figuresProblem) to the end of failedReports and save it as failedReports.Add costCenter.name (its figures could not be worked out: figuresProblem) to the end of failedReports and save it as failedReports.commentary to blank.Set commentary to blank.analysisFailedIf a step below fails, save the error as analysisFailedTry
centerFigures.facts
<<<END FIGURES>>>
WHAT TO WRITE
Plain text only: no markdown, no asterisks, no # headings and no tables. Write exactly these three parts, each starting with its label on a line of its own:
Summary
Two or three sentences: the month's net result, and how revenue and expenses moved against the previous month. For a cost center with no revenue, describe it by its costs.
What drove it
Two to four lines, each starting with - , naming the categories or transactions behind the biggest movements, with their figures.
Worth a closer look
One to three lines, each starting with - : what a finance lead would want to check, such as an unusually large transaction, a category that is new this month or has stopped, a cost growing faster than the rest, or rows that could not be counted. Word each one as something to check, not as a conclusion. If nothing stands out, write one line saying so.
RULES
- Quote only figures that appear above, exactly as they are written there. Do not add up, average, annualise, forecast or estimate anything, and do not work out a percentage that is not given.
- Do not guess at causes the figures cannot show, such as the market, the season, effort or staffing. Say what moved and point to the transactions behind it.
- If there is no previous month to compare with, say so once and do not describe changes.
- Keep it under 220 words.'. Save it as aiAnalysis.
Maximum response length: 900aiAnalysis.response_text and save it as commentary.Trim aiAnalysis.response_text and save it as commentary.On error
costCenter.name could not be written, so its report carries the figures only: analysisFailed.message.Show in the output: The commentary for costCenter.name could not be written, so its report carries the figures only: analysisFailed.message.reportBody to blank.Set reportBody to blank.commentary isn't emptyIf commentary isn't emptyYes
** with in commentary and save it as commentary.Replace ** with in commentary and save it as commentary.### with in commentary and save it as commentary.Replace ### with in commentary and save it as commentary.## with in commentary and save it as commentary.Replace ## with in commentary and save it as commentary.@centerFigures.heading @commentary ──────────────────────────────── @centerFigures.statement ──────────────────────────────── About these figures @centerFigure... and save it as reportBody.Build the text @centerFigures.heading @commentary ──────────────────────────────── @centerFigures.statement ──────────────────────────────── About these figures @centerFigure... and save it as reportBody.No
costCenter.name to the end of figuresOnly and save it as figuresOnly.Add costCenter.name to the end of figuresOnly and save it as figuresOnly.@centerFigures.heading The written commentary could not be produced this month, so this report carries the figures only. ──────────────────────────────── @cent... and save it as reportBody.Build the text @centerFigures.heading The written commentary could not be produced this month, so this report carries the figures only. ──────────────────────────────── @cent... and save it as reportBody.sendFailedIf a step below fails, save the error as sendFailedTry
reportPlan.recipients.Send an email to reportPlan.recipients.
Subject: centerFigures.subjectreportBodycostCenter.name to the end of sentReports and save it as sentReports.Add costCenter.name to the end of sentReports and save it as sentReports.On error
sendFailed.message to 300 characters and save it as sendProblem.Shorten sendFailed.message to 300 characters and save it as sendProblem.costCenter.name (sendProblem) to the end of failedReports and save it as failedReports.Add costCenter.name (sendProblem) to the end of failedReports and save it as failedReports.sentReports with , and save it as sentList.Join sentReports with , and save it as sentList.sentList is emptyIf sentList is emptyYes
sentList to none.Change sentList to none.No
No steps
The @reportPlan.month_label P&L reports went to @reportPlan.recipients for: @sentList. @reportPlan.summary and save it as runSummary.Build the text The @reportPlan.month_label P&L reports went to @reportPlan.recipients for: @sentList. @reportPlan.summary and save it as runSummary.figuresOnly isn't emptyIf figuresOnly isn't emptyYes
runSummary, The AI commentary could not be written for , figuresOnly joined by , , , so those reports carry the figures only.] with nothing and save it as runSummary.Join [runSummary, The AI commentary could not be written for , figuresOnly joined by , , , so those reports carry the figures only.] with nothing and save it as runSummary.No
No steps
failedReports isn't emptyIf failedReports isn't emptyYes
Not every report went out. Not sent: , failedReports joined by ; , . Sent: , sentList, . To send only the missing reports, put their cost centers in the onlyCostCenters step and set reportMonth to , reportPlan.month_setting, , then run it again.] joined by nothing.Stop and report a problem: [Not every report went out. Not sent: , failedReports joined by ; , . Sent: , sentList, . To send only the missing reports, put their cost centers in the onlyCostCenters step and set reportMonth to , reportPlan.month_setting, , then run it again.] joined by nothing.No
No steps
runSummary.Finish the run: runSummary.