@sylix/coworker 2.0.11 → 2.0.12

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.
Files changed (169) hide show
  1. package/dist/commands/slash/config.d.ts.map +1 -1
  2. package/dist/commands/slash/config.js +22 -4
  3. package/dist/commands/slash/config.js.map +1 -1
  4. package/dist/core/CoWorkerAgent.d.ts.map +1 -1
  5. package/dist/core/CoWorkerAgent.js +6 -3
  6. package/dist/core/CoWorkerAgent.js.map +1 -1
  7. package/dist/skills/defaults/accessibility/screen-reader-testing.md +545 -0
  8. package/dist/skills/defaults/accessibility/wcag-audit-patterns.md +555 -0
  9. package/dist/skills/defaults/ai-ml/rag.md +276 -0
  10. package/dist/skills/defaults/backend-development/api-design-principles.md +528 -0
  11. package/dist/skills/defaults/backend-development/api-design.md +285 -0
  12. package/dist/skills/defaults/backend-development/architecture-patterns.md +494 -0
  13. package/dist/skills/defaults/backend-development/async-python.md +237 -0
  14. package/dist/skills/defaults/backend-development/auth-implementation-patterns.md +638 -0
  15. package/dist/skills/defaults/backend-development/bazel-build-optimization.md +387 -0
  16. package/dist/skills/defaults/backend-development/billing-automation/SKILL.md +566 -0
  17. package/dist/skills/defaults/backend-development/code-review-excellence.md +538 -0
  18. package/dist/skills/defaults/backend-development/cqrs-implementation.md +554 -0
  19. package/dist/skills/defaults/backend-development/database-design.md +305 -0
  20. package/dist/skills/defaults/backend-development/debugging-strategies.md +536 -0
  21. package/dist/skills/defaults/backend-development/e2e-testing-patterns.md +544 -0
  22. package/dist/skills/defaults/backend-development/error-handling-patterns.md +641 -0
  23. package/dist/skills/defaults/backend-development/fastapi-templates.md +559 -0
  24. package/dist/skills/defaults/backend-development/fastapi.md +309 -0
  25. package/dist/skills/defaults/backend-development/git-advanced-workflows.md +405 -0
  26. package/dist/skills/defaults/backend-development/microservices-patterns.md +595 -0
  27. package/dist/skills/defaults/backend-development/microservices.md +284 -0
  28. package/dist/skills/defaults/backend-development/monorepo-management.md +623 -0
  29. package/dist/skills/defaults/backend-development/nodejs-backend-patterns.md +1048 -0
  30. package/dist/skills/defaults/backend-development/nx-workspace-patterns.md +457 -0
  31. package/dist/skills/defaults/backend-development/paypal-integration/SKILL.md +478 -0
  32. package/dist/skills/defaults/backend-development/pci-compliance/SKILL.md +480 -0
  33. package/dist/skills/defaults/backend-development/python-anti-patterns.md +349 -0
  34. package/dist/skills/defaults/backend-development/python-background-jobs.md +364 -0
  35. package/dist/skills/defaults/backend-development/python-code-style.md +360 -0
  36. package/dist/skills/defaults/backend-development/python-configuration.md +368 -0
  37. package/dist/skills/defaults/backend-development/python-design-patterns.md +296 -0
  38. package/dist/skills/defaults/backend-development/python-error-handling.md +323 -0
  39. package/dist/skills/defaults/backend-development/python-packaging.md +887 -0
  40. package/dist/skills/defaults/backend-development/python-performance-optimization.md +874 -0
  41. package/dist/skills/defaults/backend-development/python-project-structure.md +252 -0
  42. package/dist/skills/defaults/backend-development/python-resilience.md +376 -0
  43. package/dist/skills/defaults/backend-development/python-resource-management.md +421 -0
  44. package/dist/skills/defaults/backend-development/python-type-safety.md +428 -0
  45. package/dist/skills/defaults/backend-development/sql-optimization-patterns.md +509 -0
  46. package/dist/skills/defaults/backend-development/stripe-integration/SKILL.md +522 -0
  47. package/dist/skills/defaults/backend-development/turborepo-caching.md +376 -0
  48. package/dist/skills/defaults/blockchain/defi-protocol-templates.md +430 -0
  49. package/dist/skills/defaults/blockchain/nft-standards.md +364 -0
  50. package/dist/skills/defaults/blockchain/solidity-security.md +514 -0
  51. package/dist/skills/defaults/blockchain/web3-testing.md +360 -0
  52. package/dist/skills/defaults/business/competitive-landscape/SKILL.md +527 -0
  53. package/dist/skills/defaults/business/market-sizing-analysis/SKILL.md +451 -0
  54. package/dist/skills/defaults/business/startup-financial-modeling/SKILL.md +494 -0
  55. package/dist/skills/defaults/business/startup-metrics-framework/SKILL.md +564 -0
  56. package/dist/skills/defaults/business/team-composition-analysis.md +437 -0
  57. package/dist/skills/defaults/compliance/employment-contract-templates/SKILL.md +527 -0
  58. package/dist/skills/defaults/compliance/gdpr-data-handling/SKILL.md +630 -0
  59. package/dist/skills/defaults/data-engineering/airflow-dag-patterns.md +436 -0
  60. package/dist/skills/defaults/data-engineering/airflow.md +519 -0
  61. package/dist/skills/defaults/data-engineering/data-quality.md +583 -0
  62. package/dist/skills/defaults/data-engineering/dbt-transformation-patterns.md +482 -0
  63. package/dist/skills/defaults/data-engineering/dbt.md +556 -0
  64. package/dist/skills/defaults/data-engineering/ml-pipeline-workflow/SKILL.md +247 -0
  65. package/dist/skills/defaults/data-engineering/spark-optimization.md +348 -0
  66. package/dist/skills/defaults/data-engineering/spark.md +411 -0
  67. package/dist/skills/defaults/database/postgresql.md +202 -0
  68. package/dist/skills/defaults/debugging/systematic-debugging.md +249 -0
  69. package/dist/skills/defaults/devops/architecture-decision-records.md +448 -0
  70. package/dist/skills/defaults/devops/changelog-automation.md +580 -0
  71. package/dist/skills/defaults/devops/cicd.md +314 -0
  72. package/dist/skills/defaults/devops/cloud.md +263 -0
  73. package/dist/skills/defaults/devops/code-review-excellence.md +299 -0
  74. package/dist/skills/defaults/devops/cost-optimization.md +295 -0
  75. package/dist/skills/defaults/devops/deployment-pipeline-design.md +356 -0
  76. package/dist/skills/defaults/devops/docker.md +281 -0
  77. package/dist/skills/defaults/devops/git-workflows.md +205 -0
  78. package/dist/skills/defaults/devops/github-actions.md +311 -0
  79. package/dist/skills/defaults/devops/gitlab-ci-patterns.md +266 -0
  80. package/dist/skills/defaults/devops/hybrid-cloud-networking.md +241 -0
  81. package/dist/skills/defaults/devops/istio-traffic-management.md +327 -0
  82. package/dist/skills/defaults/devops/kubernetes.md +339 -0
  83. package/dist/skills/defaults/devops/linkerd-patterns.md +311 -0
  84. package/dist/skills/defaults/devops/multi-cloud-architecture.md +181 -0
  85. package/dist/skills/defaults/devops/observability.md +243 -0
  86. package/dist/skills/defaults/devops/openapi-spec-generation.md +1024 -0
  87. package/dist/skills/defaults/devops/postmortem-writing.md +396 -0
  88. package/dist/skills/defaults/devops/prometheus-configuration.md +265 -0
  89. package/dist/skills/defaults/devops/secrets-management.md +341 -0
  90. package/dist/skills/defaults/devops/service-mesh-observability.md +385 -0
  91. package/dist/skills/defaults/devops/terraform-module-library.md +244 -0
  92. package/dist/skills/defaults/finance/backtesting-frameworks/SKILL.md +663 -0
  93. package/dist/skills/defaults/finance/risk-metrics-calculation/SKILL.md +557 -0
  94. package/dist/skills/defaults/frontend/accessibility-compliance.md +420 -0
  95. package/dist/skills/defaults/frontend/design-system-patterns.md +337 -0
  96. package/dist/skills/defaults/frontend/interaction-design.md +327 -0
  97. package/dist/skills/defaults/frontend/javascript.md +311 -0
  98. package/dist/skills/defaults/frontend/modern-javascript-patterns.md +927 -0
  99. package/dist/skills/defaults/frontend/react-native-design.md +440 -0
  100. package/dist/skills/defaults/frontend/react.md +345 -0
  101. package/dist/skills/defaults/frontend/responsive-design.md +472 -0
  102. package/dist/skills/defaults/frontend/tailwind-design-system.md +337 -0
  103. package/dist/skills/defaults/frontend/typescript-advanced-types.md +724 -0
  104. package/dist/skills/defaults/frontend/typescript.md +334 -0
  105. package/dist/skills/defaults/frontend/visual-design-foundations.md +326 -0
  106. package/dist/skills/defaults/frontend/web-component-design.md +279 -0
  107. package/dist/skills/defaults/game-development/godot-gdscript-patterns.md +188 -0
  108. package/dist/skills/defaults/game-development/unity-ecs-patterns.md +594 -0
  109. package/dist/skills/defaults/kubernetes/gitops-workflow.md +285 -0
  110. package/dist/skills/defaults/kubernetes/gitops.md +280 -0
  111. package/dist/skills/defaults/kubernetes/helm-chart-scaffolding.md +553 -0
  112. package/dist/skills/defaults/kubernetes/helm.md +343 -0
  113. package/dist/skills/defaults/kubernetes/k8s-manifest-generator.md +501 -0
  114. package/dist/skills/defaults/kubernetes/k8s-security-policies.md +342 -0
  115. package/dist/skills/defaults/kubernetes/manifests.md +330 -0
  116. package/dist/skills/defaults/kubernetes/security.md +337 -0
  117. package/dist/skills/defaults/llm-application/embedding-strategies.md +608 -0
  118. package/dist/skills/defaults/llm-application/hybrid-search-implementation.md +570 -0
  119. package/dist/skills/defaults/llm-application/hybrid-search.md +570 -0
  120. package/dist/skills/defaults/llm-application/langchain-architecture.md +666 -0
  121. package/dist/skills/defaults/llm-application/langchain.md +259 -0
  122. package/dist/skills/defaults/llm-application/llm-evaluation.md +695 -0
  123. package/dist/skills/defaults/llm-application/prompt-engineering-patterns.md +449 -0
  124. package/dist/skills/defaults/llm-application/prompt-engineering.md +219 -0
  125. package/dist/skills/defaults/llm-application/rag-implementation.md +434 -0
  126. package/dist/skills/defaults/llm-application/similarity-search-patterns.md +560 -0
  127. package/dist/skills/defaults/llm-application/similarity-search.md +560 -0
  128. package/dist/skills/defaults/llm-application/vector-index-tuning.md +523 -0
  129. package/dist/skills/defaults/mobile/mobile-android-design.md +440 -0
  130. package/dist/skills/defaults/mobile/mobile-ios-design.md +266 -0
  131. package/dist/skills/defaults/monitoring/distributed-tracing.md +436 -0
  132. package/dist/skills/defaults/monitoring/grafana-dashboards.md +370 -0
  133. package/dist/skills/defaults/monitoring/prometheus-configuration.md +379 -0
  134. package/dist/skills/defaults/monitoring/slo-implementation.md +323 -0
  135. package/dist/skills/defaults/refactoring/code-refactoring.md +349 -0
  136. package/dist/skills/defaults/security/anti-reversing-techniques/SKILL.md +559 -0
  137. package/dist/skills/defaults/security/auditor.md +168 -0
  138. package/dist/skills/defaults/security/binary-analysis-patterns/SKILL.md +438 -0
  139. package/dist/skills/defaults/security/memory-forensics/SKILL.md +483 -0
  140. package/dist/skills/defaults/security/mtls-configuration.md +349 -0
  141. package/dist/skills/defaults/security/protocol-reverse-engineering/SKILL.md +520 -0
  142. package/dist/skills/defaults/security/sast-configuration.md +182 -0
  143. package/dist/skills/defaults/security/security.md +313 -0
  144. package/dist/skills/defaults/security/stride-analysis.md +273 -0
  145. package/dist/skills/defaults/security/threat-mitigation-mapping.md +290 -0
  146. package/dist/skills/defaults/systems/bash-defensive-patterns/SKILL.md +539 -0
  147. package/dist/skills/defaults/systems/bats-testing-patterns/SKILL.md +631 -0
  148. package/dist/skills/defaults/systems/go-concurrency-patterns.md +657 -0
  149. package/dist/skills/defaults/systems/memory-safety-patterns.md +605 -0
  150. package/dist/skills/defaults/systems/rust-async-patterns.md +519 -0
  151. package/dist/skills/defaults/systems/shellcheck-configuration/SKILL.md +456 -0
  152. package/dist/skills/defaults/team-collaboration/multi-reviewer-patterns.md +126 -0
  153. package/dist/skills/defaults/team-collaboration/parallel-feature-development.md +151 -0
  154. package/dist/skills/defaults/testing/javascript-testing-patterns.md +1021 -0
  155. package/dist/skills/defaults/testing/python-testing-patterns.md +351 -0
  156. package/dist/skills/defaults/testing/testing.md +332 -0
  157. package/dist/skills/defaults/workflows/context-driven-development.md +384 -0
  158. package/dist/skills/defaults/workflows/track-management.md +592 -0
  159. package/dist/skills/defaults/workflows/workflow-patterns.md +622 -0
  160. package/dist/skills/index.d.ts +11 -0
  161. package/dist/skills/index.d.ts.map +1 -0
  162. package/dist/skills/index.js +129 -0
  163. package/dist/skills/index.js.map +1 -0
  164. package/dist/utils/character.js +4 -4
  165. package/dist/utils/character.js.map +1 -1
  166. package/dist/utils/inputbar.d.ts.map +1 -1
  167. package/dist/utils/inputbar.js +7 -0
  168. package/dist/utils/inputbar.js.map +1 -1
  169. package/package.json +1 -1
