refactor: Replace hardcoded billing data seeding with plugin-configurable collection overrides

- Remove `seedBillingData` function for sample data creation
- Update refunds, invoices, and payments collections to use pluginConfig for dynamic overrides
- Introduce utility functions like `extractSlug` for customizable collection slugs
- Streamline customer relation and data extractor logic across collections
This commit is contained in:
2025-09-16 00:06:18 +02:00
parent f17b4c064e
commit 0308e30ebd
10 changed files with 515 additions and 580 deletions

View File

@@ -1,6 +1,11 @@
import { CollectionConfig } from 'payload'
import { FieldsOverride } from '@/plugin/utils'
export const defaults = {
paymentsCollection: 'payments'
paymentsCollection: 'payments',
invoicesCollection: 'invoices',
refundsCollection: 'refunds',
customerRelationSlug: 'customer'
}
// Provider configurations
@@ -51,13 +56,12 @@ export interface BillingPluginConfig {
dashboard?: boolean
}
collections?: {
customerRelation?: boolean | string // false to disable, string for custom collection slug
customers?: string
invoices?: string
payments?: string
refunds?: string
invoices?: string | (Partial<CollectionConfig> & {fields?: FieldsOverride})
payments?: string | (Partial<CollectionConfig> & {fields?: FieldsOverride})
refunds?: string | (Partial<CollectionConfig> & {fields?: FieldsOverride})
}
customerInfoExtractor?: CustomerInfoExtractor // Callback to extract customer info from relationship
customerRelationSlug?: string // Customer collection slug for relationship
disabled?: boolean
providers?: {
mollie?: MollieConfig

View File

@@ -1,6 +1,6 @@
import type { Config } from 'payload'
import { createInvoicesCollection, createPaymentsCollection, createRefundsCollection } from '@/collections'
import { BillingPluginConfig } from '@/plugin/config'
import type { BillingPluginConfig } from '@/plugin/config'
export const billingPlugin = (pluginConfig: BillingPluginConfig = {}) => (config: Config): Config => {
if (pluginConfig.disabled) {
@@ -12,16 +12,10 @@ export const billingPlugin = (pluginConfig: BillingPluginConfig = {}) => (config
config.collections = []
}
const customerSlug = pluginConfig.collections?.customers || 'customers'
config.collections.push(
createPaymentsCollection(pluginConfig.collections?.payments || 'payments'),
createInvoicesCollection(
pluginConfig.collections?.invoices || 'invoices',
pluginConfig.collections?.customerRelation !== false ? customerSlug : undefined,
pluginConfig.customerInfoExtractor
),
createRefundsCollection(pluginConfig.collections?.refunds || 'refunds'),
createPaymentsCollection(pluginConfig),
createInvoicesCollection(pluginConfig),
createRefundsCollection(pluginConfig),
)
// Initialize endpoints

View File

@@ -1,7 +1,58 @@
import { Customer, Refund } from '../../dev/payload-types'
export type Id = string | number
export interface Refund {
id: number;
/**
* The refund ID from the payment provider
*/
providerId: string;
payment: number | Payment;
status: 'pending' | 'processing' | 'succeeded' | 'failed' | 'canceled';
/**
* Refund amount in cents
*/
amount: number;
/**
* ISO 4217 currency code (e.g., USD, EUR)
*/
currency: string;
/**
* Reason for the refund
*/
reason?: ('duplicate' | 'fraudulent' | 'requested_by_customer' | 'other') | null;
/**
* Additional details about the refund
*/
description?: string | null;
/**
* Additional refund metadata
*/
metadata?:
| {
[k: string]: unknown;
}
| unknown[]
| string
| number
| boolean
| null;
/**
* Raw data from the payment provider
*/
providerData?:
| {
[k: string]: unknown;
}
| unknown[]
| string
| number
| boolean
| null;
updatedAt: string;
createdAt: string;
}
export interface Payment {
id: Id;
provider: 'stripe' | 'mollie' | 'test';
@@ -22,7 +73,6 @@ export interface Payment {
* Payment description
*/
description?: string | null;
customer?: (Id | null) | Customer;
invoice?: (Id | null) | Invoice;
/**
* Additional metadata for the payment
@@ -53,7 +103,7 @@ export interface Payment {
createdAt: string;
}
export interface Invoice {
export interface Invoice<TCustomer = unknown> {
id: Id;
/**
* Invoice number (e.g., INV-001)
@@ -62,7 +112,7 @@ export interface Invoice {
/**
* Link to customer record (optional)
*/
customer?: (Id | null) | Customer;
customer?: (Id | null) | TCustomer;
/**
* Customer billing information (auto-populated from customer relationship)
*/
@@ -166,3 +216,4 @@ export interface Invoice {
updatedAt: string;
createdAt: string;
}

5
src/plugin/utils.ts Normal file
View File

@@ -0,0 +1,5 @@
import type { CollectionConfig, Field } from 'payload'
export type FieldsOverride = (args: { defaultFields: Field[] }) => Field[]
export const extractSlug = (arg: string | Partial<CollectionConfig>) => typeof arg === 'string' ? arg : arg.slug!