Skip to content

Commit 20c1994

Browse files
committed
Merge branch 'main' into develop
# Conflicts: # .claude/skills/fin-daily-pulse/SKILL.md
2 parents a6f78ce + a438653 commit 20c1994

5 files changed

Lines changed: 62 additions & 33 deletions

File tree

.claude/skills/fin-daily-pulse/SKILL.md

Lines changed: 52 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,29 +9,52 @@ Daily routine that pulls data from Stripe, Omie and Evo Academy to generate an H
99

1010
**Always respond in English.**
1111

12+
## Currency Conversion Rule (apply to every Stripe value)
13+
14+
**All monetary values MUST be converted to BRL before summing or displaying as R$.**
15+
16+
1. Fetch the USD-to-BRL exchange rate from `https://api.exchangerate-api.com/v4/latest/USD` (field `rates.BRL`).
17+
- If the API call fails, use fallback rate **5.75**.
18+
- Log the rate used in the report (e.g., "USD/BRL: 5.7832" or "USD/BRL: 5.75 (fallback)").
19+
2. For each Stripe item, read the `currency` field (lowercase ISO-4217, e.g. `"usd"`, `"brl"`, `"idr"`).
20+
- `brl`: amount is in centavos — divide by 100, use as-is.
21+
- `usd`: divide by 100, then multiply by the USD-to-BRL rate.
22+
- Any other currency (e.g. `idr`, `mxn`, `eur`): **exclude from BRL totals**. Append a warning: `WARNING: Skipped {currency} {amount/100} (customer {id}) — unsupported currency, manual review required.`
23+
3. **Never add raw amounts of different currencies together.** Convert first, then sum.
24+
1225
## Step 1 — Collect Stripe data (silently)
1326

1427
Use the `/int-stripe` skill to fetch:
1528

1629
### 1a. MRR and Subscriptions
17-
- List active subscriptions (`status=active`) → count and sum values to calculate MRR
18-
- Compare with previous data if available in `workspace/finance/`
30+
- List active subscriptions (`status=active`).
31+
- For each subscription, read `currency` and `plan.amount` (centavos).
32+
- Apply the Currency Conversion Rule above to convert each amount to BRL.
33+
- Sum all converted amounts — Stripe MRR in BRL.
34+
- Log currency breakdown (e.g., "195 subs: 116 BRL, 78 USD, 1 excluded IDR").
35+
- Compare with previous data if available in `workspace/finance/`.
1936

2037
### 1b. Today's Charges
21-
- List charges created today (`created` >= start of day UTC-3)
22-
- Sum total charged amount
23-
- Count charges with `status=succeeded` vs `status=failed`
38+
- List charges created today (`created` >= start of day UTC-3).
39+
- For each charge, read `currency` and `amount` (centavos).
40+
- Apply the Currency Conversion Rule to convert each charge to BRL.
41+
- Sum converted succeeded amounts — today's revenue in BRL.
42+
- Count charges with `status=succeeded` vs `status=failed`.
43+
- Flag any single converted charge exceeding R$ 10,000 as potentially anomalous.
2444

2545
### 1c. Churn (last 30 days)
26-
- List subscriptions canceled in the last 30 days
27-
- Calculate churn rate vs total subscriptions
46+
- Fetch Stripe events with `type=customer.subscription.deleted`, paginating ALL pages until `has_more=false` — never stop at the first page.
47+
- Count unique canceled subscription IDs — churn count.
48+
- Churn rate = canceled / (total active + canceled) * 100.
49+
- Use this event-based method consistently every run.
2850

2951
### 1d. Refunds (last 7 days)
30-
- List refunds from the last 7 days
31-
- Sum total refunded amount
52+
- List refunds from the last 7 days.
53+
- Apply the Currency Conversion Rule to each refund before summing.
54+
- Report total refunded in BRL.
3255

3356
### 1e. New customers (last 7 days)
34-
- List customers created in the last 7 days
57+
- List customers created in the last 7 days.
3558

3659
## Step 2 — Collect Omie data (silently)
3760

@@ -64,31 +87,31 @@ Captura: `revenue.total`, `orders.completed`, `orders.pending`, `orders.failed`,
6487
```
6588
GET /api/v1/analytics/orders?status=completed&created_after=YYYY-MM-DD&per_page=100
6689
```
67-
(hoje em BRT; converter para UTC `created_after = date.today().isoformat()`)
68-
- Itere paginação por cursor até `meta.has_more = false`
69-
- Some `amount` de todos os orders → receita bruta Evo Academy do dia
70-
- Separe por tipo: renovações (`is_renewal=true`) vs novos (`is_renewal=false`)
71-
- Agrupe por produto: cursos, assinaturas, ingressos, outros
90+
(today in BRT; convert to UTC: `created_after = date.today().isoformat()`)
91+
- Paginate until `meta.has_more = false`
92+
- Sum `amount` of all orders Evo Academy daily revenue
93+
- Split by type: renewals (`is_renewal=true`) vs new (`is_renewal=false`)
94+
- Group by product: courses, subscriptions, tickets, others
7295

7396
### 2.5c. MRR de assinaturas ativas (Evo Academy)
7497
```
7598
GET /api/v1/analytics/subscriptions?status=active&per_page=100
7699
```
77-
- Itere até `meta.has_more = false`
78-
- Some `plan.price` de cada assinatura ativa → MRR Evo Academy
100+
- Paginate until `meta.has_more = false`
101+
- Sum `plan.price` of each active subscription — Evo Academy MRR
79102

80103
## Step 3 — Day's transactions
81104

