Files
payload-billing/CLAUDE.md
Bas van den Aakster 28e9e8d208 docs: Update CLAUDE.md to reflect current implementation
- 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>
2025-09-15 21:40:41 +02:00

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

  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

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 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