mirror of
https://github.com/xtr-dev/payload-billing.git
synced 2025-12-10 10:53:23 +00:00
- Remove outdated payment provider and testing information - Focus on current customer data management features - Document customer info extractor pattern and usage - Include clear configuration examples - Remove references to unimplemented features 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
5.5 KiB
5.5 KiB
PayloadCMS Billing Plugin Development Guidelines
Project Overview
This is a PayloadCMS plugin that provides billing and payment functionality with flexible customer data management and invoice generation capabilities.
Architecture Principles
Core Design
- TypeScript First: Full TypeScript support with strict typing throughout
- PayloadCMS Integration: Deep integration with Payload collections, hooks, and admin UI
- Flexible Customer Data: Support for both relationship-based and embedded customer information
- Callback-based Syncing: Use customer info extractors to keep data in sync
Collections Structure
- Payments: Core payment tracking with provider-specific data
- Customers: Customer management with billing information (optional)
- Invoices: Invoice generation with embedded customer info and optional customer relationship
- Refunds: Refund tracking and management
Code Organization
src/
├── collections/ # PayloadCMS collection configurations
├── types/ # TypeScript type definitions
└── index.ts # Main plugin entry point
Customer Data Management
Customer Info Extractor Pattern
The plugin uses a callback-based approach to extract customer information from customer relationships:
// Define how to extract customer info from your customer collection
const customerInfoExtractor: CustomerInfoExtractor = (customer) => ({
name: customer.name,
email: customer.email,
phone: customer.phone,
company: customer.company,
taxId: customer.taxId,
billingAddress: {
line1: customer.address.line1,
line2: customer.address.line2,
city: customer.address.city,
state: customer.address.state,
postalCode: customer.address.postalCode,
country: customer.address.country,
}
})
Invoice Customer Data Options
-
With Customer Relationship + Extractor:
- Customer relationship required
- Customer info auto-populated and read-only
- Syncs automatically when customer changes
-
With Customer Relationship (no extractor):
- Customer relationship optional
- Customer info manually editable
- Either relationship OR customer info required
-
No Customer Collection:
- Customer info fields always required and editable
- No relationship field available
Plugin Configuration
Basic Configuration
import { billingPlugin, defaultCustomerInfoExtractor } from '@xtr-dev/payload-billing'
billingPlugin({
collections: {
customers: 'customers', // Customer collection slug
invoices: 'invoices', // Invoice collection slug
payments: 'payments', // Payment collection slug
refunds: 'refunds', // Refund collection slug
customerRelation: false, // Disable customer relationship
// OR
customerRelation: 'clients', // Use custom collection slug
},
customerInfoExtractor: defaultCustomerInfoExtractor, // For built-in customer collection
})
Custom Customer Info Extractor
billingPlugin({
customerInfoExtractor: (customer) => ({
name: customer.fullName,
email: customer.contactEmail,
phone: customer.phoneNumber,
company: customer.companyName,
taxId: customer.vatNumber,
billingAddress: {
line1: customer.billing.street,
line2: customer.billing.apartment,
city: customer.billing.city,
state: customer.billing.state,
postalCode: customer.billing.zip,
country: customer.billing.countryCode,
}
})
})
Development Guidelines
TypeScript Guidelines
- Use strict TypeScript configuration
- All customer info extractors must implement
CustomerInfoExtractorinterface - Ensure consistent camelCase naming for all address fields
PayloadCMS Integration
- Follow PayloadCMS plugin patterns and conventions
- Use proper collection configurations with access control
- Utilize PayloadCMS hooks for data syncing and validation
Field Validation Rules
- When using
customerInfoExtractor: customer relationship is required, customer info auto-populated - When not using extractor: either customer relationship OR customer info must be provided
- When no customer collection: customer info is always required
Collections API
Invoice Collection Features
- Automatic invoice number generation (INV-{timestamp})
- Currency validation (3-letter ISO codes)
- Automatic due date setting (30 days from creation)
- Line item total calculations
- Customer info syncing via hooks
Customer Data Syncing
The beforeChange hook automatically:
- Detects when customer relationship changes
- Fetches customer data from the related collection
- Extracts customer info using the provided callback
- Updates invoice with extracted data
- Maintains data consistency across updates
Error Handling
Validation Errors
- Customer relationship required when using extractor
- Customer info required when not using relationship
- Proper error messages for missing required fields
Data Extraction Errors
- Failed customer fetches are logged and throw user-friendly errors
- Invalid customer data is handled gracefully
Performance Considerations
- Customer data is only fetched when relationship changes
- Read-only fields prevent unnecessary manual edits
- Efficient hook execution with proper change detection
Documentation Requirements
- Document all public APIs with examples
- Provide clear customer info extractor examples
- Include configuration guides for different use cases
- Maintain up-to-date TypeScript documentation