82105
Consolidate all financial transactions for the day:
83-
- Stripe charges (revenue)
106+
- Stripe charges (revenue, already converted to BRL per the Currency Conversion Rule)
84107
- Evo Academy orders (revenue — courses / subscriptions / tickets)
85108
- Payments recorded in Omie (expenses)
86-
- Refunds
109+
- Refunds (converted to BRL)
87110

88-
Format each transaction with: type (Revenue/Expense/Refund), description, amount, status.
111+
Format each transaction with: type (Revenue/Expense/Refund), description, amount in BRL, status.
89112

90-
**Total revenue = Stripe today + Evo Academy today**
91-
**Total MRR = Stripe MRR + Evo Academy MRR**
113+
**Total revenue = Stripe today (BRL) + Evo Academy today**
114+
**Total MRR = Stripe MRR (BRL) + Evo Academy MRR**
92115

93116
## Step 4 — Classify financial health
94117

@@ -105,6 +128,7 @@ Generate list of financial alerts:
105128
- Invoices that should have been issued
106129
- Churn above normal levels
107130
- Any anomalies in amounts
131+
- Currencies excluded from totals (currency conversion warnings from Step 1)
108132

109133
If there are no alerts: "No financial alerts at this time."
110134

@@ -133,19 +157,20 @@ workspace/finance/reports/daily/[C] YYYY-MM-DD-financial-pulse.html
133157

134158
Create the directory `workspace/finance/reports/daily/` if it does not exist.
135159

136-
## Step 8 — Confirm
160+
## Step 8 — Confirm and notify (ONE Telegram message only)
161+
162+
Output the completion summary, then send **exactly one** Telegram message. Do NOT call `reply` more than once per run.
137163

138164
```
139165
## Financial Pulse generated
140166
141167
**File:** workspace/finance/reports/daily/[C] YYYY-MM-DD-financial-pulse.html
142168
**MRR total:** R$ X,XXX (Stripe: R$ X,XXX | Evo Academy: R$ X,XXX)
143169
**Receita hoje:** R$ X,XXX | **Subscriptions:** N | **Churn:** X%
170+
**USD/BRL rate:** X.XXXX (live) or 5.75 (fallback)
144171
**Alerts:** {N} attention points
145172
```
146173

147-
### Notify via Telegram
174+
Call `reply` **once** with a short summary (do not send the full markdown above — send a compact version):
148175

149-
Upon completion, send a short summary via Telegram to the user:
150-
- Use the Telegram MCP: `reply(chat_id="YOUR_CHAT_ID", text="...")`
151-
- Format: emoji + "Financial Pulse" + MRR + alerts (1-3 lines)
176+
- Format: `[emoji] Financial Pulse [date] | MRR: R$ X,XXX | Receita: R$ X,XXX | Churn: X% | [N] alertas`

.claude/skills/prod-end-of-day/SKILL.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,10 @@ The log should include:
7272

7373
## Step 5 — Organize tasks
7474

75-
Run `/prod-review-todoist` to ensure tasks created during the day are categorized and translated.
75+
Review Todoist tasks directly (do NOT invoke `/prod-review-todoist` as a sub-skill — it sends a duplicate Telegram notification):
76+
- Run `todoist today` to list today's tasks
77+
- For each uncategorized or non-PT-BR task: rename/recategorize via `todoist update`
78+
- Report how many were organized
7679

7780
## Step 6 — Confirm
7881

.claude/skills/prod-good-morning/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ If any of these files don't exist yet (the user might be very new), that's fine
2222
Before building the recap, gather live data silently (don't narrate each step):
2323

2424
1. **Agenda do dia** — use `/gog-calendar` to list today's events. Note meetings, times, people, and free blocks.
25-
2. **Emails importantes** — use `/gog-email-triage` to check unread emails. Filter only those needing action or attention.
25+
2. **Emails importantes** — use the Gmail MCP directly (`list_emails` then `get_email` for each relevant one) to check unread emails needing action or attention. Do NOT invoke `/gog-email-triage` as a sub-skill — it sends its own Telegram notification and would cause a duplicate.
2626
3. **Tarefas de hoje** — run `todoist today` to list today's and overdue tasks from Todoist.
2727

2828
## Step 3 — Brief recap

.claude/skills/prod-review-todoist/SKILL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ If the user wants to see details of what changed, they ask.
127127

128128
### Notify via Telegram
129129

130-
Upon completion, send a short summary via Telegram to the user:
130+
Upon completion, send **exactly ONE** Telegram message — do NOT call `reply()` more than once per run:
131131
- Use the Telegram MCP: `reply(chat_id="YOUR_CHAT_ID", text="...")`
132-
- Format: emoji + routine name + main result (1-3 lines)
132+
- Format: emoji + routine name + main result (1-3 lines, all combined in a single message)
133133
- If the routine had no updates, send anyway with "no updates"

.claude/skills/pulse-faq-sync/SKILL.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,8 @@ The "Skipped" block is mandatory — it gives visibility on questions the commun
206206

207207
### Notify via Telegram
208208

209-
Upon completion, send a short summary via Telegram to the user:
209+
Upon completion, send **exactly ONE** Telegram message with the full summary:
210210
- Use the Telegram MCP: `reply(chat_id="YOUR_CHAT_ID", text="...")`
211-
- Format: emoji + routine name + main result (1-3 lines)
211+
- Format: emoji + routine name + main result (totals + alerts combined in one message)
212+
- Do NOT split into multiple messages — combine summary and alerts into a single call
212213
- If the routine had no updates, send anyway with "no updates"

0 commit comments

Comments
 (0)