mirror of
https://github.com/xtr-dev/payload-billing.git
synced 2025-12-10 19:03: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>
166 lines
5.5 KiB
Markdown
166 lines
5.5 KiB
Markdown
# 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:
|
|
|
|
```typescript
|
|
// 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
|
|
|
|
1. **With Customer Relationship + Extractor**:
|
|
- Customer relationship required
|
|
- Customer info auto-populated and read-only
|
|
- Syncs automatically when customer changes
|
|
|
|
2. **With Customer Relationship (no extractor)**:
|
|
- Customer relationship optional
|
|
- Customer info manually editable
|
|
- Either relationship OR customer info required
|
|
|
|
3. **No Customer Collection**:
|
|
- Customer info fields always required and editable
|
|
- No relationship field available
|
|
|
|
## Plugin Configuration
|
|
|
|
### Basic Configuration
|
|
```typescript
|
|
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
|
|
```typescript
|
|
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 `CustomerInfoExtractor` interface
|
|
- 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:
|
|
1. Detects when customer relationship changes
|
|
2. Fetches customer data from the related collection
|
|
3. Extracts customer info using the provided callback
|
|
4. Updates invoice with extracted data
|
|
5. 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 |