@@ -0,0 +1,566 @@
1
+ ---
2
+ name: billing-automation
3
+ description: Build automated billing systems for recurring payments, invoicing, subscription lifecycle, and dunning management. Use when implementing subscription billing, automating invoicing, or managing recurring payment systems.
4
+ ---
5
+
6
+ # Billing Automation
7
+
8
+ Master automated billing systems including recurring billing, invoice generation, dunning management, proration, and tax calculation.
9
+
10
+ ## When to Use This Skill
11
+
12
+ - Implementing SaaS subscription billing
13
+ - Automating invoice generation and delivery
14
+ - Managing failed payment recovery (dunning)
15
+ - Calculating prorated charges for plan changes
16
+ - Handling sales tax, VAT, and GST
17
+ - Processing usage-based billing
18
+ - Managing billing cycles and renewals
19
+
20
+ ## Core Concepts
21
+
22
+ ### 1. Billing Cycles
23
+
24
+ **Common Intervals:**
25
+
26
+ - Monthly (most common for SaaS)
27
+ - Annual (discounted long-term)
28
+ - Quarterly
29
+ - Weekly
30
+ - Custom (usage-based, per-seat)
31
+
32
+ ### 2. Subscription States
33
+
34
+ ```
35
+ trial → active → past_due → canceled
36
+ → paused → resumed
37
+ ```
38
+
39
+ ### 3. Dunning Management
40
+
41
+ Automated process to recover failed payments through:
42
+
43
+ - Retry schedules
44
+ - Customer notifications
45
+ - Grace periods
46
+ - Account restrictions
47
+
48
+ ### 4. Proration
49
+
50
+ Adjusting charges when:
51
+
52
+ - Upgrading/downgrading mid-cycle
53
+ - Adding/removing seats
54
+ - Changing billing frequency
55
+
56
+ ## Quick Start
57
+
58
+ ```python
59
+ from billing import BillingEngine, Subscription
60
+
61
+ # Initialize billing engine
62
+ billing = BillingEngine()
63
+
64
+ # Create subscription
65
+ subscription = billing.create_subscription(
66
+ customer_id="cus_123",
67
+ plan_id="plan_pro_monthly",
68
+ billing_cycle_anchor=datetime.now(),
69
+ trial_days=14
70
+ )
71
+
72
+ # Process billing cycle
73
+ billing.process_billing_cycle(subscription.id)
74
+ ```
75
+
76
+ ## Subscription Lifecycle Management
77
+
78
+ ```python
79
+ from datetime import datetime, timedelta
80
+ from enum import Enum
81
+
82
+ class SubscriptionStatus(Enum):
83
+ TRIAL = "trial"
84
+ ACTIVE = "active"
85
+ PAST_DUE = "past_due"
86
+ CANCELED = "canceled"
87
+ PAUSED = "paused"
88
+
89
+ class Subscription:
90
+ def __init__(self, customer_id, plan, billing_cycle_day=None):
91
+ self.id = generate_id()
92
+ self.customer_id = customer_id
93
+ self.plan = plan
94
+ self.status = SubscriptionStatus.TRIAL
95
+ self.current_period_start = datetime.now()
96
+ self.current_period_end = self.current_period_start + timedelta(days=plan.trial_days or 30)
97
+ self.billing_cycle_day = billing_cycle_day or self.current_period_start.day
98
+ self.trial_end = datetime.now() + timedelta(days=plan.trial_days) if plan.trial_days else None
99
+
100
+ def start_trial(self, trial_days):
101
+ """Start trial period."""
102
+ self.status = SubscriptionStatus.TRIAL
103
+ self.trial_end = datetime.now() + timedelta(days=trial_days)
104
+ self.current_period_end = self.trial_end
105
+
106
+ def activate(self):
107
+ """Activate subscription after trial or immediately."""
108
+ self.status = SubscriptionStatus.ACTIVE
109
+ self.current_period_start = datetime.now()
110
+ self.current_period_end = self.calculate_next_billing_date()
111
+
112
+ def mark_past_due(self):
113
+ """Mark subscription as past due after failed payment."""
114
+ self.status = SubscriptionStatus.PAST_DUE
115
+ # Trigger dunning workflow
116
+
117
+ def cancel(self, at_period_end=True):
118
+ """Cancel subscription."""
119
+ if at_period_end:
120
+ self.cancel_at_period_end = True
121
+ # Will cancel when current period ends
122
+ else:
123
+ self.status = SubscriptionStatus.CANCELED
124
+ self.canceled_at = datetime.now()
125
+
126
+ def calculate_next_billing_date(self):
127
+ """Calculate next billing date based on interval."""
128
+ if self.plan.interval == 'month':
129
+ return self.current_period_start + timedelta(days=30)
130
+ elif self.plan.interval == 'year':
131
+ return self.current_period_start + timedelta(days=365)
132
+ elif self.plan.interval == 'week':
133
+ return self.current_period_start + timedelta(days=7)
134
+ ```
135
+
136
+ ## Billing Cycle Processing
137
+
138
+ ```python
139
+ class BillingEngine:
140
+ def process_billing_cycle(self, subscription_id):
141
+ """Process billing for a subscription."""
142
+ subscription = self.get_subscription(subscription_id)
143
+
144
+ # Check if billing is due
145
+ if datetime.now() < subscription.current_period_end:
146
+ return
147
+
148
+ # Generate invoice
149
+ invoice = self.generate_invoice(subscription)
150
+
151
+ # Attempt payment
152
+ payment_result = self.charge_customer(
153
+ subscription.customer_id,
154
+ invoice.total
155
+ )
156
+
157
+ if payment_result.success:
158
+ # Payment successful
159
+ invoice.mark_paid()
160
+ subscription.advance_billing_period()
161
+ self.send_invoice(invoice)
162
+ else:
163
+ # Payment failed
164
+ subscription.mark_past_due()
165
+ self.start_dunning_process(subscription, invoice)
166
+
167
+ def generate_invoice(self, subscription):
168
+ """Generate invoice for billing period."""
169
+ invoice = Invoice(
170
+ customer_id=subscription.customer_id,
171
+ subscription_id=subscription.id,
172
+ period_start=subscription.current_period_start,
173
+ period_end=subscription.current_period_end
174
+ )
175
+
176
+ # Add subscription line item
177
+ invoice.add_line_item(
178
+ description=subscription.plan.name,
179
+ amount=subscription.plan.amount,
180
+ quantity=subscription.quantity or 1
181
+ )
182
+
183
+ # Add usage-based charges if applicable
184
+ if subscription.has_usage_billing:
185
+ usage_charges = self.calculate_usage_charges(subscription)
186
+ invoice.add_line_item(
187
+ description="Usage charges",
188
+ amount=usage_charges
189
+ )
190
+
191
+ # Calculate tax
192
+ tax = self.calculate_tax(invoice.subtotal, subscription.customer)
193
+ invoice.tax = tax
194
+
195
+ invoice.finalize()
196
+ return invoice
197
+
198
+ def charge_customer(self, customer_id, amount):
199
+ """Charge customer using saved payment method."""
200
+ customer = self.get_customer(customer_id)
201
+
202
+ try:
203
+ # Charge using payment processor
204
+ charge = stripe.Charge.create(
205
+ customer=customer.stripe_id,
206
+ amount=int(amount * 100), # Convert to cents
207
+ currency='usd'
208
+ )
209
+
210
+ return PaymentResult(success=True, transaction_id=charge.id)
211
+ except stripe.error.CardError as e:
212
+ return PaymentResult(success=False, error=str(e))
213
+ ```
214
+
215
+ ## Dunning Management
216
+
217
+ ```python
218
+ class DunningManager:
219
+ """Manage failed payment recovery."""
220
+
221
+ def __init__(self):
222
+ self.retry_schedule = [
223
+ {'days': 3, 'email_template': 'payment_failed_first'},
224
+ {'days': 7, 'email_template': 'payment_failed_reminder'},
225
+ {'days': 14, 'email_template': 'payment_failed_final'}
226
+ ]
227
+
228
+ def start_dunning_process(self, subscription, invoice):
229
+ """Start dunning process for failed payment."""
230
+ dunning_attempt = DunningAttempt(
231
+ subscription_id=subscription.id,
232
+ invoice_id=invoice.id,
233
+ attempt_number=1,
234
+ next_retry=datetime.now() + timedelta(days=3)
235
+ )
236
+
237
+ # Send initial failure notification
238
+ self.send_dunning_email(subscription, 'payment_failed_first')
239
+
240
+ # Schedule retries
241
+ self.schedule_retries(dunning_attempt)
242
+
243
+ def retry_payment(self, dunning_attempt):
244
+ """Retry failed payment."""
245
+ subscription = self.get_subscription(dunning_attempt.subscription_id)
246
+ invoice = self.get_invoice(dunning_attempt.invoice_id)
247
+
248
+ # Attempt payment again
249
+ result = self.charge_customer(subscription.customer_id, invoice.total)
250
+
251
+ if result.success:
252
+ # Payment succeeded
253
+ invoice.mark_paid()
254
+ subscription.status = SubscriptionStatus.ACTIVE
255
+ self.send_dunning_email(subscription, 'payment_recovered')
256
+ dunning_attempt.mark_resolved()
257
+ else:
258
+ # Still failing
259
+ dunning_attempt.attempt_number += 1
260
+
261
+ if dunning_attempt.attempt_number < len(self.retry_schedule):
262
+ # Schedule next retry
263
+ next_retry_config = self.retry_schedule[dunning_attempt.attempt_number]
264
+ dunning_attempt.next_retry = datetime.now() + timedelta(days=next_retry_config['days'])
265
+ self.send_dunning_email(subscription, next_retry_config['email_template'])
266
+ else:
267
+ # Exhausted retries, cancel subscription
268
+ subscription.cancel(at_period_end=False)
269
+ self.send_dunning_email(subscription, 'subscription_canceled')
270
+
271
+ def send_dunning_email(self, subscription, template):
272
+ """Send dunning notification to customer."""
273
+ customer = self.get_customer(subscription.customer_id)
274
+
275
+ email_content = self.render_template(template, {
276
+ 'customer_name': customer.name,
277
+ 'amount_due': subscription.plan.amount,
278
+ 'update_payment_url': f"https://app.example.com/billing"
279
+ })
280
+
281
+ send_email(
282
+ to=customer.email,
283
+ subject=email_content['subject'],
284
+ body=email_content['body']
285
+ )
286
+ ```
287
+
288
+ ## Proration
289
+
290
+ ```python
291
+ class ProrationCalculator:
292
+ """Calculate prorated charges for plan changes."""
293
+
294
+ @staticmethod
295
+ def calculate_proration(old_plan, new_plan, period_start, period_end, change_date):
296
+ """Calculate proration for plan change."""
297
+ # Days in current period
298
+ total_days = (period_end - period_start).days
299
+
300
+ # Days used on old plan
301
+ days_used = (change_date - period_start).days
302
+
303
+ # Days remaining on new plan
304
+ days_remaining = (period_end - change_date).days
305
+
306
+ # Calculate prorated amounts
307
+ unused_amount = (old_plan.amount / total_days) * days_remaining
308
+ new_plan_amount = (new_plan.amount / total_days) * days_remaining
309
+
310
+ # Net charge/credit
311
+ proration = new_plan_amount - unused_amount
312
+
313
+ return {
314
+ 'old_plan_credit': -unused_amount,
315
+ 'new_plan_charge': new_plan_amount,
316
+ 'net_proration': proration,
317
+ 'days_used': days_used,
318
+ 'days_remaining': days_remaining
319
+ }
320
+
321
+ @staticmethod
322
+ def calculate_seat_proration(current_seats, new_seats, price_per_seat, period_start, period_end, change_date):
323
+ """Calculate proration for seat changes."""
324
+ total_days = (period_end - period_start).days
325
+ days_remaining = (period_end - change_date).days
326
+
327
+ # Additional seats charge
328
+ additional_seats = new_seats - current_seats
329
+ prorated_amount = (additional_seats * price_per_seat / total_days) * days_remaining
330
+
331
+ return {
332
+ 'additional_seats': additional_seats,
333
+ 'prorated_charge': max(0, prorated_amount), # No refund for removing seats mid-cycle
334
+ 'effective_date': change_date
335
+ }
336
+ ```
337
+
338
+ ## Tax Calculation
339
+
340
+ ```python
341
+ class TaxCalculator:
342
+ """Calculate sales tax, VAT, GST."""
343
+
344
+ def __init__(self):
345
+ # Tax rates by region
346
+ self.tax_rates = {
347
+ 'US_CA': 0.0725, # California sales tax
348
+ 'US_NY': 0.04, # New York sales tax
349
+ 'GB': 0.20, # UK VAT
350
+ 'DE': 0.19, # Germany VAT
351
+ 'FR': 0.20, # France VAT
352
+ 'AU': 0.10, # Australia GST
353
+ }
354
+
355
+ def calculate_tax(self, amount, customer):
356
+ """Calculate applicable tax."""
357
+ # Determine tax jurisdiction
358
+ jurisdiction = self.get_tax_jurisdiction(customer)
359
+
360
+ if not jurisdiction:
361
+ return 0
362
+
363
+ # Get tax rate
364
+ tax_rate = self.tax_rates.get(jurisdiction, 0)
365
+
366
+ # Calculate tax
367
+ tax = amount * tax_rate
368
+
369
+ return {
370
+ 'tax_amount': tax,
371
+ 'tax_rate': tax_rate,
372
+ 'jurisdiction': jurisdiction,
373
+ 'tax_type': self.get_tax_type(jurisdiction)
374
+ }
375
+
376
+ def get_tax_jurisdiction(self, customer):
377
+ """Determine tax jurisdiction based on customer location."""
378
+ if customer.country == 'US':
379
+ # US: Tax based on customer state
380
+ return f"US_{customer.state}"
381
+ elif customer.country in ['GB', 'DE', 'FR']:
382
+ # EU: VAT
383
+ return customer.country
384
+ elif customer.country == 'AU':
385
+ # Australia: GST
386
+ return 'AU'
387
+ else:
388
+ return None
389
+
390
+ def get_tax_type(self, jurisdiction):
391
+ """Get type of tax for jurisdiction."""
392
+ if jurisdiction.startswith('US_'):
393
+ return 'Sales Tax'
394
+ elif jurisdiction in ['GB', 'DE', 'FR']:
395
+ return 'VAT'
396
+ elif jurisdiction == 'AU':
397
+ return 'GST'
398
+ return 'Tax'
399
+
400
+ def validate_vat_number(self, vat_number, country):
401
+ """Validate EU VAT number."""
402
+ # Use VIES API for validation
403
+ # Returns True if valid, False otherwise
404
+ pass
405
+ ```
406
+
407
+ ## Invoice Generation
408
+
409
+ ```python
410
+ class Invoice:
411
+ def __init__(self, customer_id, subscription_id=None):
412
+ self.id = generate_invoice_number()
413
+ self.customer_id = customer_id
414
+ self.subscription_id = subscription_id
415
+ self.status = 'draft'
416
+ self.line_items = []
417
+ self.subtotal = 0
418
+ self.tax = 0
419
+ self.total = 0
420
+ self.created_at = datetime.now()
421
+
422
+ def add_line_item(self, description, amount, quantity=1):
423
+ """Add line item to invoice."""
424
+ line_item = {
425
+ 'description': description,
426
+ 'unit_amount': amount,
427
+ 'quantity': quantity,
428
+ 'total': amount * quantity
429
+ }
430
+ self.line_items.append(line_item)
431
+ self.subtotal += line_item['total']
432
+
433
+ def finalize(self):
434
+ """Finalize invoice and calculate total."""
435
+ self.total = self.subtotal + self.tax
436
+ self.status = 'open'
437
+ self.finalized_at = datetime.now()
438
+
439
+ def mark_paid(self):
440
+ """Mark invoice as paid."""
441
+ self.status = 'paid'
442
+ self.paid_at = datetime.now()
443
+
444
+ def to_pdf(self):
445
+ """Generate PDF invoice."""
446
+ from reportlab.pdfgen import canvas
447
+
448
+ # Generate PDF
449
+ # Include: company info, customer info, line items, tax, total
450
+ pass
451
+
452
+ def to_html(self):
453
+ """Generate HTML invoice."""
454
+ template = """
455
+ <!DOCTYPE html>
456
+ <html>
457
+ <head><title>Invoice #{invoice_number}</title></head>
458
+ <body>
459
+ <h1>Invoice #{invoice_number}</h1>
460
+ <p>Date: {date}</p>
461
+ <h2>Bill To:</h2>
462
+ <p>{customer_name}<br>{customer_address}</p>
463
+ <table>
464
+ <tr><th>Description</th><th>Quantity</th><th>Amount</th></tr>
465
+ {line_items}
466
+ </table>
467
+ <p>Subtotal: ${subtotal}</p>
468
+ <p>Tax: ${tax}</p>
469
+ <h3>Total: ${total}</h3>
470
+ </body>
471
+ </html>
472
+ """
473
+
474
+ return template.format(
475
+ invoice_number=self.id,
476
+ date=self.created_at.strftime('%Y-%m-%d'),
477
+ customer_name=self.customer.name,
478
+ customer_address=self.customer.address,
479
+ line_items=self.render_line_items(),
480
+ subtotal=self.subtotal,
481
+ tax=self.tax,
482
+ total=self.total
483
+ )
484
+ ```
485
+
486
+ ## Usage-Based Billing
487
+
488
+ ```python
489
+ class UsageBillingEngine:
490
+ """Track and bill for usage."""
491
+
492
+ def track_usage(self, customer_id, metric, quantity):
493
+ """Track usage event."""
494
+ UsageRecord.create(
495
+ customer_id=customer_id,
496
+ metric=metric,
497
+ quantity=quantity,
498
+ timestamp=datetime.now()
499
+ )
500
+
501
+ def calculate_usage_charges(self, subscription, period_start, period_end):
502
+ """Calculate charges for usage in billing period."""
503
+ usage_records = UsageRecord.get_for_period(
504
+ subscription.customer_id,
505
+ period_start,
506
+ period_end
507
+ )
508
+
509
+ total_usage = sum(record.quantity for record in usage_records)
510
+
511
+ # Tiered pricing
512
+ if subscription.plan.pricing_model == 'tiered':
513
+ charge = self.calculate_tiered_pricing(total_usage, subscription.plan.tiers)
514
+ # Per-unit pricing
515
+ elif subscription.plan.pricing_model == 'per_unit':
516
+ charge = total_usage * subscription.plan.unit_price
517
+ # Volume pricing
518
+ elif subscription.plan.pricing_model == 'volume':
519
+ charge = self.calculate_volume_pricing(total_usage, subscription.plan.tiers)
520
+
521
+ return charge
522
+
523
+ def calculate_tiered_pricing(self, total_usage, tiers):
524
+ """Calculate cost using tiered pricing."""
525
+ charge = 0
526
+ remaining = total_usage
527
+
528
+ for tier in sorted(tiers, key=lambda x: x['up_to']):
529
+ tier_usage = min(remaining, tier['up_to'] - tier['from'])
530
+ charge += tier_usage * tier['unit_price']
531
+ remaining -= tier_usage
532
+
533
+ if remaining <= 0:
534
+ break
535
+
536
+ return charge
537
+ ```
538
+
539
+ ## Resources
540
+
541
+ - **references/billing-cycles.md**: Billing cycle management
542
+ - **references/dunning-management.md**: Failed payment recovery
543
+ - **references/proration.md**: Prorated charge calculations
544
+ - **references/tax-calculation.md**: Tax/VAT/GST handling
545
+ - **references/invoice-lifecycle.md**: Invoice state management
546
+ - **assets/billing-state-machine.yaml**: Billing workflow
547
+ - **assets/invoice-template.html**: Invoice templates
548
+ - **assets/dunning-policy.yaml**: Dunning configuration
549
+
550
+ ## Best Practices
551
+
552
+ 1. **Automate Everything**: Minimize manual intervention
553
+ 2. **Clear Communication**: Notify customers of billing events
554
+ 3. **Flexible Retry Logic**: Balance recovery with customer experience
555
+ 4. **Accurate Proration**: Fair calculation for plan changes
556
+ 5. **Tax Compliance**: Calculate correct tax for jurisdiction
557
+ 6. **Audit Trail**: Log all billing events
558
+ 7. **Graceful Degradation**: Handle edge cases without breaking
559
+
560
+ ## Common Pitfalls
561
+
562
+ - **Incorrect Proration**: Not accounting for partial periods
563
+ - **Missing Tax**: Forgetting to add tax to invoices
564
+ - **Aggressive Dunning**: Canceling too quickly
565
+ - **No Notifications**: Not informing customers of failures
566
+ - **Hardcoded Cycles**: Not supporting custom billing dates