@happyvertical/smrt-affiliates 0.34.9 → 0.35.1
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.
- package/dist/index.d.ts +72 -9
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +8 -8
- package/dist/smrt-knowledge.json +4 -4
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SmrtCollection } from '@happyvertical/smrt-core';
|
|
2
2
|
import { SmrtObject } from '@happyvertical/smrt-core';
|
|
3
|
+
import { SmrtObjectOptions } from '@happyvertical/smrt-core';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Commission tracks revenue attribution from ad events to partners.
|
|
@@ -104,7 +105,7 @@ export declare class Commission extends SmrtObject {
|
|
|
104
105
|
* Additional metadata as JSON string
|
|
105
106
|
*/
|
|
106
107
|
metadata: string;
|
|
107
|
-
constructor(options?:
|
|
108
|
+
constructor(options?: CommissionOptions);
|
|
108
109
|
/**
|
|
109
110
|
* Check if commission is pending (not yet in a payout)
|
|
110
111
|
*/
|
|
@@ -148,11 +149,11 @@ export declare class Commission extends SmrtObject {
|
|
|
148
149
|
/**
|
|
149
150
|
* Get metadata as object
|
|
150
151
|
*/
|
|
151
|
-
getMetadata(): Record<string,
|
|
152
|
+
getMetadata(): Record<string, unknown>;
|
|
152
153
|
/**
|
|
153
154
|
* Set metadata from object
|
|
154
155
|
*/
|
|
155
|
-
setMetadata(data: Record<string,
|
|
156
|
+
setMetadata(data: Record<string, unknown>): void;
|
|
156
157
|
}
|
|
157
158
|
|
|
158
159
|
export declare class CommissionCollection extends SmrtCollection<Commission> {
|
|
@@ -324,6 +325,26 @@ export declare class CommissionCollection extends SmrtCollection<Commission> {
|
|
|
324
325
|
}>;
|
|
325
326
|
}
|
|
326
327
|
|
|
328
|
+
/**
|
|
329
|
+
* Options for constructing a {@link Commission}.
|
|
330
|
+
*/
|
|
331
|
+
declare interface CommissionOptions extends SmrtObjectOptions {
|
|
332
|
+
eventId?: string;
|
|
333
|
+
partnerId?: string;
|
|
334
|
+
commissionType?: CommissionType;
|
|
335
|
+
grossRevenue?: number;
|
|
336
|
+
commissionRate?: number;
|
|
337
|
+
commissionAmount?: number;
|
|
338
|
+
currency?: string;
|
|
339
|
+
payoutId?: string;
|
|
340
|
+
status?: CommissionStatus;
|
|
341
|
+
eventTimestamp?: Date;
|
|
342
|
+
networkId?: string;
|
|
343
|
+
siteId?: string;
|
|
344
|
+
campaignId?: string;
|
|
345
|
+
metadata?: string;
|
|
346
|
+
}
|
|
347
|
+
|
|
327
348
|
/**
|
|
328
349
|
* Commission status - lifecycle of a commission
|
|
329
350
|
*/
|
|
@@ -447,7 +468,7 @@ export declare class Partner extends SmrtObject {
|
|
|
447
468
|
* (bank details, tax info, etc.)
|
|
448
469
|
*/
|
|
449
470
|
metadata: string;
|
|
450
|
-
constructor(options?:
|
|
471
|
+
constructor(options?: PartnerOptions);
|
|
451
472
|
/**
|
|
452
473
|
* Get partner types as array
|
|
453
474
|
*/
|
|
@@ -495,11 +516,11 @@ export declare class Partner extends SmrtObject {
|
|
|
495
516
|
/**
|
|
496
517
|
* Get metadata as object
|
|
497
518
|
*/
|
|
498
|
-
getMetadata(): Record<string,
|
|
519
|
+
getMetadata(): Record<string, unknown>;
|
|
499
520
|
/**
|
|
500
521
|
* Set metadata from object
|
|
501
522
|
*/
|
|
502
|
-
setMetadata(data: Record<string,
|
|
523
|
+
setMetadata(data: Record<string, unknown>): void;
|
|
503
524
|
/**
|
|
504
525
|
* Calculate effective sales commission rate (after parent share)
|
|
505
526
|
*/
|
|
@@ -594,6 +615,26 @@ export declare class PartnerCollection extends SmrtCollection<Partner> {
|
|
|
594
615
|
findEligibleForPayout(): Promise<Partner[]>;
|
|
595
616
|
}
|
|
596
617
|
|
|
618
|
+
/**
|
|
619
|
+
* Options for constructing a {@link Partner}.
|
|
620
|
+
*/
|
|
621
|
+
declare interface PartnerOptions extends SmrtObjectOptions {
|
|
622
|
+
profileId?: string;
|
|
623
|
+
propertyId?: string;
|
|
624
|
+
partnerTypes?: string;
|
|
625
|
+
parentPartnerId?: string;
|
|
626
|
+
referredById?: string;
|
|
627
|
+
parentCommissionShare?: number;
|
|
628
|
+
displayCommissionRate?: number;
|
|
629
|
+
referralCommissionRate?: number;
|
|
630
|
+
salesCommissionRate?: number;
|
|
631
|
+
payoutThreshold?: number;
|
|
632
|
+
payoutMethod?: PayoutMethod;
|
|
633
|
+
currency?: string;
|
|
634
|
+
status?: PartnerStatus;
|
|
635
|
+
metadata?: string;
|
|
636
|
+
}
|
|
637
|
+
|
|
597
638
|
/**
|
|
598
639
|
* Partner status
|
|
599
640
|
*/
|
|
@@ -710,7 +751,7 @@ export declare class Payout extends SmrtObject {
|
|
|
710
751
|
* Additional metadata as JSON string
|
|
711
752
|
*/
|
|
712
753
|
metadata: string;
|
|
713
|
-
constructor(options?:
|
|
754
|
+
constructor(options?: PayoutOptions);
|
|
714
755
|
/**
|
|
715
756
|
* Check if payout is pending approval
|
|
716
757
|
*/
|
|
@@ -766,11 +807,11 @@ export declare class Payout extends SmrtObject {
|
|
|
766
807
|
/**
|
|
767
808
|
* Get metadata as object
|
|
768
809
|
*/
|
|
769
|
-
getMetadata(): Record<string,
|
|
810
|
+
getMetadata(): Record<string, unknown>;
|
|
770
811
|
/**
|
|
771
812
|
* Set metadata from object
|
|
772
813
|
*/
|
|
773
|
-
setMetadata(data: Record<string,
|
|
814
|
+
setMetadata(data: Record<string, unknown>): void;
|
|
774
815
|
/**
|
|
775
816
|
* Approve the payout for processing
|
|
776
817
|
*
|
|
@@ -918,6 +959,28 @@ export declare enum PayoutMethod {
|
|
|
918
959
|
CREDIT = "credit"
|
|
919
960
|
}
|
|
920
961
|
|
|
962
|
+
/**
|
|
963
|
+
* Options for constructing a {@link Payout}.
|
|
964
|
+
*/
|
|
965
|
+
declare interface PayoutOptions extends SmrtObjectOptions {
|
|
966
|
+
partnerId?: string;
|
|
967
|
+
periodStart?: Date;
|
|
968
|
+
periodEnd?: Date;
|
|
969
|
+
displayEarnings?: number;
|
|
970
|
+
referralEarnings?: number;
|
|
971
|
+
salesEarnings?: number;
|
|
972
|
+
parentEarnings?: number;
|
|
973
|
+
overheadEarnings?: number;
|
|
974
|
+
totalAmount?: number;
|
|
975
|
+
currency?: string;
|
|
976
|
+
invoiceId?: string;
|
|
977
|
+
status?: PayoutStatus;
|
|
978
|
+
paymentReference?: string;
|
|
979
|
+
paidAt?: Date | null;
|
|
980
|
+
notes?: string;
|
|
981
|
+
metadata?: string;
|
|
982
|
+
}
|
|
983
|
+
|
|
921
984
|
/**
|
|
922
985
|
* Payout status - lifecycle of a payout batch
|
|
923
986
|
*/
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/__smrt-register__.ts","../src/types/index.ts","../src/models/Commission.ts","../src/collections/CommissionCollection.ts","../src/models/Partner.ts","../src/collections/PartnerCollection.ts","../src/models/Payout.ts","../src/collections/PayoutCollection.ts"],"sourcesContent":["/**\n * Self-registers this package's build-time manifest before any @smrt() decorator\n * in the package fires. Fixes issue #1132: in consumer runtimes (tsx, SvelteKit\n * SSR, plain `vite dev`) the decorator's synchronous manifest lookup previously\n * missed because no step populated the global manifest cache — classes got\n * registered with zero fields and `save()` / `toJSON()` silently dropped every\n * declared property.\n *\n * Import this module as the first statement in `src/index.ts` so its top-level\n * side effect runs ahead of any class module's @smrt() decorator.\n *\n * Silent no-op in dev/test, where the vitest plugin already populates manifests\n * via a different path. Only needs to succeed in the published dist output.\n *\n * @see https://github.com/happyvertical/smrt/issues/1132\n */\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\n// `new URL('./manifest.json', import.meta.url)` resolves at runtime to the\n// manifest sitting next to this module's compiled output. Vite warns at build\n// time that it cannot pre-resolve the URL; that is the intended behavior —\n// the URL must resolve to dist/manifest.json at runtime, not be inlined.\nObjectRegistry.registerPackageManifest(\n new URL('./manifest.json', import.meta.url),\n);\n","/**\n * Types and enums for smrt-affiliates package\n */\n\n/**\n * Partner types - what role(s) this partner plays\n */\nexport enum PartnerType {\n PUBLISHER = 'publisher',\n SALESPERSON = 'salesperson',\n REFERRER = 'referrer',\n}\n\n/**\n * Partner status\n */\nexport enum PartnerStatus {\n PENDING = 'pending',\n ACTIVE = 'active',\n SUSPENDED = 'suspended',\n}\n\n/**\n * Commission types - how earnings were generated\n */\nexport enum CommissionType {\n DISPLAY = 'display',\n REFERRAL = 'referral',\n SALES = 'sales',\n PARENT = 'parent',\n OVERHEAD = 'overhead',\n}\n\n/**\n * Commission status - lifecycle of a commission\n */\nexport enum CommissionStatus {\n PENDING = 'pending',\n INCLUDED = 'included',\n PAID = 'paid',\n}\n\n/**\n * Payout status - lifecycle of a payout batch\n */\nexport enum PayoutStatus {\n PENDING = 'pending',\n APPROVED = 'approved',\n PROCESSING = 'processing',\n COMPLETED = 'completed',\n FAILED = 'failed',\n}\n\n/**\n * Payout method - how payment is delivered\n */\nexport enum PayoutMethod {\n BANK_TRANSFER = 'bank_transfer',\n CHECK = 'check',\n PAYPAL = 'paypal',\n CREDIT = 'credit',\n}\n","/**\n * Commission model - Revenue attribution per ad event\n * @packageDocumentation\n */\n\nimport {\n crossPackageRef,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { CommissionStatus, CommissionType } from '../types/index.js';\n\n/**\n * Commission tracks revenue attribution from ad events to partners.\n *\n * Each ad event can generate multiple commissions:\n * - Display commission to publisher (site owner)\n * - Referral commission to referrer (who brought in the publisher)\n * - Sales commission to salesperson (who brought in the advertiser)\n * - Parent commission to salesperson's parent publisher\n *\n * References:\n * - eventId: String reference to smrt-ads AdEvent (cross-package)\n * - partnerId: FK to Partner (within package)\n * - payoutId: FK to Payout (within package)\n *\n * @example\n * ```typescript\n * // Create display commission for a publisher\n * const commission = await commissions.create({\n * eventId: 'adevent-uuid',\n * partnerId: publisher.id,\n * commissionType: CommissionType.DISPLAY,\n * grossRevenue: 100, // 1 cent = $0.01\n * commissionRate: 0.50,\n * commissionAmount: 50, // 0.5 cents\n * currency: 'CAD',\n * status: CommissionStatus.PENDING\n * });\n * ```\n */\n// Intentional exception to standards.md §7 (`@TenantScoped`):\n// `Commission` is deliberately NOT tenant-scoped. The affiliate network\n// attributes revenue to a `Partner` across whichever tenant generated the\n// underlying ad event; cross-tenant attribution is the point of the network.\n// Tenant-attributed reporting should aggregate by joining back through\n// `eventId` (smrt-ads). See `packages/affiliates/CLAUDE.md` \"Tenancy\" section.\n@smrt({\n api: { include: ['create', 'list', 'get'] }, // No delete (audit trail)\n mcp: { include: ['create', 'list'] },\n cli: false, // High volume, not useful in CLI\n})\nexport class Commission extends SmrtObject {\n /**\n * Calculate commission amount from gross revenue and rate\n *\n * @param grossRevenue - Gross revenue in cents\n * @param rate - Commission rate (0-1)\n * @returns Commission amount in cents (rounded)\n *\n * @example\n * ```typescript\n * const amount = Commission.calculateAmount(1000, 0.50); // 500 cents\n * ```\n */\n static calculateAmount(grossRevenue: number, rate: number): number {\n return Math.round(grossRevenue * rate);\n }\n /**\n * Ad Event ID (FK to smrt-ads AdEvent, cross-package)\n */\n @crossPackageRef('@happyvertical/smrt-ads:AdEvent')\n eventId: string = '';\n\n /**\n * Partner ID (FK to Partner)\n */\n @foreignKey('Partner')\n partnerId: string = '';\n\n /**\n * Commission type (display, referral, sales, parent)\n */\n commissionType: CommissionType = CommissionType.DISPLAY;\n\n /**\n * Gross revenue from the event in cents\n * This is the total ad revenue before commission split\n */\n grossRevenue: number = 0;\n\n /**\n * Commission rate applied (0-1)\n * Copied from partner at time of event for audit trail\n */\n commissionRate: number = 0;\n\n /**\n * Calculated commission amount in cents\n * = grossRevenue * commissionRate\n */\n commissionAmount: number = 0;\n\n /**\n * Currency code\n * Defaults to CAD\n */\n currency: string = 'CAD';\n\n /**\n * Payout ID when commission is included in a payout\n */\n @foreignKey('Payout')\n payoutId: string = '';\n\n /**\n * Commission status\n */\n status: CommissionStatus = CommissionStatus.PENDING;\n\n /**\n * Event timestamp (copied from AdEvent for reporting)\n */\n eventTimestamp: Date = new Date();\n\n /**\n * Network ID for aggregate queries (optional context)\n */\n networkId: string = '';\n\n /**\n * Site/Property ID for aggregate queries (optional context)\n */\n siteId: string = '';\n\n /**\n * Campaign ID for aggregate queries (optional context)\n */\n campaignId: string = '';\n\n /**\n * Additional metadata as JSON string\n */\n metadata: string = '';\n\n constructor(options: any = {}) {\n super(options);\n if (options.eventId !== undefined) this.eventId = options.eventId;\n if (options.partnerId !== undefined) this.partnerId = options.partnerId;\n if (options.commissionType !== undefined)\n this.commissionType = options.commissionType;\n if (options.grossRevenue !== undefined)\n this.grossRevenue = options.grossRevenue;\n if (options.commissionRate !== undefined)\n this.commissionRate = options.commissionRate;\n if (options.commissionAmount !== undefined)\n this.commissionAmount = options.commissionAmount;\n if (options.currency !== undefined) this.currency = options.currency;\n if (options.payoutId !== undefined) this.payoutId = options.payoutId;\n if (options.status !== undefined) this.status = options.status;\n if (options.eventTimestamp !== undefined)\n this.eventTimestamp = options.eventTimestamp;\n if (options.networkId !== undefined) this.networkId = options.networkId;\n if (options.siteId !== undefined) this.siteId = options.siteId;\n if (options.campaignId !== undefined) this.campaignId = options.campaignId;\n if (options.metadata !== undefined) this.metadata = options.metadata;\n }\n\n /**\n * Check if commission is pending (not yet in a payout)\n */\n isPending(): boolean {\n return this.status === CommissionStatus.PENDING;\n }\n\n /**\n * Check if commission is included in a payout\n */\n isIncluded(): boolean {\n return this.status === CommissionStatus.INCLUDED;\n }\n\n /**\n * Check if commission has been paid\n */\n isPaid(): boolean {\n return this.status === CommissionStatus.PAID;\n }\n\n /**\n * Check if this is a display commission\n */\n isDisplay(): boolean {\n return this.commissionType === CommissionType.DISPLAY;\n }\n\n /**\n * Check if this is a referral commission\n */\n isReferral(): boolean {\n return this.commissionType === CommissionType.REFERRAL;\n }\n\n /**\n * Check if this is a sales commission\n */\n isSales(): boolean {\n return this.commissionType === CommissionType.SALES;\n }\n\n /**\n * Check if this is a parent commission\n */\n isParent(): boolean {\n return this.commissionType === CommissionType.PARENT;\n }\n\n /**\n * Check if this is an overhead commission\n */\n isOverhead(): boolean {\n return this.commissionType === CommissionType.OVERHEAD;\n }\n\n /**\n * Get commission amount in dollars (for display)\n */\n getAmountInDollars(): number {\n return this.commissionAmount / 100;\n }\n\n /**\n * Get gross revenue in dollars (for display)\n */\n getGrossRevenueInDollars(): number {\n return this.grossRevenue / 100;\n }\n\n /**\n * Get metadata as object\n */\n getMetadata(): Record<string, any> {\n if (!this.metadata) return {};\n try {\n return JSON.parse(this.metadata);\n } catch {\n return {};\n }\n }\n\n /**\n * Set metadata from object\n */\n setMetadata(data: Record<string, any>): void {\n this.metadata = JSON.stringify(data);\n }\n}\n\nexport default Commission;\n","/**\n * CommissionCollection - Collection manager for Commission objects\n * @packageDocumentation\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { Commission } from '../models/Commission.js';\nimport { CommissionStatus, CommissionType } from '../types/index.js';\n\nexport class CommissionCollection extends SmrtCollection<Commission> {\n static readonly _itemClass = Commission;\n\n /**\n * Find commissions by partner\n *\n * @param partnerId - Partner ID\n * @returns Array of commissions\n */\n async findByPartner(partnerId: string): Promise<Commission[]> {\n return await this.list({\n where: { partnerId },\n orderBy: 'event_timestamp DESC',\n });\n }\n\n /**\n * Find commissions by ad event\n *\n * @param eventId - Ad Event ID\n * @returns Array of commissions\n */\n async findByEvent(eventId: string): Promise<Commission[]> {\n return await this.list({\n where: { eventId },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find commissions by payout\n *\n * @param payoutId - Payout ID\n * @returns Array of commissions\n */\n async findByPayout(payoutId: string): Promise<Commission[]> {\n return await this.list({\n where: { payoutId },\n orderBy: 'event_timestamp DESC',\n });\n }\n\n /**\n * Find commissions by status\n *\n * @param status - Commission status\n * @returns Array of commissions\n */\n async findByStatus(status: CommissionStatus): Promise<Commission[]> {\n return await this.list({\n where: { status },\n orderBy: 'event_timestamp DESC',\n });\n }\n\n /**\n * Find all pending commissions\n */\n async findPending(): Promise<Commission[]> {\n return await this.findByStatus(CommissionStatus.PENDING);\n }\n\n /**\n * Find pending commissions for a partner\n *\n * @param partnerId - Partner ID\n * @returns Array of pending commissions\n */\n async findPendingByPartner(partnerId: string): Promise<Commission[]> {\n return await this.list({\n where: { partnerId, status: CommissionStatus.PENDING },\n orderBy: 'event_timestamp DESC',\n });\n }\n\n /**\n * Find commissions by type\n *\n * @param commissionType - Commission type\n * @returns Array of commissions\n */\n async findByType(commissionType: CommissionType): Promise<Commission[]> {\n return await this.list({\n where: { commissionType },\n orderBy: 'event_timestamp DESC',\n });\n }\n\n /**\n * Find commissions in date range\n *\n * @param start - Start date\n * @param end - End date\n * @returns Array of commissions\n */\n async findByDateRange(start: Date, end: Date): Promise<Commission[]> {\n return await this.list({\n where: {\n 'event_timestamp >=': start.toISOString(),\n 'event_timestamp <=': end.toISOString(),\n },\n orderBy: 'event_timestamp DESC',\n });\n }\n\n /**\n * Find commissions for a partner in date range\n *\n * @param partnerId - Partner ID\n * @param start - Start date\n * @param end - End date\n * @returns Array of commissions\n */\n async findByPartnerAndDateRange(\n partnerId: string,\n start: Date,\n end: Date,\n ): Promise<Commission[]> {\n return await this.list({\n where: {\n partnerId,\n 'event_timestamp >=': start.toISOString(),\n 'event_timestamp <=': end.toISOString(),\n },\n orderBy: 'event_timestamp DESC',\n });\n }\n\n // --- Network-scoped queries ---\n\n /**\n * Find all commissions for a network\n *\n * @param networkId - Network ID\n * @returns Array of commissions\n */\n async findByNetwork(networkId: string): Promise<Commission[]> {\n return await this.list({\n where: { networkId },\n orderBy: 'event_timestamp DESC',\n });\n }\n\n /**\n * Find commissions for a network filtered by type\n *\n * @param networkId - Network ID\n * @param commissionType - Commission type\n * @returns Array of commissions\n */\n async findByNetworkAndType(\n networkId: string,\n commissionType: CommissionType,\n ): Promise<Commission[]> {\n return await this.list({\n where: { networkId, commissionType },\n orderBy: 'event_timestamp DESC',\n });\n }\n\n /**\n * Find pending commissions for a network\n *\n * @param networkId - Network ID\n * @returns Array of pending commissions\n */\n async findPendingByNetwork(networkId: string): Promise<Commission[]> {\n return await this.list({\n where: { networkId, status: CommissionStatus.PENDING },\n orderBy: 'event_timestamp DESC',\n });\n }\n\n /**\n * Get aggregate summary of commissions by type and site for a network.\n *\n * @param networkId - Network ID\n * @param options - Optional filters (siteId, from, to, commissionType)\n * @returns Summary with byType, bySite, total, and count\n */\n async getSummaryByNetwork(\n networkId: string,\n options: {\n siteId?: string;\n from?: Date;\n to?: Date;\n commissionType?: CommissionType;\n } = {},\n ): Promise<{\n byType: Record<string, number>;\n bySite: Record<string, number>;\n total: number;\n count: number;\n }> {\n const where: Record<string, unknown> = { networkId };\n if (options.siteId) where.siteId = options.siteId;\n if (options.commissionType) where.commissionType = options.commissionType;\n if (options.from) where['event_timestamp >='] = options.from.toISOString();\n if (options.to) where['event_timestamp <='] = options.to.toISOString();\n\n const filtered = await this.list({ where });\n\n const byType: Record<string, number> = {\n overhead: 0,\n display: 0,\n referral: 0,\n sales: 0,\n parent: 0,\n };\n const bySite: Record<string, number> = {};\n let total = 0;\n\n for (const c of filtered) {\n byType[c.commissionType] =\n (byType[c.commissionType] ?? 0) + c.commissionAmount;\n if (c.siteId) {\n bySite[c.siteId] = (bySite[c.siteId] ?? 0) + c.commissionAmount;\n }\n total += c.commissionAmount;\n }\n\n return { byType, bySite, total, count: filtered.length };\n }\n\n /**\n * Get pending commissions grouped by partnerId for a network.\n *\n * @param networkId - Network ID\n * @returns Array of payout groups (partnerId, totalPending, currency, entries)\n */\n async getPendingPayoutsByNetwork(networkId: string): Promise<\n Array<{\n partnerId: string;\n totalPending: number;\n currency: string;\n entryCount: number;\n entries: Array<{\n id: string;\n commissionType: string;\n commissionAmount: number;\n campaignId: string;\n siteId: string;\n }>;\n }>\n > {\n const pending = await this.findPendingByNetwork(networkId);\n\n // Filter to entries with a partnerId\n const withPartner = pending.filter(\n (c) => c.partnerId && c.partnerId !== '',\n );\n\n // Group by partnerId\n const grouped = new Map<string, Commission[]>();\n for (const c of withPartner) {\n const existing = grouped.get(c.partnerId) ?? [];\n existing.push(c);\n grouped.set(c.partnerId, existing);\n }\n\n const payouts: Array<{\n partnerId: string;\n totalPending: number;\n currency: string;\n entryCount: number;\n entries: Array<{\n id: string;\n commissionType: string;\n commissionAmount: number;\n campaignId: string;\n siteId: string;\n }>;\n }> = [];\n for (const [partnerId, group] of grouped) {\n const totalPending = group.reduce(\n (sum, c) => sum + c.commissionAmount,\n 0,\n );\n const currency = group[0]?.currency ?? 'CAD';\n\n payouts.push({\n partnerId,\n totalPending,\n currency,\n entryCount: group.length,\n entries: group.map((c) => ({\n id: c.id ?? '',\n commissionType: c.commissionType,\n commissionAmount: c.commissionAmount,\n campaignId: c.campaignId,\n siteId: c.siteId,\n })),\n });\n }\n\n // Sort by total pending descending\n payouts.sort((a, b) => b.totalPending - a.totalPending);\n\n return payouts;\n }\n\n // --- Aggregation queries ---\n\n /**\n * Sum pending commissions for a partner\n *\n * @param partnerId - Partner ID\n * @returns Total pending amount in cents\n */\n async sumPendingByPartner(partnerId: string): Promise<number> {\n const pending = await this.findPendingByPartner(partnerId);\n return pending.reduce((sum, c) => sum + c.commissionAmount, 0);\n }\n\n /**\n * Sum commissions by type for a partner\n *\n * @param partnerId - Partner ID\n * @param commissionType - Commission type\n * @returns Total amount in cents\n */\n async sumByPartnerAndType(\n partnerId: string,\n commissionType: CommissionType,\n ): Promise<number> {\n const commissions = await this.list({\n where: { partnerId, commissionType },\n });\n return commissions.reduce((sum, c) => sum + c.commissionAmount, 0);\n }\n\n /**\n * Get earnings breakdown for a partner\n *\n * @param partnerId - Partner ID\n * @returns Breakdown by commission type\n */\n async getEarningsBreakdown(partnerId: string): Promise<{\n display: number;\n referral: number;\n sales: number;\n parent: number;\n overhead: number;\n total: number;\n }> {\n const commissions = await this.findByPartner(partnerId);\n const breakdown = {\n display: 0,\n referral: 0,\n sales: 0,\n parent: 0,\n overhead: 0,\n total: 0,\n };\n\n for (const c of commissions) {\n if (c.isPaid() || c.isIncluded()) {\n switch (c.commissionType) {\n case CommissionType.DISPLAY:\n breakdown.display += c.commissionAmount;\n break;\n case CommissionType.REFERRAL:\n breakdown.referral += c.commissionAmount;\n break;\n case CommissionType.SALES:\n breakdown.sales += c.commissionAmount;\n break;\n case CommissionType.PARENT:\n breakdown.parent += c.commissionAmount;\n break;\n case CommissionType.OVERHEAD:\n breakdown.overhead += c.commissionAmount;\n break;\n }\n }\n }\n\n breakdown.total =\n breakdown.display +\n breakdown.referral +\n breakdown.sales +\n breakdown.parent +\n breakdown.overhead;\n return breakdown;\n }\n\n /**\n * Get pending earnings breakdown for a partner\n *\n * @param partnerId - Partner ID\n * @returns Breakdown of pending commissions by type\n */\n async getPendingBreakdown(partnerId: string): Promise<{\n display: number;\n referral: number;\n sales: number;\n parent: number;\n overhead: number;\n total: number;\n }> {\n const pending = await this.findPendingByPartner(partnerId);\n const breakdown = {\n display: 0,\n referral: 0,\n sales: 0,\n parent: 0,\n overhead: 0,\n total: 0,\n };\n\n for (const c of pending) {\n switch (c.commissionType) {\n case CommissionType.DISPLAY:\n breakdown.display += c.commissionAmount;\n break;\n case CommissionType.REFERRAL:\n breakdown.referral += c.commissionAmount;\n break;\n case CommissionType.SALES:\n breakdown.sales += c.commissionAmount;\n break;\n case CommissionType.PARENT:\n breakdown.parent += c.commissionAmount;\n break;\n case CommissionType.OVERHEAD:\n breakdown.overhead += c.commissionAmount;\n break;\n }\n }\n\n breakdown.total =\n breakdown.display +\n breakdown.referral +\n breakdown.sales +\n breakdown.parent +\n breakdown.overhead;\n return breakdown;\n }\n}\n","/**\n * Partner model - Affiliate partner earning entity\n * @packageDocumentation\n */\n\nimport {\n crossPackageRef,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { PartnerStatus, PartnerType, PayoutMethod } from '../types/index.js';\n\n/**\n * Partner represents an entity that earns commissions from ad revenue.\n *\n * Partners can be:\n * - Publishers: Own sites that display ads (earn display commissions)\n * - Salespeople: Bring in advertisers (earn sales commissions)\n * - Referrers: Refer new publishers/partners (earn referral commissions)\n *\n * References:\n * - profileId: String reference to smrt-profiles Profile (cross-package)\n * - propertyId: String reference to smrt-properties Property (cross-package)\n * - parentPartnerId: Self-reference for site-attached salespeople\n *\n * @example\n * ```typescript\n * // Create a publisher partner\n * const publisher = await partners.create({\n * profileId: 'profile-uuid',\n * propertyId: 'property-uuid',\n * partnerTypes: JSON.stringify([PartnerType.PUBLISHER]),\n * displayCommissionRate: 0.50,\n * status: PartnerStatus.ACTIVE\n * });\n *\n * // Create a salesperson attached to a publisher\n * const salesperson = await partners.create({\n * profileId: 'salesperson-profile-uuid',\n * parentPartnerId: publisher.id,\n * partnerTypes: JSON.stringify([PartnerType.SALESPERSON]),\n * salesCommissionRate: 0.10,\n * parentCommissionShare: 0.20,\n * status: PartnerStatus.ACTIVE\n * });\n * ```\n */\n// Intentional exception to standards.md §7 (`@TenantScoped`):\n// `Partner` is deliberately NOT tenant-scoped. A single partner (e.g. a\n// publisher operating sites across multiple tenants) needs a stable identity\n// for revenue aggregation, payout thresholds, and tax reporting; slicing\n// identity per tenant would duplicate the row or hide payouts owed across\n// tenants. See `packages/affiliates/CLAUDE.md` \"Tenancy\" section.\n@smrt({\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get', 'create'] },\n cli: true,\n})\nexport class Partner extends SmrtObject {\n /**\n * Profile ID (FK to smrt-profiles Profile, cross-package)\n */\n @crossPackageRef('@happyvertical/smrt-profiles:Profile')\n profileId: string = '';\n\n /**\n * Property ID (FK to smrt-properties Property, cross-package)\n * Only set for publisher partners\n */\n @crossPackageRef('@happyvertical/smrt-properties:Property')\n propertyId: string = '';\n\n /**\n * Partner types as JSON array (publisher, salesperson, referrer)\n * A partner can have multiple types\n */\n partnerTypes: string = '[]';\n\n /**\n * Parent partner ID (self-reference)\n * For site-attached salespeople, this is the publisher they work under\n */\n @foreignKey('Partner')\n parentPartnerId: string = '';\n\n /**\n * Referred by partner ID (self-reference)\n * Tracks who referred this partner for referral commission attribution\n */\n @foreignKey('Partner')\n referredById: string = '';\n\n /**\n * Share of commission that goes to parent partner (0-1)\n * e.g., 0.20 means 20% of this partner's sales commission goes to parent\n */\n parentCommissionShare: number = 0;\n\n /**\n * Commission rate for display (impression) revenue (0-1)\n * Default 50% - publisher earns half of ad impression revenue\n */\n displayCommissionRate: number = 0.5;\n\n /**\n * Commission rate for referral revenue (0-1)\n * Default 5% - referrer earns 5% of referred partner's first-year revenue\n */\n referralCommissionRate: number = 0.05;\n\n /**\n * Commission rate for sales revenue (0-1)\n * Default 10% - salesperson earns 10% of advertiser spend they brought in\n */\n salesCommissionRate: number = 0.1;\n\n /**\n * Minimum payout threshold in cents\n * Default $50 = 5000 cents\n */\n payoutThreshold: number = 5000;\n\n /**\n * Preferred payout method\n */\n payoutMethod: PayoutMethod = PayoutMethod.BANK_TRANSFER;\n\n /**\n * Currency code for all monetary values\n * Defaults to CAD, allows future multi-currency support\n */\n currency: string = 'CAD';\n\n /**\n * Partner status\n */\n status: PartnerStatus = PartnerStatus.PENDING;\n\n /**\n * Additional metadata as JSON string\n * (bank details, tax info, etc.)\n */\n metadata: string = '';\n\n constructor(options: any = {}) {\n super(options);\n if (options.profileId !== undefined) this.profileId = options.profileId;\n if (options.propertyId !== undefined) this.propertyId = options.propertyId;\n if (options.partnerTypes !== undefined)\n this.partnerTypes = options.partnerTypes;\n if (options.parentPartnerId !== undefined)\n this.parentPartnerId = options.parentPartnerId;\n if (options.referredById !== undefined)\n this.referredById = options.referredById;\n if (options.parentCommissionShare !== undefined)\n this.parentCommissionShare = options.parentCommissionShare;\n if (options.displayCommissionRate !== undefined)\n this.displayCommissionRate = options.displayCommissionRate;\n if (options.referralCommissionRate !== undefined)\n this.referralCommissionRate = options.referralCommissionRate;\n if (options.salesCommissionRate !== undefined)\n this.salesCommissionRate = options.salesCommissionRate;\n if (options.payoutThreshold !== undefined)\n this.payoutThreshold = options.payoutThreshold;\n if (options.payoutMethod !== undefined)\n this.payoutMethod = options.payoutMethod;\n if (options.currency !== undefined) this.currency = options.currency;\n if (options.status !== undefined) this.status = options.status;\n if (options.metadata !== undefined) this.metadata = options.metadata;\n }\n\n /**\n * Get partner types as array\n */\n getPartnerTypes(): PartnerType[] {\n if (!this.partnerTypes) return [];\n try {\n return JSON.parse(this.partnerTypes);\n } catch {\n return [];\n }\n }\n\n /**\n * Set partner types from array\n */\n setPartnerTypes(types: PartnerType[]): void {\n this.partnerTypes = JSON.stringify(types);\n }\n\n /**\n * Check if partner has a specific type\n */\n hasType(type: PartnerType): boolean {\n return this.getPartnerTypes().includes(type);\n }\n\n /**\n * Check if partner is a publisher\n */\n isPublisher(): boolean {\n return this.hasType(PartnerType.PUBLISHER);\n }\n\n /**\n * Check if partner is a salesperson\n */\n isSalesperson(): boolean {\n return this.hasType(PartnerType.SALESPERSON);\n }\n\n /**\n * Check if partner is a referrer\n */\n isReferrer(): boolean {\n return this.hasType(PartnerType.REFERRER);\n }\n\n /**\n * Check if partner is active\n */\n isActive(): boolean {\n return this.status === PartnerStatus.ACTIVE;\n }\n\n /**\n * Check if partner is pending approval\n */\n isPending(): boolean {\n return this.status === PartnerStatus.PENDING;\n }\n\n /**\n * Check if partner is suspended\n */\n isSuspended(): boolean {\n return this.status === PartnerStatus.SUSPENDED;\n }\n\n /**\n * Check if partner has a parent (site-attached)\n */\n hasParent(): boolean {\n return !!this.parentPartnerId;\n }\n\n /**\n * Check if partner was referred by another partner\n */\n wasReferred(): boolean {\n return !!this.referredById;\n }\n\n /**\n * Get metadata as object\n */\n getMetadata(): Record<string, any> {\n if (!this.metadata) return {};\n try {\n return JSON.parse(this.metadata);\n } catch {\n return {};\n }\n }\n\n /**\n * Set metadata from object\n */\n setMetadata(data: Record<string, any>): void {\n this.metadata = JSON.stringify(data);\n }\n\n /**\n * Calculate effective sales commission rate (after parent share)\n */\n getEffectiveSalesRate(): number {\n if (this.parentPartnerId && this.parentCommissionShare > 0) {\n return this.salesCommissionRate * (1 - this.parentCommissionShare);\n }\n return this.salesCommissionRate;\n }\n}\n\nexport default Partner;\n","/**\n * PartnerCollection - Collection manager for Partner objects\n * @packageDocumentation\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { Partner } from '../models/Partner.js';\nimport { PartnerStatus, PartnerType } from '../types/index.js';\n\nexport class PartnerCollection extends SmrtCollection<Partner> {\n static readonly _itemClass = Partner;\n\n /**\n * Find partners by profile ID\n *\n * @param profileId - Profile ID\n * @returns Array of partners\n */\n async findByProfile(profileId: string): Promise<Partner[]> {\n return await this.list({\n where: { profileId },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find partner by property ID (publishers)\n *\n * @param propertyId - Property ID\n * @returns Partner or null\n */\n async findByProperty(propertyId: string): Promise<Partner | null> {\n const results = await this.list({\n where: { propertyId },\n limit: 1,\n });\n return results[0] || null;\n }\n\n /**\n * Find partners by parent partner ID\n *\n * @param parentPartnerId - Parent partner ID\n * @returns Array of child partners\n */\n async findByParent(parentPartnerId: string): Promise<Partner[]> {\n return await this.list({\n where: { parentPartnerId },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find partners referred by a specific partner\n *\n * @param referredById - Referrer partner ID\n * @returns Array of referred partners\n */\n async findByReferrer(referredById: string): Promise<Partner[]> {\n return await this.list({\n where: { referredById },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find partners by status\n *\n * @param status - Partner status\n * @returns Array of partners\n */\n async findByStatus(status: PartnerStatus): Promise<Partner[]> {\n return await this.list({\n where: { status },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find all active partners\n */\n async findActive(): Promise<Partner[]> {\n return await this.findByStatus(PartnerStatus.ACTIVE);\n }\n\n /**\n * Find all pending partners (awaiting approval)\n */\n async findPending(): Promise<Partner[]> {\n return await this.findByStatus(PartnerStatus.PENDING);\n }\n\n /**\n * Find all suspended partners\n */\n async findSuspended(): Promise<Partner[]> {\n return await this.findByStatus(PartnerStatus.SUSPENDED);\n }\n\n /**\n * Find partners by type (requires in-memory filtering for JSON field)\n *\n * @param type - Partner type to filter by\n * @returns Array of partners with that type\n */\n async findByType(type: PartnerType): Promise<Partner[]> {\n const all = await this.list({});\n return all.filter((partner) => partner.hasType(type));\n }\n\n /**\n * Find all publisher partners\n */\n async findPublishers(): Promise<Partner[]> {\n return await this.findByType(PartnerType.PUBLISHER);\n }\n\n /**\n * Find all salesperson partners\n */\n async findSalespeople(): Promise<Partner[]> {\n return await this.findByType(PartnerType.SALESPERSON);\n }\n\n /**\n * Find all referrer partners\n */\n async findReferrers(): Promise<Partner[]> {\n return await this.findByType(PartnerType.REFERRER);\n }\n\n /**\n * Find active publishers (for ad serving)\n */\n async findActivePublishers(): Promise<Partner[]> {\n const publishers = await this.findPublishers();\n return publishers.filter((p) => p.isActive());\n }\n\n /**\n * Find partner for ad serving by property ID\n * Returns active publisher partner for the property\n *\n * @param propertyId - Property ID\n * @returns Active publisher partner or null\n */\n async findActiveByProperty(propertyId: string): Promise<Partner | null> {\n const partner = await this.findByProperty(propertyId);\n if (partner?.isActive() && partner.isPublisher()) {\n return partner;\n }\n return null;\n }\n\n /**\n * Find partners eligible for payout\n * (active partners with pending commissions above threshold)\n * Note: Actual threshold check requires joining with commissions\n */\n async findEligibleForPayout(): Promise<Partner[]> {\n const active = await this.findActive();\n // Actual eligibility check happens in payout service\n // which sums pending commissions per partner\n return active;\n }\n}\n","/**\n * Payout model - Aggregated payout batch for a partner\n * @packageDocumentation\n */\n\nimport {\n crossPackageRef,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { PayoutStatus } from '../types/index.js';\n\n/**\n * Payout represents an aggregated payment batch for a partner.\n *\n * Payouts are created periodically (e.g., monthly) and include\n * all pending commissions for a partner that meet the threshold.\n *\n * References:\n * - partnerId: FK to Partner (within package)\n * - invoiceId: String reference to smrt-commerce Invoice (cross-package)\n *\n * @example\n * ```typescript\n * // Create a payout for a partner\n * const payout = await payouts.create({\n * partnerId: publisher.id,\n * periodStart: new Date('2024-01-01'),\n * periodEnd: new Date('2024-01-31'),\n * displayEarnings: 25000, // $250.00\n * referralEarnings: 500, // $5.00\n * salesEarnings: 0,\n * parentEarnings: 0,\n * totalAmount: 25500, // $255.00\n * currency: 'CAD',\n * status: PayoutStatus.PENDING\n * });\n * ```\n */\n// Intentional exception to standards.md §7 (`@TenantScoped`):\n// `Payout` is deliberately NOT tenant-scoped. Payouts aggregate commissions\n// for a `Partner` regardless of which tenant generated the underlying revenue;\n// a tenant-scoped query would systematically under-report what is owed. See\n// `packages/affiliates/CLAUDE.md` \"Tenancy\" section.\n@smrt({\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get', 'create'] },\n cli: true,\n})\nexport class Payout extends SmrtObject {\n /**\n * Partner ID (FK to Partner)\n */\n @foreignKey('Partner')\n partnerId: string = '';\n\n /**\n * Period start date\n */\n periodStart: Date = new Date();\n\n /**\n * Period end date\n */\n periodEnd: Date = new Date();\n\n /**\n * Total display earnings in cents\n */\n displayEarnings: number = 0;\n\n /**\n * Total referral earnings in cents\n */\n referralEarnings: number = 0;\n\n /**\n * Total sales earnings in cents\n */\n salesEarnings: number = 0;\n\n /**\n * Total parent earnings in cents (from site-attached salespeople)\n */\n parentEarnings: number = 0;\n\n /**\n * Total overhead earnings in cents (network overhead commissions)\n */\n overheadEarnings: number = 0;\n\n /**\n * Total payout amount in cents\n * = displayEarnings + referralEarnings + salesEarnings + parentEarnings + overheadEarnings\n */\n totalAmount: number = 0;\n\n /**\n * Currency code\n * Defaults to CAD\n */\n currency: string = 'CAD';\n\n /**\n * Invoice ID when payout is processed (FK to smrt-commerce Invoice)\n * Partner is treated as a Vendor for payout invoices\n */\n @crossPackageRef('@happyvertical/smrt-commerce:Invoice')\n invoiceId: string = '';\n\n /**\n * Payout status\n */\n status: PayoutStatus = PayoutStatus.PENDING;\n\n /**\n * Payment reference (check number, transfer ID, etc.)\n */\n paymentReference: string = '';\n\n /**\n * Date payment was processed\n */\n paidAt: Date | null = null;\n\n /**\n * Notes from admin (approval notes, issues, etc.)\n */\n notes: string = '';\n\n /**\n * Additional metadata as JSON string\n */\n metadata: string = '';\n\n constructor(options: any = {}) {\n super(options);\n if (options.partnerId !== undefined) this.partnerId = options.partnerId;\n if (options.periodStart !== undefined)\n this.periodStart = options.periodStart;\n if (options.periodEnd !== undefined) this.periodEnd = options.periodEnd;\n if (options.displayEarnings !== undefined)\n this.displayEarnings = options.displayEarnings;\n if (options.referralEarnings !== undefined)\n this.referralEarnings = options.referralEarnings;\n if (options.salesEarnings !== undefined)\n this.salesEarnings = options.salesEarnings;\n if (options.parentEarnings !== undefined)\n this.parentEarnings = options.parentEarnings;\n if (options.overheadEarnings !== undefined)\n this.overheadEarnings = options.overheadEarnings;\n if (options.totalAmount !== undefined)\n this.totalAmount = options.totalAmount;\n if (options.currency !== undefined) this.currency = options.currency;\n if (options.invoiceId !== undefined) this.invoiceId = options.invoiceId;\n if (options.status !== undefined) this.status = options.status;\n if (options.paymentReference !== undefined)\n this.paymentReference = options.paymentReference;\n if (options.paidAt !== undefined) this.paidAt = options.paidAt;\n if (options.notes !== undefined) this.notes = options.notes;\n if (options.metadata !== undefined) this.metadata = options.metadata;\n }\n\n /**\n * Check if payout is pending approval\n */\n isPending(): boolean {\n return this.status === PayoutStatus.PENDING;\n }\n\n /**\n * Check if payout is approved (waiting for processing)\n */\n isApproved(): boolean {\n return this.status === PayoutStatus.APPROVED;\n }\n\n /**\n * Check if payout is being processed\n */\n isProcessing(): boolean {\n return this.status === PayoutStatus.PROCESSING;\n }\n\n /**\n * Check if payout is completed\n */\n isCompleted(): boolean {\n return this.status === PayoutStatus.COMPLETED;\n }\n\n /**\n * Check if payout failed\n */\n isFailed(): boolean {\n return this.status === PayoutStatus.FAILED;\n }\n\n /**\n * Get total amount in dollars (for display)\n */\n getTotalInDollars(): number {\n return this.totalAmount / 100;\n }\n\n /**\n * Get display earnings in dollars\n */\n getDisplayEarningsInDollars(): number {\n return this.displayEarnings / 100;\n }\n\n /**\n * Get referral earnings in dollars\n */\n getReferralEarningsInDollars(): number {\n return this.referralEarnings / 100;\n }\n\n /**\n * Get sales earnings in dollars\n */\n getSalesEarningsInDollars(): number {\n return this.salesEarnings / 100;\n }\n\n /**\n * Get parent earnings in dollars\n */\n getParentEarningsInDollars(): number {\n return this.parentEarnings / 100;\n }\n\n /**\n * Get overhead earnings in dollars\n */\n getOverheadEarningsInDollars(): number {\n return this.overheadEarnings / 100;\n }\n\n /**\n * Calculate total from component earnings\n */\n calculateTotal(): number {\n return (\n this.displayEarnings +\n this.referralEarnings +\n this.salesEarnings +\n this.parentEarnings +\n this.overheadEarnings\n );\n }\n\n /**\n * Get period as human-readable string\n */\n getPeriodString(): string {\n const start = this.periodStart.toISOString().split('T')[0];\n const end = this.periodEnd.toISOString().split('T')[0];\n return `${start} to ${end}`;\n }\n\n /**\n * Get metadata as object\n */\n getMetadata(): Record<string, any> {\n if (!this.metadata) return {};\n try {\n return JSON.parse(this.metadata);\n } catch {\n return {};\n }\n }\n\n /**\n * Set metadata from object\n */\n setMetadata(data: Record<string, any>): void {\n this.metadata = JSON.stringify(data);\n }\n\n // ============================================================================\n // Status Transitions\n // ============================================================================\n\n /**\n * Approve the payout for processing\n *\n * @throws Error if payout is not in pending status\n */\n approve(): void {\n if (this.status !== PayoutStatus.PENDING) {\n throw new Error(\n `Cannot approve payout with status '${this.status}'. Only pending payouts can be approved.`,\n );\n }\n this.status = PayoutStatus.APPROVED;\n }\n\n /**\n * Mark payout as processing (payment in progress)\n *\n * @throws Error if payout is not in approved status\n */\n markProcessing(): void {\n if (this.status !== PayoutStatus.APPROVED) {\n throw new Error(\n `Cannot mark payout as processing with status '${this.status}'. Only approved payouts can be processed.`,\n );\n }\n this.status = PayoutStatus.PROCESSING;\n }\n\n /**\n * Mark payout as completed\n *\n * @param paymentReference - Payment reference (check number, transfer ID, etc.)\n * @throws Error if payout is not in processing status\n */\n complete(paymentReference: string): void {\n if (this.status !== PayoutStatus.PROCESSING) {\n throw new Error(\n `Cannot complete payout with status '${this.status}'. Only processing payouts can be completed.`,\n );\n }\n this.status = PayoutStatus.COMPLETED;\n this.paymentReference = paymentReference;\n this.paidAt = new Date();\n }\n\n /**\n * Mark payout as failed\n *\n * @param reason - Reason for failure (stored in notes)\n */\n fail(reason: string): void {\n if (\n this.status !== PayoutStatus.APPROVED &&\n this.status !== PayoutStatus.PROCESSING\n ) {\n throw new Error(\n `Cannot fail payout with status '${this.status}'. Only approved or processing payouts can fail.`,\n );\n }\n this.status = PayoutStatus.FAILED;\n this.notes = reason;\n }\n}\n\nexport default Payout;\n","/**\n * PayoutCollection - Collection manager for Payout objects\n * @packageDocumentation\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { Payout } from '../models/Payout.js';\nimport { PayoutStatus } from '../types/index.js';\n\nexport class PayoutCollection extends SmrtCollection<Payout> {\n static readonly _itemClass = Payout;\n\n /**\n * Find payouts by partner\n *\n * @param partnerId - Partner ID\n * @returns Array of payouts\n */\n async findByPartner(partnerId: string): Promise<Payout[]> {\n return await this.list({\n where: { partnerId },\n orderBy: 'period_end DESC',\n });\n }\n\n /**\n * Find payouts by status\n *\n * @param status - Payout status\n * @returns Array of payouts\n */\n async findByStatus(status: PayoutStatus): Promise<Payout[]> {\n return await this.list({\n where: { status },\n orderBy: 'period_end DESC',\n });\n }\n\n /**\n * Find all pending payouts (awaiting approval)\n */\n async findPending(): Promise<Payout[]> {\n return await this.findByStatus(PayoutStatus.PENDING);\n }\n\n /**\n * Find all approved payouts (ready for processing)\n */\n async findApproved(): Promise<Payout[]> {\n return await this.findByStatus(PayoutStatus.APPROVED);\n }\n\n /**\n * Find all processing payouts\n */\n async findProcessing(): Promise<Payout[]> {\n return await this.findByStatus(PayoutStatus.PROCESSING);\n }\n\n /**\n * Find all completed payouts\n */\n async findCompleted(): Promise<Payout[]> {\n return await this.findByStatus(PayoutStatus.COMPLETED);\n }\n\n /**\n * Find all failed payouts\n */\n async findFailed(): Promise<Payout[]> {\n return await this.findByStatus(PayoutStatus.FAILED);\n }\n\n /**\n * Find payouts by invoice\n *\n * @param invoiceId - Invoice ID\n * @returns Array of payouts\n */\n async findByInvoice(invoiceId: string): Promise<Payout[]> {\n return await this.list({\n where: { invoiceId },\n orderBy: 'period_end DESC',\n });\n }\n\n /**\n * Find payouts in period range\n *\n * @param start - Period start date\n * @param end - Period end date\n * @returns Array of payouts\n */\n async findByPeriod(start: Date, end: Date): Promise<Payout[]> {\n return await this.list({\n where: {\n 'period_start >=': start.toISOString(),\n 'period_end <=': end.toISOString(),\n },\n orderBy: 'period_end DESC',\n });\n }\n\n /**\n * Find payouts for a partner by status\n *\n * @param partnerId - Partner ID\n * @param status - Payout status\n * @returns Array of payouts\n */\n async findByPartnerAndStatus(\n partnerId: string,\n status: PayoutStatus,\n ): Promise<Payout[]> {\n return await this.list({\n where: { partnerId, status },\n orderBy: 'period_end DESC',\n });\n }\n\n /**\n * Find pending payouts for a partner\n *\n * @param partnerId - Partner ID\n * @returns Array of pending payouts\n */\n async findPendingByPartner(partnerId: string): Promise<Payout[]> {\n return await this.findByPartnerAndStatus(partnerId, PayoutStatus.PENDING);\n }\n\n /**\n * Find completed payouts for a partner\n *\n * @param partnerId - Partner ID\n * @returns Array of completed payouts\n */\n async findCompletedByPartner(partnerId: string): Promise<Payout[]> {\n return await this.findByPartnerAndStatus(partnerId, PayoutStatus.COMPLETED);\n }\n\n /**\n * Sum total paid to a partner\n *\n * @param partnerId - Partner ID\n * @returns Total paid in cents\n */\n async sumPaidByPartner(partnerId: string): Promise<number> {\n const completed = await this.findCompletedByPartner(partnerId);\n return completed.reduce((sum, p) => sum + p.totalAmount, 0);\n }\n\n /**\n * Sum total pending for a partner\n *\n * @param partnerId - Partner ID\n * @returns Total pending in cents\n */\n async sumPendingByPartner(partnerId: string): Promise<number> {\n const pending = await this.findPendingByPartner(partnerId);\n return pending.reduce((sum, p) => sum + p.totalAmount, 0);\n }\n\n /**\n * Get most recent payout for a partner\n *\n * @param partnerId - Partner ID\n * @returns Most recent payout or null\n */\n async findLatestByPartner(partnerId: string): Promise<Payout | null> {\n const results = await this.list({\n where: { partnerId },\n orderBy: 'period_end DESC',\n limit: 1,\n });\n return results[0] || null;\n }\n\n /**\n * Get payout statistics\n *\n * @returns Stats object\n */\n async getStats(): Promise<{\n pending: number;\n approved: number;\n processing: number;\n completed: number;\n failed: number;\n totalPaid: number;\n totalPending: number;\n }> {\n const all = await this.list({});\n\n const stats = {\n pending: 0,\n approved: 0,\n processing: 0,\n completed: 0,\n failed: 0,\n totalPaid: 0,\n totalPending: 0,\n };\n\n for (const p of all) {\n switch (p.status) {\n case PayoutStatus.PENDING:\n stats.pending++;\n stats.totalPending += p.totalAmount;\n break;\n case PayoutStatus.APPROVED:\n stats.approved++;\n stats.totalPending += p.totalAmount;\n break;\n case PayoutStatus.PROCESSING:\n stats.processing++;\n break;\n case PayoutStatus.COMPLETED:\n stats.completed++;\n stats.totalPaid += p.totalAmount;\n break;\n case PayoutStatus.FAILED:\n stats.failed++;\n break;\n }\n }\n\n return stats;\n }\n}\n"],"names":["PartnerType","PartnerStatus","CommissionType","CommissionStatus","PayoutStatus","PayoutMethod","__decorateClass"],"mappings":";AAsBA,eAAe;AAAA,EACb,IAAA,IAAA,mBAAA,YAAA,GAAA;AACF;ACjBO,IAAK,gCAAAA,iBAAL;AACLA,eAAA,WAAA,IAAY;AACZA,eAAA,aAAA,IAAc;AACdA,eAAA,UAAA,IAAW;AAHD,SAAAA;AAAA,GAAA,eAAA,CAAA,CAAA;AASL,IAAK,kCAAAC,mBAAL;AACLA,iBAAA,SAAA,IAAU;AACVA,iBAAA,QAAA,IAAS;AACTA,iBAAA,WAAA,IAAY;AAHF,SAAAA;AAAA,GAAA,iBAAA,CAAA,CAAA;AASL,IAAK,mCAAAC,oBAAL;AACLA,kBAAA,SAAA,IAAU;AACVA,kBAAA,UAAA,IAAW;AACXA,kBAAA,OAAA,IAAQ;AACRA,kBAAA,QAAA,IAAS;AACTA,kBAAA,UAAA,IAAW;AALD,SAAAA;AAAA,GAAA,kBAAA,CAAA,CAAA;AAWL,IAAK,qCAAAC,sBAAL;AACLA,oBAAA,SAAA,IAAU;AACVA,oBAAA,UAAA,IAAW;AACXA,oBAAA,MAAA,IAAO;AAHG,SAAAA;AAAA,GAAA,oBAAA,CAAA,CAAA;AASL,IAAK,iCAAAC,kBAAL;AACLA,gBAAA,SAAA,IAAU;AACVA,gBAAA,UAAA,IAAW;AACXA,gBAAA,YAAA,IAAa;AACbA,gBAAA,WAAA,IAAY;AACZA,gBAAA,QAAA,IAAS;AALC,SAAAA;AAAA,GAAA,gBAAA,CAAA,CAAA;AAWL,IAAK,iCAAAC,kBAAL;AACLA,gBAAA,eAAA,IAAgB;AAChBA,gBAAA,OAAA,IAAQ;AACRA,gBAAA,QAAA,IAAS;AACTA,gBAAA,QAAA,IAAS;AAJC,SAAAA;AAAA,GAAA,gBAAA,CAAA,CAAA;;;;;;;;;;;ACHL,IAAM,aAAN,cAAyB,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAazC,OAAO,gBAAgB,cAAsB,MAAsB;AACjE,WAAO,KAAK,MAAM,eAAe,IAAI;AAAA,EACvC;AAAA,EAKA,UAAkB;AAAA,EAMlB,YAAoB;AAAA;AAAA;AAAA;AAAA,EAKpB,iBAAiC,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA,EAMhD,eAAuB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMvB,iBAAyB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMzB,mBAA2B;AAAA;AAAA;AAAA;AAAA;AAAA,EAM3B,WAAmB;AAAA,EAMnB,WAAmB;AAAA;AAAA;AAAA;AAAA,EAKnB,SAA2B,iBAAiB;AAAA;AAAA;AAAA;AAAA,EAK5C,qCAA2B,KAAA;AAAA;AAAA;AAAA;AAAA,EAK3B,YAAoB;AAAA;AAAA;AAAA;AAAA,EAKpB,SAAiB;AAAA;AAAA;AAAA;AAAA,EAKjB,aAAqB;AAAA;AAAA;AAAA;AAAA,EAKrB,WAAmB;AAAA,EAEnB,YAAY,UAAe,IAAI;AAC7B,UAAM,OAAO;AACb,QAAI,QAAQ,YAAY,OAAW,MAAK,UAAU,QAAQ;AAC1D,QAAI,QAAQ,cAAc,OAAW,MAAK,YAAY,QAAQ;AAC9D,QAAI,QAAQ,mBAAmB;AAC7B,WAAK,iBAAiB,QAAQ;AAChC,QAAI,QAAQ,iBAAiB;AAC3B,WAAK,eAAe,QAAQ;AAC9B,QAAI,QAAQ,mBAAmB;AAC7B,WAAK,iBAAiB,QAAQ;AAChC,QAAI,QAAQ,qBAAqB;AAC/B,WAAK,mBAAmB,QAAQ;AAClC,QAAI,QAAQ,aAAa,OAAW,MAAK,WAAW,QAAQ;AAC5D,QAAI,QAAQ,aAAa,OAAW,MAAK,WAAW,QAAQ;AAC5D,QAAI,QAAQ,WAAW,OAAW,MAAK,SAAS,QAAQ;AACxD,QAAI,QAAQ,mBAAmB;AAC7B,WAAK,iBAAiB,QAAQ;AAChC,QAAI,QAAQ,cAAc,OAAW,MAAK,YAAY,QAAQ;AAC9D,QAAI,QAAQ,WAAW,OAAW,MAAK,SAAS,QAAQ;AACxD,QAAI,QAAQ,eAAe,OAAW,MAAK,aAAa,QAAQ;AAChE,QAAI,QAAQ,aAAa,OAAW,MAAK,WAAW,QAAQ;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA,EAKA,YAAqB;AACnB,WAAO,KAAK,WAAW,iBAAiB;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,aAAsB;AACpB,WAAO,KAAK,WAAW,iBAAiB;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,SAAkB;AAChB,WAAO,KAAK,WAAW,iBAAiB;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,YAAqB;AACnB,WAAO,KAAK,mBAAmB,eAAe;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,aAAsB;AACpB,WAAO,KAAK,mBAAmB,eAAe;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,UAAmB;AACjB,WAAO,KAAK,mBAAmB,eAAe;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,WAAoB;AAClB,WAAO,KAAK,mBAAmB,eAAe;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,aAAsB;AACpB,WAAO,KAAK,mBAAmB,eAAe;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,qBAA6B;AAC3B,WAAO,KAAK,mBAAmB;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,2BAAmC;AACjC,WAAO,KAAK,eAAe;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,cAAmC;AACjC,QAAI,CAAC,KAAK,SAAU,QAAO,CAAA;AAC3B,QAAI;AACF,aAAO,KAAK,MAAM,KAAK,QAAQ;AAAA,IACjC,QAAQ;AACN,aAAO,CAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,MAAiC;AAC3C,SAAK,WAAW,KAAK,UAAU,IAAI;AAAA,EACrC;AACF;AAxLEC,kBAAA;AAAA,EADC,gBAAgB,iCAAiC;AAAA,GAnBvC,WAoBX,WAAA,WAAA,CAAA;AAMAA,kBAAA;AAAA,EADC,WAAW,SAAS;AAAA,GAzBV,WA0BX,WAAA,aAAA,CAAA;AAmCAA,kBAAA;AAAA,EADC,WAAW,QAAQ;AAAA,GA5DT,WA6DX,WAAA,YAAA,CAAA;AA7DW,aAANA,kBAAA;AAAA,EALN,KAAK;AAAA,IACJ,KAAK,EAAE,SAAS,CAAC,UAAU,QAAQ,KAAK,EAAA;AAAA;AAAA,IACxC,KAAK,EAAE,SAAS,CAAC,UAAU,MAAM,EAAA;AAAA,IACjC,KAAK;AAAA;AAAA,EAAA,CACN;AAAA,GACY,UAAA;AC5CN,MAAM,6BAA6B,eAA2B;AAAA,EACnE,OAAgB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ7B,MAAM,cAAc,WAA0C;AAC5D,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,UAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,YAAY,SAAwC;AACxD,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,QAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aAAa,UAAyC;AAC1D,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,SAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aAAa,QAAiD;AAClE,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,OAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAqC;AACzC,WAAO,MAAM,KAAK,aAAa,iBAAiB,OAAO;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,qBAAqB,WAA0C;AACnE,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,WAAW,QAAQ,iBAAiB,QAAA;AAAA,MAC7C,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,WAAW,gBAAuD;AACtE,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,eAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,gBAAgB,OAAa,KAAkC;AACnE,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO;AAAA,QACL,sBAAsB,MAAM,YAAA;AAAA,QAC5B,sBAAsB,IAAI,YAAA;AAAA,MAAY;AAAA,MAExC,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,0BACJ,WACA,OACA,KACuB;AACvB,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO;AAAA,QACL;AAAA,QACA,sBAAsB,MAAM,YAAA;AAAA,QAC5B,sBAAsB,IAAI,YAAA;AAAA,MAAY;AAAA,MAExC,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,cAAc,WAA0C;AAC5D,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,UAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,qBACJ,WACA,gBACuB;AACvB,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,WAAW,eAAA;AAAA,MACpB,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,qBAAqB,WAA0C;AACnE,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,WAAW,QAAQ,iBAAiB,QAAA;AAAA,MAC7C,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,oBACJ,WACA,UAKI,IAMH;AACD,UAAM,QAAiC,EAAE,UAAA;AACzC,QAAI,QAAQ,OAAQ,OAAM,SAAS,QAAQ;AAC3C,QAAI,QAAQ,eAAgB,OAAM,iBAAiB,QAAQ;AAC3D,QAAI,QAAQ,KAAM,OAAM,oBAAoB,IAAI,QAAQ,KAAK,YAAA;AAC7D,QAAI,QAAQ,GAAI,OAAM,oBAAoB,IAAI,QAAQ,GAAG,YAAA;AAEzD,UAAM,WAAW,MAAM,KAAK,KAAK,EAAE,OAAO;AAE1C,UAAM,SAAiC;AAAA,MACrC,UAAU;AAAA,MACV,SAAS;AAAA,MACT,UAAU;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,IAAA;AAEV,UAAM,SAAiC,CAAA;AACvC,QAAI,QAAQ;AAEZ,eAAW,KAAK,UAAU;AACxB,aAAO,EAAE,cAAc,KACpB,OAAO,EAAE,cAAc,KAAK,KAAK,EAAE;AACtC,UAAI,EAAE,QAAQ;AACZ,eAAO,EAAE,MAAM,KAAK,OAAO,EAAE,MAAM,KAAK,KAAK,EAAE;AAAA,MACjD;AACA,eAAS,EAAE;AAAA,IACb;AAEA,WAAO,EAAE,QAAQ,QAAQ,OAAO,OAAO,SAAS,OAAA;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,2BAA2B,WAc/B;AACA,UAAM,UAAU,MAAM,KAAK,qBAAqB,SAAS;AAGzD,UAAM,cAAc,QAAQ;AAAA,MAC1B,CAAC,MAAM,EAAE,aAAa,EAAE,cAAc;AAAA,IAAA;AAIxC,UAAM,8BAAc,IAAA;AACpB,eAAW,KAAK,aAAa;AAC3B,YAAM,WAAW,QAAQ,IAAI,EAAE,SAAS,KAAK,CAAA;AAC7C,eAAS,KAAK,CAAC;AACf,cAAQ,IAAI,EAAE,WAAW,QAAQ;AAAA,IACnC;AAEA,UAAM,UAYD,CAAA;AACL,eAAW,CAAC,WAAW,KAAK,KAAK,SAAS;AACxC,YAAM,eAAe,MAAM;AAAA,QACzB,CAAC,KAAK,MAAM,MAAM,EAAE;AAAA,QACpB;AAAA,MAAA;AAEF,YAAM,WAAW,MAAM,CAAC,GAAG,YAAY;AAEvC,cAAQ,KAAK;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,QACA,YAAY,MAAM;AAAA,QAClB,SAAS,MAAM,IAAI,CAAC,OAAO;AAAA,UACzB,IAAI,EAAE,MAAM;AAAA,UACZ,gBAAgB,EAAE;AAAA,UAClB,kBAAkB,EAAE;AAAA,UACpB,YAAY,EAAE;AAAA,UACd,QAAQ,EAAE;AAAA,QAAA,EACV;AAAA,MAAA,CACH;AAAA,IACH;AAGA,YAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,eAAe,EAAE,YAAY;AAEtD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,oBAAoB,WAAoC;AAC5D,UAAM,UAAU,MAAM,KAAK,qBAAqB,SAAS;AACzD,WAAO,QAAQ,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,kBAAkB,CAAC;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,oBACJ,WACA,gBACiB;AACjB,UAAM,cAAc,MAAM,KAAK,KAAK;AAAA,MAClC,OAAO,EAAE,WAAW,eAAA;AAAA,IAAe,CACpC;AACD,WAAO,YAAY,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,kBAAkB,CAAC;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,qBAAqB,WAOxB;AACD,UAAM,cAAc,MAAM,KAAK,cAAc,SAAS;AACtD,UAAM,YAAY;AAAA,MAChB,SAAS;AAAA,MACT,UAAU;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,OAAO;AAAA,IAAA;AAGT,eAAW,KAAK,aAAa;AAC3B,UAAI,EAAE,OAAA,KAAY,EAAE,cAAc;AAChC,gBAAQ,EAAE,gBAAA;AAAA,UACR,KAAK,eAAe;AAClB,sBAAU,WAAW,EAAE;AACvB;AAAA,UACF,KAAK,eAAe;AAClB,sBAAU,YAAY,EAAE;AACxB;AAAA,UACF,KAAK,eAAe;AAClB,sBAAU,SAAS,EAAE;AACrB;AAAA,UACF,KAAK,eAAe;AAClB,sBAAU,UAAU,EAAE;AACtB;AAAA,UACF,KAAK,eAAe;AAClB,sBAAU,YAAY,EAAE;AACxB;AAAA,QAAA;AAAA,MAEN;AAAA,IACF;AAEA,cAAU,QACR,UAAU,UACV,UAAU,WACV,UAAU,QACV,UAAU,SACV,UAAU;AACZ,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,oBAAoB,WAOvB;AACD,UAAM,UAAU,MAAM,KAAK,qBAAqB,SAAS;AACzD,UAAM,YAAY;AAAA,MAChB,SAAS;AAAA,MACT,UAAU;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,OAAO;AAAA,IAAA;AAGT,eAAW,KAAK,SAAS;AACvB,cAAQ,EAAE,gBAAA;AAAA,QACR,KAAK,eAAe;AAClB,oBAAU,WAAW,EAAE;AACvB;AAAA,QACF,KAAK,eAAe;AAClB,oBAAU,YAAY,EAAE;AACxB;AAAA,QACF,KAAK,eAAe;AAClB,oBAAU,SAAS,EAAE;AACrB;AAAA,QACF,KAAK,eAAe;AAClB,oBAAU,UAAU,EAAE;AACtB;AAAA,QACF,KAAK,eAAe;AAClB,oBAAU,YAAY,EAAE;AACxB;AAAA,MAAA;AAAA,IAEN;AAEA,cAAU,QACR,UAAU,UACV,UAAU,WACV,UAAU,QACV,UAAU,SACV,UAAU;AACZ,WAAO;AAAA,EACT;AACF;;;;;;;;;;;ACpYO,IAAM,UAAN,cAAsB,WAAW;AAAA,EAKtC,YAAoB;AAAA,EAOpB,aAAqB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMrB,eAAuB;AAAA,EAOvB,kBAA0B;AAAA,EAO1B,eAAuB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMvB,wBAAgC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMhC,wBAAgC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMhC,yBAAiC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMjC,sBAA8B;AAAA;AAAA;AAAA;AAAA;AAAA,EAM9B,kBAA0B;AAAA;AAAA;AAAA;AAAA,EAK1B,eAA6B,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA,EAM1C,WAAmB;AAAA;AAAA;AAAA;AAAA,EAKnB,SAAwB,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA,EAMtC,WAAmB;AAAA,EAEnB,YAAY,UAAe,IAAI;AAC7B,UAAM,OAAO;AACb,QAAI,QAAQ,cAAc,OAAW,MAAK,YAAY,QAAQ;AAC9D,QAAI,QAAQ,eAAe,OAAW,MAAK,aAAa,QAAQ;AAChE,QAAI,QAAQ,iBAAiB;AAC3B,WAAK,eAAe,QAAQ;AAC9B,QAAI,QAAQ,oBAAoB;AAC9B,WAAK,kBAAkB,QAAQ;AACjC,QAAI,QAAQ,iBAAiB;AAC3B,WAAK,eAAe,QAAQ;AAC9B,QAAI,QAAQ,0BAA0B;AACpC,WAAK,wBAAwB,QAAQ;AACvC,QAAI,QAAQ,0BAA0B;AACpC,WAAK,wBAAwB,QAAQ;AACvC,QAAI,QAAQ,2BAA2B;AACrC,WAAK,yBAAyB,QAAQ;AACxC,QAAI,QAAQ,wBAAwB;AAClC,WAAK,sBAAsB,QAAQ;AACrC,QAAI,QAAQ,oBAAoB;AAC9B,WAAK,kBAAkB,QAAQ;AACjC,QAAI,QAAQ,iBAAiB;AAC3B,WAAK,eAAe,QAAQ;AAC9B,QAAI,QAAQ,aAAa,OAAW,MAAK,WAAW,QAAQ;AAC5D,QAAI,QAAQ,WAAW,OAAW,MAAK,SAAS,QAAQ;AACxD,QAAI,QAAQ,aAAa,OAAW,MAAK,WAAW,QAAQ;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAiC;AAC/B,QAAI,CAAC,KAAK,aAAc,QAAO,CAAA;AAC/B,QAAI;AACF,aAAO,KAAK,MAAM,KAAK,YAAY;AAAA,IACrC,QAAQ;AACN,aAAO,CAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,OAA4B;AAC1C,SAAK,eAAe,KAAK,UAAU,KAAK;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,MAA4B;AAClC,WAAO,KAAK,kBAAkB,SAAS,IAAI;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,cAAuB;AACrB,WAAO,KAAK,QAAQ,YAAY,SAAS;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAyB;AACvB,WAAO,KAAK,QAAQ,YAAY,WAAW;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,aAAsB;AACpB,WAAO,KAAK,QAAQ,YAAY,QAAQ;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,WAAoB;AAClB,WAAO,KAAK,WAAW,cAAc;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,YAAqB;AACnB,WAAO,KAAK,WAAW,cAAc;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,cAAuB;AACrB,WAAO,KAAK,WAAW,cAAc;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,YAAqB;AACnB,WAAO,CAAC,CAAC,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,cAAuB;AACrB,WAAO,CAAC,CAAC,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,cAAmC;AACjC,QAAI,CAAC,KAAK,SAAU,QAAO,CAAA;AAC3B,QAAI;AACF,aAAO,KAAK,MAAM,KAAK,QAAQ;AAAA,IACjC,QAAQ;AACN,aAAO,CAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,MAAiC;AAC3C,SAAK,WAAW,KAAK,UAAU,IAAI;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,wBAAgC;AAC9B,QAAI,KAAK,mBAAmB,KAAK,wBAAwB,GAAG;AAC1D,aAAO,KAAK,uBAAuB,IAAI,KAAK;AAAA,IAC9C;AACA,WAAO,KAAK;AAAA,EACd;AACF;AA1NEA,kBAAA;AAAA,EADC,gBAAgB,sCAAsC;AAAA,GAJ5C,QAKX,WAAA,aAAA,CAAA;AAOAA,kBAAA;AAAA,EADC,gBAAgB,yCAAyC;AAAA,GAX/C,QAYX,WAAA,cAAA,CAAA;AAaAA,kBAAA;AAAA,EADC,WAAW,SAAS;AAAA,GAxBV,QAyBX,WAAA,mBAAA,CAAA;AAOAA,kBAAA;AAAA,EADC,WAAW,SAAS;AAAA,GA/BV,QAgCX,WAAA,gBAAA,CAAA;AAhCW,UAANA,kBAAA;AAAA,EALN,KAAK;AAAA,IACJ,KAAK,EAAE,SAAS,CAAC,QAAQ,OAAO,UAAU,QAAQ,EAAA;AAAA,IAClD,KAAK,EAAE,SAAS,CAAC,QAAQ,OAAO,QAAQ,EAAA;AAAA,IACxC,KAAK;AAAA,EAAA,CACN;AAAA,GACY,OAAA;AClDN,MAAM,0BAA0B,eAAwB;AAAA,EAC7D,OAAgB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ7B,MAAM,cAAc,WAAuC;AACzD,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,UAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,eAAe,YAA6C;AAChE,UAAM,UAAU,MAAM,KAAK,KAAK;AAAA,MAC9B,OAAO,EAAE,WAAA;AAAA,MACT,OAAO;AAAA,IAAA,CACR;AACD,WAAO,QAAQ,CAAC,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aAAa,iBAA6C;AAC9D,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,gBAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,eAAe,cAA0C;AAC7D,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,aAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aAAa,QAA2C;AAC5D,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,OAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAiC;AACrC,WAAO,MAAM,KAAK,aAAa,cAAc,MAAM;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAkC;AACtC,WAAO,MAAM,KAAK,aAAa,cAAc,OAAO;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAoC;AACxC,WAAO,MAAM,KAAK,aAAa,cAAc,SAAS;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,WAAW,MAAuC;AACtD,UAAM,MAAM,MAAM,KAAK,KAAK,CAAA,CAAE;AAC9B,WAAO,IAAI,OAAO,CAAC,YAAY,QAAQ,QAAQ,IAAI,CAAC;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAqC;AACzC,WAAO,MAAM,KAAK,WAAW,YAAY,SAAS;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBAAsC;AAC1C,WAAO,MAAM,KAAK,WAAW,YAAY,WAAW;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAoC;AACxC,WAAO,MAAM,KAAK,WAAW,YAAY,QAAQ;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,uBAA2C;AAC/C,UAAM,aAAa,MAAM,KAAK,eAAA;AAC9B,WAAO,WAAW,OAAO,CAAC,MAAM,EAAE,UAAU;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,qBAAqB,YAA6C;AACtE,UAAM,UAAU,MAAM,KAAK,eAAe,UAAU;AACpD,QAAI,SAAS,SAAA,KAAc,QAAQ,eAAe;AAChD,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,wBAA4C;AAChD,UAAM,SAAS,MAAM,KAAK,WAAA;AAG1B,WAAO;AAAA,EACT;AACF;;;;;;;;;;;ACnHO,IAAM,SAAN,cAAqB,WAAW;AAAA,EAKrC,YAAoB;AAAA;AAAA;AAAA;AAAA,EAKpB,kCAAwB,KAAA;AAAA;AAAA;AAAA;AAAA,EAKxB,gCAAsB,KAAA;AAAA;AAAA;AAAA;AAAA,EAKtB,kBAA0B;AAAA;AAAA;AAAA;AAAA,EAK1B,mBAA2B;AAAA;AAAA;AAAA;AAAA,EAK3B,gBAAwB;AAAA;AAAA;AAAA;AAAA,EAKxB,iBAAyB;AAAA;AAAA;AAAA;AAAA,EAKzB,mBAA2B;AAAA;AAAA;AAAA;AAAA;AAAA,EAM3B,cAAsB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMtB,WAAmB;AAAA,EAOnB,YAAoB;AAAA;AAAA;AAAA;AAAA,EAKpB,SAAuB,aAAa;AAAA;AAAA;AAAA;AAAA,EAKpC,mBAA2B;AAAA;AAAA;AAAA;AAAA,EAK3B,SAAsB;AAAA;AAAA;AAAA;AAAA,EAKtB,QAAgB;AAAA;AAAA;AAAA;AAAA,EAKhB,WAAmB;AAAA,EAEnB,YAAY,UAAe,IAAI;AAC7B,UAAM,OAAO;AACb,QAAI,QAAQ,cAAc,OAAW,MAAK,YAAY,QAAQ;AAC9D,QAAI,QAAQ,gBAAgB;AAC1B,WAAK,cAAc,QAAQ;AAC7B,QAAI,QAAQ,cAAc,OAAW,MAAK,YAAY,QAAQ;AAC9D,QAAI,QAAQ,oBAAoB;AAC9B,WAAK,kBAAkB,QAAQ;AACjC,QAAI,QAAQ,qBAAqB;AAC/B,WAAK,mBAAmB,QAAQ;AAClC,QAAI,QAAQ,kBAAkB;AAC5B,WAAK,gBAAgB,QAAQ;AAC/B,QAAI,QAAQ,mBAAmB;AAC7B,WAAK,iBAAiB,QAAQ;AAChC,QAAI,QAAQ,qBAAqB;AAC/B,WAAK,mBAAmB,QAAQ;AAClC,QAAI,QAAQ,gBAAgB;AAC1B,WAAK,cAAc,QAAQ;AAC7B,QAAI,QAAQ,aAAa,OAAW,MAAK,WAAW,QAAQ;AAC5D,QAAI,QAAQ,cAAc,OAAW,MAAK,YAAY,QAAQ;AAC9D,QAAI,QAAQ,WAAW,OAAW,MAAK,SAAS,QAAQ;AACxD,QAAI,QAAQ,qBAAqB;AAC/B,WAAK,mBAAmB,QAAQ;AAClC,QAAI,QAAQ,WAAW,OAAW,MAAK,SAAS,QAAQ;AACxD,QAAI,QAAQ,UAAU,OAAW,MAAK,QAAQ,QAAQ;AACtD,QAAI,QAAQ,aAAa,OAAW,MAAK,WAAW,QAAQ;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA,EAKA,YAAqB;AACnB,WAAO,KAAK,WAAW,aAAa;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,aAAsB;AACpB,WAAO,KAAK,WAAW,aAAa;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,eAAwB;AACtB,WAAO,KAAK,WAAW,aAAa;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,cAAuB;AACrB,WAAO,KAAK,WAAW,aAAa;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,WAAoB;AAClB,WAAO,KAAK,WAAW,aAAa;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,oBAA4B;AAC1B,WAAO,KAAK,cAAc;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,8BAAsC;AACpC,WAAO,KAAK,kBAAkB;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,+BAAuC;AACrC,WAAO,KAAK,mBAAmB;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,4BAAoC;AAClC,WAAO,KAAK,gBAAgB;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,6BAAqC;AACnC,WAAO,KAAK,iBAAiB;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,+BAAuC;AACrC,WAAO,KAAK,mBAAmB;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAyB;AACvB,WACE,KAAK,kBACL,KAAK,mBACL,KAAK,gBACL,KAAK,iBACL,KAAK;AAAA,EAET;AAAA;AAAA;AAAA;AAAA,EAKA,kBAA0B;AACxB,UAAM,QAAQ,KAAK,YAAY,YAAA,EAAc,MAAM,GAAG,EAAE,CAAC;AACzD,UAAM,MAAM,KAAK,UAAU,YAAA,EAAc,MAAM,GAAG,EAAE,CAAC;AACrD,WAAO,GAAG,KAAK,OAAO,GAAG;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,cAAmC;AACjC,QAAI,CAAC,KAAK,SAAU,QAAO,CAAA;AAC3B,QAAI;AACF,aAAO,KAAK,MAAM,KAAK,QAAQ;AAAA,IACjC,QAAQ;AACN,aAAO,CAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,MAAiC;AAC3C,SAAK,WAAW,KAAK,UAAU,IAAI;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,UAAgB;AACd,QAAI,KAAK,WAAW,aAAa,SAAS;AACxC,YAAM,IAAI;AAAA,QACR,sCAAsC,KAAK,MAAM;AAAA,MAAA;AAAA,IAErD;AACA,SAAK,SAAS,aAAa;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAuB;AACrB,QAAI,KAAK,WAAW,aAAa,UAAU;AACzC,YAAM,IAAI;AAAA,QACR,iDAAiD,KAAK,MAAM;AAAA,MAAA;AAAA,IAEhE;AACA,SAAK,SAAS,aAAa;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,SAAS,kBAAgC;AACvC,QAAI,KAAK,WAAW,aAAa,YAAY;AAC3C,YAAM,IAAI;AAAA,QACR,uCAAuC,KAAK,MAAM;AAAA,MAAA;AAAA,IAEtD;AACA,SAAK,SAAS,aAAa;AAC3B,SAAK,mBAAmB;AACxB,SAAK,6BAAa,KAAA;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,KAAK,QAAsB;AACzB,QACE,KAAK,WAAW,aAAa,YAC7B,KAAK,WAAW,aAAa,YAC7B;AACA,YAAM,IAAI;AAAA,QACR,mCAAmC,KAAK,MAAM;AAAA,MAAA;AAAA,IAElD;AACA,SAAK,SAAS,aAAa;AAC3B,SAAK,QAAQ;AAAA,EACf;AACF;AArSE,gBAAA;AAAA,EADC,WAAW,SAAS;AAAA,GAJV,OAKX,WAAA,aAAA,CAAA;AAsDA,gBAAA;AAAA,EADC,gBAAgB,sCAAsC;AAAA,GA1D5C,OA2DX,WAAA,aAAA,CAAA;AA3DW,SAAN,gBAAA;AAAA,EALN,KAAK;AAAA,IACJ,KAAK,EAAE,SAAS,CAAC,QAAQ,OAAO,UAAU,QAAQ,EAAA;AAAA,IAClD,KAAK,EAAE,SAAS,CAAC,QAAQ,OAAO,QAAQ,EAAA;AAAA,IACxC,KAAK;AAAA,EAAA,CACN;AAAA,GACY,MAAA;ACzCN,MAAM,yBAAyB,eAAuB;AAAA,EAC3D,OAAgB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ7B,MAAM,cAAc,WAAsC;AACxD,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,UAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aAAa,QAAyC;AAC1D,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,OAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAiC;AACrC,WAAO,MAAM,KAAK,aAAa,aAAa,OAAO;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAkC;AACtC,WAAO,MAAM,KAAK,aAAa,aAAa,QAAQ;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAoC;AACxC,WAAO,MAAM,KAAK,aAAa,aAAa,UAAU;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAmC;AACvC,WAAO,MAAM,KAAK,aAAa,aAAa,SAAS;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAgC;AACpC,WAAO,MAAM,KAAK,aAAa,aAAa,MAAM;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,cAAc,WAAsC;AACxD,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,UAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,aAAa,OAAa,KAA8B;AAC5D,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO;AAAA,QACL,mBAAmB,MAAM,YAAA;AAAA,QACzB,iBAAiB,IAAI,YAAA;AAAA,MAAY;AAAA,MAEnC,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,uBACJ,WACA,QACmB;AACnB,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,WAAW,OAAA;AAAA,MACpB,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,qBAAqB,WAAsC;AAC/D,WAAO,MAAM,KAAK,uBAAuB,WAAW,aAAa,OAAO;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,uBAAuB,WAAsC;AACjE,WAAO,MAAM,KAAK,uBAAuB,WAAW,aAAa,SAAS;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,iBAAiB,WAAoC;AACzD,UAAM,YAAY,MAAM,KAAK,uBAAuB,SAAS;AAC7D,WAAO,UAAU,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,aAAa,CAAC;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,oBAAoB,WAAoC;AAC5D,UAAM,UAAU,MAAM,KAAK,qBAAqB,SAAS;AACzD,WAAO,QAAQ,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,aAAa,CAAC;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,oBAAoB,WAA2C;AACnE,UAAM,UAAU,MAAM,KAAK,KAAK;AAAA,MAC9B,OAAO,EAAE,UAAA;AAAA,MACT,SAAS;AAAA,MACT,OAAO;AAAA,IAAA,CACR;AACD,WAAO,QAAQ,CAAC,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,WAQH;AACD,UAAM,MAAM,MAAM,KAAK,KAAK,CAAA,CAAE;AAE9B,UAAM,QAAQ;AAAA,MACZ,SAAS;AAAA,MACT,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,cAAc;AAAA,IAAA;AAGhB,eAAW,KAAK,KAAK;AACnB,cAAQ,EAAE,QAAA;AAAA,QACR,KAAK,aAAa;AAChB,gBAAM;AACN,gBAAM,gBAAgB,EAAE;AACxB;AAAA,QACF,KAAK,aAAa;AAChB,gBAAM;AACN,gBAAM,gBAAgB,EAAE;AACxB;AAAA,QACF,KAAK,aAAa;AAChB,gBAAM;AACN;AAAA,QACF,KAAK,aAAa;AAChB,gBAAM;AACN,gBAAM,aAAa,EAAE;AACrB;AAAA,QACF,KAAK,aAAa;AAChB,gBAAM;AACN;AAAA,MAAA;AAAA,IAEN;AAEA,WAAO;AAAA,EACT;AACF;"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/__smrt-register__.ts","../src/types/index.ts","../src/models/Commission.ts","../src/collections/CommissionCollection.ts","../src/models/Partner.ts","../src/collections/PartnerCollection.ts","../src/models/Payout.ts","../src/collections/PayoutCollection.ts"],"sourcesContent":["/**\n * Self-registers this package's build-time manifest before any @smrt() decorator\n * in the package fires. Fixes issue #1132: in consumer runtimes (tsx, SvelteKit\n * SSR, plain `vite dev`) the decorator's synchronous manifest lookup previously\n * missed because no step populated the global manifest cache — classes got\n * registered with zero fields and `save()` / `toJSON()` silently dropped every\n * declared property.\n *\n * Import this module as the first statement in `src/index.ts` so its top-level\n * side effect runs ahead of any class module's @smrt() decorator.\n *\n * Silent no-op in dev/test, where the vitest plugin already populates manifests\n * via a different path. Only needs to succeed in the published dist output.\n *\n * @see https://github.com/happyvertical/smrt/issues/1132\n */\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\n// `new URL('./manifest.json', import.meta.url)` resolves at runtime to the\n// manifest sitting next to this module's compiled output. Vite warns at build\n// time that it cannot pre-resolve the URL; that is the intended behavior —\n// the URL must resolve to dist/manifest.json at runtime, not be inlined.\nObjectRegistry.registerPackageManifest(\n new URL('./manifest.json', import.meta.url),\n);\n","/**\n * Types and enums for smrt-affiliates package\n */\n\n/**\n * Partner types - what role(s) this partner plays\n */\nexport enum PartnerType {\n PUBLISHER = 'publisher',\n SALESPERSON = 'salesperson',\n REFERRER = 'referrer',\n}\n\n/**\n * Partner status\n */\nexport enum PartnerStatus {\n PENDING = 'pending',\n ACTIVE = 'active',\n SUSPENDED = 'suspended',\n}\n\n/**\n * Commission types - how earnings were generated\n */\nexport enum CommissionType {\n DISPLAY = 'display',\n REFERRAL = 'referral',\n SALES = 'sales',\n PARENT = 'parent',\n OVERHEAD = 'overhead',\n}\n\n/**\n * Commission status - lifecycle of a commission\n */\nexport enum CommissionStatus {\n PENDING = 'pending',\n INCLUDED = 'included',\n PAID = 'paid',\n}\n\n/**\n * Payout status - lifecycle of a payout batch\n */\nexport enum PayoutStatus {\n PENDING = 'pending',\n APPROVED = 'approved',\n PROCESSING = 'processing',\n COMPLETED = 'completed',\n FAILED = 'failed',\n}\n\n/**\n * Payout method - how payment is delivered\n */\nexport enum PayoutMethod {\n BANK_TRANSFER = 'bank_transfer',\n CHECK = 'check',\n PAYPAL = 'paypal',\n CREDIT = 'credit',\n}\n","/**\n * Commission model - Revenue attribution per ad event\n * @packageDocumentation\n */\n\nimport {\n crossPackageRef,\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { CommissionStatus, CommissionType } from '../types/index.js';\n\n/**\n * Options for constructing a {@link Commission}.\n */\nexport interface CommissionOptions extends SmrtObjectOptions {\n eventId?: string;\n partnerId?: string;\n commissionType?: CommissionType;\n grossRevenue?: number;\n commissionRate?: number;\n commissionAmount?: number;\n currency?: string;\n payoutId?: string;\n status?: CommissionStatus;\n eventTimestamp?: Date;\n networkId?: string;\n siteId?: string;\n campaignId?: string;\n metadata?: string;\n}\n\n/**\n * Commission tracks revenue attribution from ad events to partners.\n *\n * Each ad event can generate multiple commissions:\n * - Display commission to publisher (site owner)\n * - Referral commission to referrer (who brought in the publisher)\n * - Sales commission to salesperson (who brought in the advertiser)\n * - Parent commission to salesperson's parent publisher\n *\n * References:\n * - eventId: String reference to smrt-ads AdEvent (cross-package)\n * - partnerId: FK to Partner (within package)\n * - payoutId: FK to Payout (within package)\n *\n * @example\n * ```typescript\n * // Create display commission for a publisher\n * const commission = await commissions.create({\n * eventId: 'adevent-uuid',\n * partnerId: publisher.id,\n * commissionType: CommissionType.DISPLAY,\n * grossRevenue: 100, // 1 cent = $0.01\n * commissionRate: 0.50,\n * commissionAmount: 50, // 0.5 cents\n * currency: 'CAD',\n * status: CommissionStatus.PENDING\n * });\n * ```\n */\n// Intentional exception to standards.md §7 (`@TenantScoped`):\n// `Commission` is deliberately NOT tenant-scoped. The affiliate network\n// attributes revenue to a `Partner` across whichever tenant generated the\n// underlying ad event; cross-tenant attribution is the point of the network.\n// Tenant-attributed reporting should aggregate by joining back through\n// `eventId` (smrt-ads). See `packages/affiliates/CLAUDE.md` \"Tenancy\" section.\n@smrt({\n api: { include: ['create', 'list', 'get'] }, // No delete (audit trail)\n mcp: { include: ['create', 'list'] },\n cli: false, // High volume, not useful in CLI\n})\nexport class Commission extends SmrtObject {\n /**\n * Calculate commission amount from gross revenue and rate\n *\n * @param grossRevenue - Gross revenue in cents\n * @param rate - Commission rate (0-1)\n * @returns Commission amount in cents (rounded)\n *\n * @example\n * ```typescript\n * const amount = Commission.calculateAmount(1000, 0.50); // 500 cents\n * ```\n */\n static calculateAmount(grossRevenue: number, rate: number): number {\n return Math.round(grossRevenue * rate);\n }\n /**\n * Ad Event ID (FK to smrt-ads AdEvent, cross-package)\n */\n @crossPackageRef('@happyvertical/smrt-ads:AdEvent')\n eventId: string = '';\n\n /**\n * Partner ID (FK to Partner)\n */\n @foreignKey('Partner')\n partnerId: string = '';\n\n /**\n * Commission type (display, referral, sales, parent)\n */\n commissionType: CommissionType = CommissionType.DISPLAY;\n\n /**\n * Gross revenue from the event in cents\n * This is the total ad revenue before commission split\n */\n grossRevenue: number = 0;\n\n /**\n * Commission rate applied (0-1)\n * Copied from partner at time of event for audit trail\n */\n commissionRate: number = 0;\n\n /**\n * Calculated commission amount in cents\n * = grossRevenue * commissionRate\n */\n commissionAmount: number = 0;\n\n /**\n * Currency code\n * Defaults to CAD\n */\n currency: string = 'CAD';\n\n /**\n * Payout ID when commission is included in a payout\n */\n @foreignKey('Payout')\n payoutId: string = '';\n\n /**\n * Commission status\n */\n status: CommissionStatus = CommissionStatus.PENDING;\n\n /**\n * Event timestamp (copied from AdEvent for reporting)\n */\n eventTimestamp: Date = new Date();\n\n /**\n * Network ID for aggregate queries (optional context)\n */\n networkId: string = '';\n\n /**\n * Site/Property ID for aggregate queries (optional context)\n */\n siteId: string = '';\n\n /**\n * Campaign ID for aggregate queries (optional context)\n */\n campaignId: string = '';\n\n /**\n * Additional metadata as JSON string\n */\n metadata: string = '';\n\n constructor(options: CommissionOptions = {}) {\n super(options);\n if (options.eventId !== undefined) this.eventId = options.eventId;\n if (options.partnerId !== undefined) this.partnerId = options.partnerId;\n if (options.commissionType !== undefined)\n this.commissionType = options.commissionType;\n if (options.grossRevenue !== undefined)\n this.grossRevenue = options.grossRevenue;\n if (options.commissionRate !== undefined)\n this.commissionRate = options.commissionRate;\n if (options.commissionAmount !== undefined)\n this.commissionAmount = options.commissionAmount;\n if (options.currency !== undefined) this.currency = options.currency;\n if (options.payoutId !== undefined) this.payoutId = options.payoutId;\n if (options.status !== undefined) this.status = options.status;\n if (options.eventTimestamp !== undefined)\n this.eventTimestamp = options.eventTimestamp;\n if (options.networkId !== undefined) this.networkId = options.networkId;\n if (options.siteId !== undefined) this.siteId = options.siteId;\n if (options.campaignId !== undefined) this.campaignId = options.campaignId;\n if (options.metadata !== undefined) this.metadata = options.metadata;\n }\n\n /**\n * Check if commission is pending (not yet in a payout)\n */\n isPending(): boolean {\n return this.status === CommissionStatus.PENDING;\n }\n\n /**\n * Check if commission is included in a payout\n */\n isIncluded(): boolean {\n return this.status === CommissionStatus.INCLUDED;\n }\n\n /**\n * Check if commission has been paid\n */\n isPaid(): boolean {\n return this.status === CommissionStatus.PAID;\n }\n\n /**\n * Check if this is a display commission\n */\n isDisplay(): boolean {\n return this.commissionType === CommissionType.DISPLAY;\n }\n\n /**\n * Check if this is a referral commission\n */\n isReferral(): boolean {\n return this.commissionType === CommissionType.REFERRAL;\n }\n\n /**\n * Check if this is a sales commission\n */\n isSales(): boolean {\n return this.commissionType === CommissionType.SALES;\n }\n\n /**\n * Check if this is a parent commission\n */\n isParent(): boolean {\n return this.commissionType === CommissionType.PARENT;\n }\n\n /**\n * Check if this is an overhead commission\n */\n isOverhead(): boolean {\n return this.commissionType === CommissionType.OVERHEAD;\n }\n\n /**\n * Get commission amount in dollars (for display)\n */\n getAmountInDollars(): number {\n return this.commissionAmount / 100;\n }\n\n /**\n * Get gross revenue in dollars (for display)\n */\n getGrossRevenueInDollars(): number {\n return this.grossRevenue / 100;\n }\n\n /**\n * Get metadata as object\n */\n getMetadata(): Record<string, unknown> {\n if (!this.metadata) return {};\n try {\n return JSON.parse(this.metadata);\n } catch {\n return {};\n }\n }\n\n /**\n * Set metadata from object\n */\n setMetadata(data: Record<string, unknown>): void {\n this.metadata = JSON.stringify(data);\n }\n}\n\nexport default Commission;\n","/**\n * CommissionCollection - Collection manager for Commission objects\n * @packageDocumentation\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { Commission } from '../models/Commission.js';\nimport { CommissionStatus, CommissionType } from '../types/index.js';\n\nexport class CommissionCollection extends SmrtCollection<Commission> {\n static readonly _itemClass = Commission;\n\n /**\n * Find commissions by partner\n *\n * @param partnerId - Partner ID\n * @returns Array of commissions\n */\n async findByPartner(partnerId: string): Promise<Commission[]> {\n return await this.list({\n where: { partnerId },\n orderBy: 'event_timestamp DESC',\n });\n }\n\n /**\n * Find commissions by ad event\n *\n * @param eventId - Ad Event ID\n * @returns Array of commissions\n */\n async findByEvent(eventId: string): Promise<Commission[]> {\n return await this.list({\n where: { eventId },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find commissions by payout\n *\n * @param payoutId - Payout ID\n * @returns Array of commissions\n */\n async findByPayout(payoutId: string): Promise<Commission[]> {\n return await this.list({\n where: { payoutId },\n orderBy: 'event_timestamp DESC',\n });\n }\n\n /**\n * Find commissions by status\n *\n * @param status - Commission status\n * @returns Array of commissions\n */\n async findByStatus(status: CommissionStatus): Promise<Commission[]> {\n return await this.list({\n where: { status },\n orderBy: 'event_timestamp DESC',\n });\n }\n\n /**\n * Find all pending commissions\n */\n async findPending(): Promise<Commission[]> {\n return await this.findByStatus(CommissionStatus.PENDING);\n }\n\n /**\n * Find pending commissions for a partner\n *\n * @param partnerId - Partner ID\n * @returns Array of pending commissions\n */\n async findPendingByPartner(partnerId: string): Promise<Commission[]> {\n return await this.list({\n where: { partnerId, status: CommissionStatus.PENDING },\n orderBy: 'event_timestamp DESC',\n });\n }\n\n /**\n * Find commissions by type\n *\n * @param commissionType - Commission type\n * @returns Array of commissions\n */\n async findByType(commissionType: CommissionType): Promise<Commission[]> {\n return await this.list({\n where: { commissionType },\n orderBy: 'event_timestamp DESC',\n });\n }\n\n /**\n * Find commissions in date range\n *\n * @param start - Start date\n * @param end - End date\n * @returns Array of commissions\n */\n async findByDateRange(start: Date, end: Date): Promise<Commission[]> {\n return await this.list({\n where: {\n 'event_timestamp >=': start.toISOString(),\n 'event_timestamp <=': end.toISOString(),\n },\n orderBy: 'event_timestamp DESC',\n });\n }\n\n /**\n * Find commissions for a partner in date range\n *\n * @param partnerId - Partner ID\n * @param start - Start date\n * @param end - End date\n * @returns Array of commissions\n */\n async findByPartnerAndDateRange(\n partnerId: string,\n start: Date,\n end: Date,\n ): Promise<Commission[]> {\n return await this.list({\n where: {\n partnerId,\n 'event_timestamp >=': start.toISOString(),\n 'event_timestamp <=': end.toISOString(),\n },\n orderBy: 'event_timestamp DESC',\n });\n }\n\n // --- Network-scoped queries ---\n\n /**\n * Find all commissions for a network\n *\n * @param networkId - Network ID\n * @returns Array of commissions\n */\n async findByNetwork(networkId: string): Promise<Commission[]> {\n return await this.list({\n where: { networkId },\n orderBy: 'event_timestamp DESC',\n });\n }\n\n /**\n * Find commissions for a network filtered by type\n *\n * @param networkId - Network ID\n * @param commissionType - Commission type\n * @returns Array of commissions\n */\n async findByNetworkAndType(\n networkId: string,\n commissionType: CommissionType,\n ): Promise<Commission[]> {\n return await this.list({\n where: { networkId, commissionType },\n orderBy: 'event_timestamp DESC',\n });\n }\n\n /**\n * Find pending commissions for a network\n *\n * @param networkId - Network ID\n * @returns Array of pending commissions\n */\n async findPendingByNetwork(networkId: string): Promise<Commission[]> {\n return await this.list({\n where: { networkId, status: CommissionStatus.PENDING },\n orderBy: 'event_timestamp DESC',\n });\n }\n\n /**\n * Get aggregate summary of commissions by type and site for a network.\n *\n * @param networkId - Network ID\n * @param options - Optional filters (siteId, from, to, commissionType)\n * @returns Summary with byType, bySite, total, and count\n */\n async getSummaryByNetwork(\n networkId: string,\n options: {\n siteId?: string;\n from?: Date;\n to?: Date;\n commissionType?: CommissionType;\n } = {},\n ): Promise<{\n byType: Record<string, number>;\n bySite: Record<string, number>;\n total: number;\n count: number;\n }> {\n const where: Record<string, unknown> = { networkId };\n if (options.siteId) where.siteId = options.siteId;\n if (options.commissionType) where.commissionType = options.commissionType;\n if (options.from) where['event_timestamp >='] = options.from.toISOString();\n if (options.to) where['event_timestamp <='] = options.to.toISOString();\n\n const filtered = await this.list({ where });\n\n const byType: Record<string, number> = {\n overhead: 0,\n display: 0,\n referral: 0,\n sales: 0,\n parent: 0,\n };\n const bySite: Record<string, number> = {};\n let total = 0;\n\n for (const c of filtered) {\n byType[c.commissionType] =\n (byType[c.commissionType] ?? 0) + c.commissionAmount;\n if (c.siteId) {\n bySite[c.siteId] = (bySite[c.siteId] ?? 0) + c.commissionAmount;\n }\n total += c.commissionAmount;\n }\n\n return { byType, bySite, total, count: filtered.length };\n }\n\n /**\n * Get pending commissions grouped by partnerId for a network.\n *\n * @param networkId - Network ID\n * @returns Array of payout groups (partnerId, totalPending, currency, entries)\n */\n async getPendingPayoutsByNetwork(networkId: string): Promise<\n Array<{\n partnerId: string;\n totalPending: number;\n currency: string;\n entryCount: number;\n entries: Array<{\n id: string;\n commissionType: string;\n commissionAmount: number;\n campaignId: string;\n siteId: string;\n }>;\n }>\n > {\n const pending = await this.findPendingByNetwork(networkId);\n\n // Filter to entries with a partnerId\n const withPartner = pending.filter(\n (c) => c.partnerId && c.partnerId !== '',\n );\n\n // Group by partnerId\n const grouped = new Map<string, Commission[]>();\n for (const c of withPartner) {\n const existing = grouped.get(c.partnerId) ?? [];\n existing.push(c);\n grouped.set(c.partnerId, existing);\n }\n\n const payouts: Array<{\n partnerId: string;\n totalPending: number;\n currency: string;\n entryCount: number;\n entries: Array<{\n id: string;\n commissionType: string;\n commissionAmount: number;\n campaignId: string;\n siteId: string;\n }>;\n }> = [];\n for (const [partnerId, group] of grouped) {\n const totalPending = group.reduce(\n (sum, c) => sum + c.commissionAmount,\n 0,\n );\n const currency = group[0]?.currency ?? 'CAD';\n\n payouts.push({\n partnerId,\n totalPending,\n currency,\n entryCount: group.length,\n entries: group.map((c) => ({\n id: c.id ?? '',\n commissionType: c.commissionType,\n commissionAmount: c.commissionAmount,\n campaignId: c.campaignId,\n siteId: c.siteId,\n })),\n });\n }\n\n // Sort by total pending descending\n payouts.sort((a, b) => b.totalPending - a.totalPending);\n\n return payouts;\n }\n\n // --- Aggregation queries ---\n\n /**\n * Sum pending commissions for a partner\n *\n * @param partnerId - Partner ID\n * @returns Total pending amount in cents\n */\n async sumPendingByPartner(partnerId: string): Promise<number> {\n const pending = await this.findPendingByPartner(partnerId);\n return pending.reduce((sum, c) => sum + c.commissionAmount, 0);\n }\n\n /**\n * Sum commissions by type for a partner\n *\n * @param partnerId - Partner ID\n * @param commissionType - Commission type\n * @returns Total amount in cents\n */\n async sumByPartnerAndType(\n partnerId: string,\n commissionType: CommissionType,\n ): Promise<number> {\n const commissions = await this.list({\n where: { partnerId, commissionType },\n });\n return commissions.reduce((sum, c) => sum + c.commissionAmount, 0);\n }\n\n /**\n * Get earnings breakdown for a partner\n *\n * @param partnerId - Partner ID\n * @returns Breakdown by commission type\n */\n async getEarningsBreakdown(partnerId: string): Promise<{\n display: number;\n referral: number;\n sales: number;\n parent: number;\n overhead: number;\n total: number;\n }> {\n const commissions = await this.findByPartner(partnerId);\n const breakdown = {\n display: 0,\n referral: 0,\n sales: 0,\n parent: 0,\n overhead: 0,\n total: 0,\n };\n\n for (const c of commissions) {\n if (c.isPaid() || c.isIncluded()) {\n switch (c.commissionType) {\n case CommissionType.DISPLAY:\n breakdown.display += c.commissionAmount;\n break;\n case CommissionType.REFERRAL:\n breakdown.referral += c.commissionAmount;\n break;\n case CommissionType.SALES:\n breakdown.sales += c.commissionAmount;\n break;\n case CommissionType.PARENT:\n breakdown.parent += c.commissionAmount;\n break;\n case CommissionType.OVERHEAD:\n breakdown.overhead += c.commissionAmount;\n break;\n }\n }\n }\n\n breakdown.total =\n breakdown.display +\n breakdown.referral +\n breakdown.sales +\n breakdown.parent +\n breakdown.overhead;\n return breakdown;\n }\n\n /**\n * Get pending earnings breakdown for a partner\n *\n * @param partnerId - Partner ID\n * @returns Breakdown of pending commissions by type\n */\n async getPendingBreakdown(partnerId: string): Promise<{\n display: number;\n referral: number;\n sales: number;\n parent: number;\n overhead: number;\n total: number;\n }> {\n const pending = await this.findPendingByPartner(partnerId);\n const breakdown = {\n display: 0,\n referral: 0,\n sales: 0,\n parent: 0,\n overhead: 0,\n total: 0,\n };\n\n for (const c of pending) {\n switch (c.commissionType) {\n case CommissionType.DISPLAY:\n breakdown.display += c.commissionAmount;\n break;\n case CommissionType.REFERRAL:\n breakdown.referral += c.commissionAmount;\n break;\n case CommissionType.SALES:\n breakdown.sales += c.commissionAmount;\n break;\n case CommissionType.PARENT:\n breakdown.parent += c.commissionAmount;\n break;\n case CommissionType.OVERHEAD:\n breakdown.overhead += c.commissionAmount;\n break;\n }\n }\n\n breakdown.total =\n breakdown.display +\n breakdown.referral +\n breakdown.sales +\n breakdown.parent +\n breakdown.overhead;\n return breakdown;\n }\n}\n","/**\n * Partner model - Affiliate partner earning entity\n * @packageDocumentation\n */\n\nimport {\n crossPackageRef,\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { PartnerStatus, PartnerType, PayoutMethod } from '../types/index.js';\n\n/**\n * Options for constructing a {@link Partner}.\n */\nexport interface PartnerOptions extends SmrtObjectOptions {\n profileId?: string;\n propertyId?: string;\n partnerTypes?: string;\n parentPartnerId?: string;\n referredById?: string;\n parentCommissionShare?: number;\n displayCommissionRate?: number;\n referralCommissionRate?: number;\n salesCommissionRate?: number;\n payoutThreshold?: number;\n payoutMethod?: PayoutMethod;\n currency?: string;\n status?: PartnerStatus;\n metadata?: string;\n}\n\n/**\n * Partner represents an entity that earns commissions from ad revenue.\n *\n * Partners can be:\n * - Publishers: Own sites that display ads (earn display commissions)\n * - Salespeople: Bring in advertisers (earn sales commissions)\n * - Referrers: Refer new publishers/partners (earn referral commissions)\n *\n * References:\n * - profileId: String reference to smrt-profiles Profile (cross-package)\n * - propertyId: String reference to smrt-properties Property (cross-package)\n * - parentPartnerId: Self-reference for site-attached salespeople\n *\n * @example\n * ```typescript\n * // Create a publisher partner\n * const publisher = await partners.create({\n * profileId: 'profile-uuid',\n * propertyId: 'property-uuid',\n * partnerTypes: JSON.stringify([PartnerType.PUBLISHER]),\n * displayCommissionRate: 0.50,\n * status: PartnerStatus.ACTIVE\n * });\n *\n * // Create a salesperson attached to a publisher\n * const salesperson = await partners.create({\n * profileId: 'salesperson-profile-uuid',\n * parentPartnerId: publisher.id,\n * partnerTypes: JSON.stringify([PartnerType.SALESPERSON]),\n * salesCommissionRate: 0.10,\n * parentCommissionShare: 0.20,\n * status: PartnerStatus.ACTIVE\n * });\n * ```\n */\n// Intentional exception to standards.md §7 (`@TenantScoped`):\n// `Partner` is deliberately NOT tenant-scoped. A single partner (e.g. a\n// publisher operating sites across multiple tenants) needs a stable identity\n// for revenue aggregation, payout thresholds, and tax reporting; slicing\n// identity per tenant would duplicate the row or hide payouts owed across\n// tenants. See `packages/affiliates/CLAUDE.md` \"Tenancy\" section.\n@smrt({\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get', 'create'] },\n cli: true,\n})\nexport class Partner extends SmrtObject {\n /**\n * Profile ID (FK to smrt-profiles Profile, cross-package)\n */\n @crossPackageRef('@happyvertical/smrt-profiles:Profile')\n profileId: string = '';\n\n /**\n * Property ID (FK to smrt-properties Property, cross-package)\n * Only set for publisher partners\n */\n @crossPackageRef('@happyvertical/smrt-properties:Property')\n propertyId: string = '';\n\n /**\n * Partner types as JSON array (publisher, salesperson, referrer)\n * A partner can have multiple types\n */\n partnerTypes: string = '[]';\n\n /**\n * Parent partner ID (self-reference)\n * For site-attached salespeople, this is the publisher they work under\n */\n @foreignKey('Partner')\n parentPartnerId: string = '';\n\n /**\n * Referred by partner ID (self-reference)\n * Tracks who referred this partner for referral commission attribution\n */\n @foreignKey('Partner')\n referredById: string = '';\n\n /**\n * Share of commission that goes to parent partner (0-1)\n * e.g., 0.20 means 20% of this partner's sales commission goes to parent\n */\n parentCommissionShare: number = 0;\n\n /**\n * Commission rate for display (impression) revenue (0-1)\n * Default 50% - publisher earns half of ad impression revenue\n */\n displayCommissionRate: number = 0.5;\n\n /**\n * Commission rate for referral revenue (0-1)\n * Default 5% - referrer earns 5% of referred partner's first-year revenue\n */\n referralCommissionRate: number = 0.05;\n\n /**\n * Commission rate for sales revenue (0-1)\n * Default 10% - salesperson earns 10% of advertiser spend they brought in\n */\n salesCommissionRate: number = 0.1;\n\n /**\n * Minimum payout threshold in cents\n * Default $50 = 5000 cents\n */\n payoutThreshold: number = 5000;\n\n /**\n * Preferred payout method\n */\n payoutMethod: PayoutMethod = PayoutMethod.BANK_TRANSFER;\n\n /**\n * Currency code for all monetary values\n * Defaults to CAD, allows future multi-currency support\n */\n currency: string = 'CAD';\n\n /**\n * Partner status\n */\n status: PartnerStatus = PartnerStatus.PENDING;\n\n /**\n * Additional metadata as JSON string\n * (bank details, tax info, etc.)\n */\n metadata: string = '';\n\n constructor(options: PartnerOptions = {}) {\n super(options);\n if (options.profileId !== undefined) this.profileId = options.profileId;\n if (options.propertyId !== undefined) this.propertyId = options.propertyId;\n if (options.partnerTypes !== undefined)\n this.partnerTypes = options.partnerTypes;\n if (options.parentPartnerId !== undefined)\n this.parentPartnerId = options.parentPartnerId;\n if (options.referredById !== undefined)\n this.referredById = options.referredById;\n if (options.parentCommissionShare !== undefined)\n this.parentCommissionShare = options.parentCommissionShare;\n if (options.displayCommissionRate !== undefined)\n this.displayCommissionRate = options.displayCommissionRate;\n if (options.referralCommissionRate !== undefined)\n this.referralCommissionRate = options.referralCommissionRate;\n if (options.salesCommissionRate !== undefined)\n this.salesCommissionRate = options.salesCommissionRate;\n if (options.payoutThreshold !== undefined)\n this.payoutThreshold = options.payoutThreshold;\n if (options.payoutMethod !== undefined)\n this.payoutMethod = options.payoutMethod;\n if (options.currency !== undefined) this.currency = options.currency;\n if (options.status !== undefined) this.status = options.status;\n if (options.metadata !== undefined) this.metadata = options.metadata;\n }\n\n /**\n * Get partner types as array\n */\n getPartnerTypes(): PartnerType[] {\n if (!this.partnerTypes) return [];\n try {\n return JSON.parse(this.partnerTypes);\n } catch {\n return [];\n }\n }\n\n /**\n * Set partner types from array\n */\n setPartnerTypes(types: PartnerType[]): void {\n this.partnerTypes = JSON.stringify(types);\n }\n\n /**\n * Check if partner has a specific type\n */\n hasType(type: PartnerType): boolean {\n return this.getPartnerTypes().includes(type);\n }\n\n /**\n * Check if partner is a publisher\n */\n isPublisher(): boolean {\n return this.hasType(PartnerType.PUBLISHER);\n }\n\n /**\n * Check if partner is a salesperson\n */\n isSalesperson(): boolean {\n return this.hasType(PartnerType.SALESPERSON);\n }\n\n /**\n * Check if partner is a referrer\n */\n isReferrer(): boolean {\n return this.hasType(PartnerType.REFERRER);\n }\n\n /**\n * Check if partner is active\n */\n isActive(): boolean {\n return this.status === PartnerStatus.ACTIVE;\n }\n\n /**\n * Check if partner is pending approval\n */\n isPending(): boolean {\n return this.status === PartnerStatus.PENDING;\n }\n\n /**\n * Check if partner is suspended\n */\n isSuspended(): boolean {\n return this.status === PartnerStatus.SUSPENDED;\n }\n\n /**\n * Check if partner has a parent (site-attached)\n */\n hasParent(): boolean {\n return !!this.parentPartnerId;\n }\n\n /**\n * Check if partner was referred by another partner\n */\n wasReferred(): boolean {\n return !!this.referredById;\n }\n\n /**\n * Get metadata as object\n */\n getMetadata(): Record<string, unknown> {\n if (!this.metadata) return {};\n try {\n return JSON.parse(this.metadata);\n } catch {\n return {};\n }\n }\n\n /**\n * Set metadata from object\n */\n setMetadata(data: Record<string, unknown>): void {\n this.metadata = JSON.stringify(data);\n }\n\n /**\n * Calculate effective sales commission rate (after parent share)\n */\n getEffectiveSalesRate(): number {\n if (this.parentPartnerId && this.parentCommissionShare > 0) {\n return this.salesCommissionRate * (1 - this.parentCommissionShare);\n }\n return this.salesCommissionRate;\n }\n}\n\nexport default Partner;\n","/**\n * PartnerCollection - Collection manager for Partner objects\n * @packageDocumentation\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { Partner } from '../models/Partner.js';\nimport { PartnerStatus, PartnerType } from '../types/index.js';\n\nexport class PartnerCollection extends SmrtCollection<Partner> {\n static readonly _itemClass = Partner;\n\n /**\n * Find partners by profile ID\n *\n * @param profileId - Profile ID\n * @returns Array of partners\n */\n async findByProfile(profileId: string): Promise<Partner[]> {\n return await this.list({\n where: { profileId },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find partner by property ID (publishers)\n *\n * @param propertyId - Property ID\n * @returns Partner or null\n */\n async findByProperty(propertyId: string): Promise<Partner | null> {\n const results = await this.list({\n where: { propertyId },\n limit: 1,\n });\n return results[0] || null;\n }\n\n /**\n * Find partners by parent partner ID\n *\n * @param parentPartnerId - Parent partner ID\n * @returns Array of child partners\n */\n async findByParent(parentPartnerId: string): Promise<Partner[]> {\n return await this.list({\n where: { parentPartnerId },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find partners referred by a specific partner\n *\n * @param referredById - Referrer partner ID\n * @returns Array of referred partners\n */\n async findByReferrer(referredById: string): Promise<Partner[]> {\n return await this.list({\n where: { referredById },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find partners by status\n *\n * @param status - Partner status\n * @returns Array of partners\n */\n async findByStatus(status: PartnerStatus): Promise<Partner[]> {\n return await this.list({\n where: { status },\n orderBy: 'created_at DESC',\n });\n }\n\n /**\n * Find all active partners\n */\n async findActive(): Promise<Partner[]> {\n return await this.findByStatus(PartnerStatus.ACTIVE);\n }\n\n /**\n * Find all pending partners (awaiting approval)\n */\n async findPending(): Promise<Partner[]> {\n return await this.findByStatus(PartnerStatus.PENDING);\n }\n\n /**\n * Find all suspended partners\n */\n async findSuspended(): Promise<Partner[]> {\n return await this.findByStatus(PartnerStatus.SUSPENDED);\n }\n\n /**\n * Find partners by type (requires in-memory filtering for JSON field)\n *\n * @param type - Partner type to filter by\n * @returns Array of partners with that type\n */\n async findByType(type: PartnerType): Promise<Partner[]> {\n const all = await this.list({});\n return all.filter((partner) => partner.hasType(type));\n }\n\n /**\n * Find all publisher partners\n */\n async findPublishers(): Promise<Partner[]> {\n return await this.findByType(PartnerType.PUBLISHER);\n }\n\n /**\n * Find all salesperson partners\n */\n async findSalespeople(): Promise<Partner[]> {\n return await this.findByType(PartnerType.SALESPERSON);\n }\n\n /**\n * Find all referrer partners\n */\n async findReferrers(): Promise<Partner[]> {\n return await this.findByType(PartnerType.REFERRER);\n }\n\n /**\n * Find active publishers (for ad serving)\n */\n async findActivePublishers(): Promise<Partner[]> {\n const publishers = await this.findPublishers();\n return publishers.filter((p) => p.isActive());\n }\n\n /**\n * Find partner for ad serving by property ID\n * Returns active publisher partner for the property\n *\n * @param propertyId - Property ID\n * @returns Active publisher partner or null\n */\n async findActiveByProperty(propertyId: string): Promise<Partner | null> {\n const partner = await this.findByProperty(propertyId);\n if (partner?.isActive() && partner.isPublisher()) {\n return partner;\n }\n return null;\n }\n\n /**\n * Find partners eligible for payout\n * (active partners with pending commissions above threshold)\n * Note: Actual threshold check requires joining with commissions\n */\n async findEligibleForPayout(): Promise<Partner[]> {\n const active = await this.findActive();\n // Actual eligibility check happens in payout service\n // which sums pending commissions per partner\n return active;\n }\n}\n","/**\n * Payout model - Aggregated payout batch for a partner\n * @packageDocumentation\n */\n\nimport {\n crossPackageRef,\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { PayoutStatus } from '../types/index.js';\n\n/**\n * Options for constructing a {@link Payout}.\n */\nexport interface PayoutOptions extends SmrtObjectOptions {\n partnerId?: string;\n periodStart?: Date;\n periodEnd?: Date;\n displayEarnings?: number;\n referralEarnings?: number;\n salesEarnings?: number;\n parentEarnings?: number;\n overheadEarnings?: number;\n totalAmount?: number;\n currency?: string;\n invoiceId?: string;\n status?: PayoutStatus;\n paymentReference?: string;\n paidAt?: Date | null;\n notes?: string;\n metadata?: string;\n}\n\n/**\n * Payout represents an aggregated payment batch for a partner.\n *\n * Payouts are created periodically (e.g., monthly) and include\n * all pending commissions for a partner that meet the threshold.\n *\n * References:\n * - partnerId: FK to Partner (within package)\n * - invoiceId: String reference to smrt-commerce Invoice (cross-package)\n *\n * @example\n * ```typescript\n * // Create a payout for a partner\n * const payout = await payouts.create({\n * partnerId: publisher.id,\n * periodStart: new Date('2024-01-01'),\n * periodEnd: new Date('2024-01-31'),\n * displayEarnings: 25000, // $250.00\n * referralEarnings: 500, // $5.00\n * salesEarnings: 0,\n * parentEarnings: 0,\n * totalAmount: 25500, // $255.00\n * currency: 'CAD',\n * status: PayoutStatus.PENDING\n * });\n * ```\n */\n// Intentional exception to standards.md §7 (`@TenantScoped`):\n// `Payout` is deliberately NOT tenant-scoped. Payouts aggregate commissions\n// for a `Partner` regardless of which tenant generated the underlying revenue;\n// a tenant-scoped query would systematically under-report what is owed. See\n// `packages/affiliates/CLAUDE.md` \"Tenancy\" section.\n@smrt({\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get', 'create'] },\n cli: true,\n})\nexport class Payout extends SmrtObject {\n /**\n * Partner ID (FK to Partner)\n */\n @foreignKey('Partner')\n partnerId: string = '';\n\n /**\n * Period start date\n */\n periodStart: Date = new Date();\n\n /**\n * Period end date\n */\n periodEnd: Date = new Date();\n\n /**\n * Total display earnings in cents\n */\n displayEarnings: number = 0;\n\n /**\n * Total referral earnings in cents\n */\n referralEarnings: number = 0;\n\n /**\n * Total sales earnings in cents\n */\n salesEarnings: number = 0;\n\n /**\n * Total parent earnings in cents (from site-attached salespeople)\n */\n parentEarnings: number = 0;\n\n /**\n * Total overhead earnings in cents (network overhead commissions)\n */\n overheadEarnings: number = 0;\n\n /**\n * Total payout amount in cents\n * = displayEarnings + referralEarnings + salesEarnings + parentEarnings + overheadEarnings\n */\n totalAmount: number = 0;\n\n /**\n * Currency code\n * Defaults to CAD\n */\n currency: string = 'CAD';\n\n /**\n * Invoice ID when payout is processed (FK to smrt-commerce Invoice)\n * Partner is treated as a Vendor for payout invoices\n */\n @crossPackageRef('@happyvertical/smrt-commerce:Invoice')\n invoiceId: string = '';\n\n /**\n * Payout status\n */\n status: PayoutStatus = PayoutStatus.PENDING;\n\n /**\n * Payment reference (check number, transfer ID, etc.)\n */\n paymentReference: string = '';\n\n /**\n * Date payment was processed\n */\n paidAt: Date | null = null;\n\n /**\n * Notes from admin (approval notes, issues, etc.)\n */\n notes: string = '';\n\n /**\n * Additional metadata as JSON string\n */\n metadata: string = '';\n\n constructor(options: PayoutOptions = {}) {\n super(options);\n if (options.partnerId !== undefined) this.partnerId = options.partnerId;\n if (options.periodStart !== undefined)\n this.periodStart = options.periodStart;\n if (options.periodEnd !== undefined) this.periodEnd = options.periodEnd;\n if (options.displayEarnings !== undefined)\n this.displayEarnings = options.displayEarnings;\n if (options.referralEarnings !== undefined)\n this.referralEarnings = options.referralEarnings;\n if (options.salesEarnings !== undefined)\n this.salesEarnings = options.salesEarnings;\n if (options.parentEarnings !== undefined)\n this.parentEarnings = options.parentEarnings;\n if (options.overheadEarnings !== undefined)\n this.overheadEarnings = options.overheadEarnings;\n if (options.totalAmount !== undefined)\n this.totalAmount = options.totalAmount;\n if (options.currency !== undefined) this.currency = options.currency;\n if (options.invoiceId !== undefined) this.invoiceId = options.invoiceId;\n if (options.status !== undefined) this.status = options.status;\n if (options.paymentReference !== undefined)\n this.paymentReference = options.paymentReference;\n if (options.paidAt !== undefined) this.paidAt = options.paidAt;\n if (options.notes !== undefined) this.notes = options.notes;\n if (options.metadata !== undefined) this.metadata = options.metadata;\n }\n\n /**\n * Check if payout is pending approval\n */\n isPending(): boolean {\n return this.status === PayoutStatus.PENDING;\n }\n\n /**\n * Check if payout is approved (waiting for processing)\n */\n isApproved(): boolean {\n return this.status === PayoutStatus.APPROVED;\n }\n\n /**\n * Check if payout is being processed\n */\n isProcessing(): boolean {\n return this.status === PayoutStatus.PROCESSING;\n }\n\n /**\n * Check if payout is completed\n */\n isCompleted(): boolean {\n return this.status === PayoutStatus.COMPLETED;\n }\n\n /**\n * Check if payout failed\n */\n isFailed(): boolean {\n return this.status === PayoutStatus.FAILED;\n }\n\n /**\n * Get total amount in dollars (for display)\n */\n getTotalInDollars(): number {\n return this.totalAmount / 100;\n }\n\n /**\n * Get display earnings in dollars\n */\n getDisplayEarningsInDollars(): number {\n return this.displayEarnings / 100;\n }\n\n /**\n * Get referral earnings in dollars\n */\n getReferralEarningsInDollars(): number {\n return this.referralEarnings / 100;\n }\n\n /**\n * Get sales earnings in dollars\n */\n getSalesEarningsInDollars(): number {\n return this.salesEarnings / 100;\n }\n\n /**\n * Get parent earnings in dollars\n */\n getParentEarningsInDollars(): number {\n return this.parentEarnings / 100;\n }\n\n /**\n * Get overhead earnings in dollars\n */\n getOverheadEarningsInDollars(): number {\n return this.overheadEarnings / 100;\n }\n\n /**\n * Calculate total from component earnings\n */\n calculateTotal(): number {\n return (\n this.displayEarnings +\n this.referralEarnings +\n this.salesEarnings +\n this.parentEarnings +\n this.overheadEarnings\n );\n }\n\n /**\n * Get period as human-readable string\n */\n getPeriodString(): string {\n const start = this.periodStart.toISOString().split('T')[0];\n const end = this.periodEnd.toISOString().split('T')[0];\n return `${start} to ${end}`;\n }\n\n /**\n * Get metadata as object\n */\n getMetadata(): Record<string, unknown> {\n if (!this.metadata) return {};\n try {\n return JSON.parse(this.metadata);\n } catch {\n return {};\n }\n }\n\n /**\n * Set metadata from object\n */\n setMetadata(data: Record<string, unknown>): void {\n this.metadata = JSON.stringify(data);\n }\n\n // ============================================================================\n // Status Transitions\n // ============================================================================\n\n /**\n * Approve the payout for processing\n *\n * @throws Error if payout is not in pending status\n */\n approve(): void {\n if (this.status !== PayoutStatus.PENDING) {\n throw new Error(\n `Cannot approve payout with status '${this.status}'. Only pending payouts can be approved.`,\n );\n }\n this.status = PayoutStatus.APPROVED;\n }\n\n /**\n * Mark payout as processing (payment in progress)\n *\n * @throws Error if payout is not in approved status\n */\n markProcessing(): void {\n if (this.status !== PayoutStatus.APPROVED) {\n throw new Error(\n `Cannot mark payout as processing with status '${this.status}'. Only approved payouts can be processed.`,\n );\n }\n this.status = PayoutStatus.PROCESSING;\n }\n\n /**\n * Mark payout as completed\n *\n * @param paymentReference - Payment reference (check number, transfer ID, etc.)\n * @throws Error if payout is not in processing status\n */\n complete(paymentReference: string): void {\n if (this.status !== PayoutStatus.PROCESSING) {\n throw new Error(\n `Cannot complete payout with status '${this.status}'. Only processing payouts can be completed.`,\n );\n }\n this.status = PayoutStatus.COMPLETED;\n this.paymentReference = paymentReference;\n this.paidAt = new Date();\n }\n\n /**\n * Mark payout as failed\n *\n * @param reason - Reason for failure (stored in notes)\n */\n fail(reason: string): void {\n if (\n this.status !== PayoutStatus.APPROVED &&\n this.status !== PayoutStatus.PROCESSING\n ) {\n throw new Error(\n `Cannot fail payout with status '${this.status}'. Only approved or processing payouts can fail.`,\n );\n }\n this.status = PayoutStatus.FAILED;\n this.notes = reason;\n }\n}\n\nexport default Payout;\n","/**\n * PayoutCollection - Collection manager for Payout objects\n * @packageDocumentation\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { Payout } from '../models/Payout.js';\nimport { PayoutStatus } from '../types/index.js';\n\nexport class PayoutCollection extends SmrtCollection<Payout> {\n static readonly _itemClass = Payout;\n\n /**\n * Find payouts by partner\n *\n * @param partnerId - Partner ID\n * @returns Array of payouts\n */\n async findByPartner(partnerId: string): Promise<Payout[]> {\n return await this.list({\n where: { partnerId },\n orderBy: 'period_end DESC',\n });\n }\n\n /**\n * Find payouts by status\n *\n * @param status - Payout status\n * @returns Array of payouts\n */\n async findByStatus(status: PayoutStatus): Promise<Payout[]> {\n return await this.list({\n where: { status },\n orderBy: 'period_end DESC',\n });\n }\n\n /**\n * Find all pending payouts (awaiting approval)\n */\n async findPending(): Promise<Payout[]> {\n return await this.findByStatus(PayoutStatus.PENDING);\n }\n\n /**\n * Find all approved payouts (ready for processing)\n */\n async findApproved(): Promise<Payout[]> {\n return await this.findByStatus(PayoutStatus.APPROVED);\n }\n\n /**\n * Find all processing payouts\n */\n async findProcessing(): Promise<Payout[]> {\n return await this.findByStatus(PayoutStatus.PROCESSING);\n }\n\n /**\n * Find all completed payouts\n */\n async findCompleted(): Promise<Payout[]> {\n return await this.findByStatus(PayoutStatus.COMPLETED);\n }\n\n /**\n * Find all failed payouts\n */\n async findFailed(): Promise<Payout[]> {\n return await this.findByStatus(PayoutStatus.FAILED);\n }\n\n /**\n * Find payouts by invoice\n *\n * @param invoiceId - Invoice ID\n * @returns Array of payouts\n */\n async findByInvoice(invoiceId: string): Promise<Payout[]> {\n return await this.list({\n where: { invoiceId },\n orderBy: 'period_end DESC',\n });\n }\n\n /**\n * Find payouts in period range\n *\n * @param start - Period start date\n * @param end - Period end date\n * @returns Array of payouts\n */\n async findByPeriod(start: Date, end: Date): Promise<Payout[]> {\n return await this.list({\n where: {\n 'period_start >=': start.toISOString(),\n 'period_end <=': end.toISOString(),\n },\n orderBy: 'period_end DESC',\n });\n }\n\n /**\n * Find payouts for a partner by status\n *\n * @param partnerId - Partner ID\n * @param status - Payout status\n * @returns Array of payouts\n */\n async findByPartnerAndStatus(\n partnerId: string,\n status: PayoutStatus,\n ): Promise<Payout[]> {\n return await this.list({\n where: { partnerId, status },\n orderBy: 'period_end DESC',\n });\n }\n\n /**\n * Find pending payouts for a partner\n *\n * @param partnerId - Partner ID\n * @returns Array of pending payouts\n */\n async findPendingByPartner(partnerId: string): Promise<Payout[]> {\n return await this.findByPartnerAndStatus(partnerId, PayoutStatus.PENDING);\n }\n\n /**\n * Find completed payouts for a partner\n *\n * @param partnerId - Partner ID\n * @returns Array of completed payouts\n */\n async findCompletedByPartner(partnerId: string): Promise<Payout[]> {\n return await this.findByPartnerAndStatus(partnerId, PayoutStatus.COMPLETED);\n }\n\n /**\n * Sum total paid to a partner\n *\n * @param partnerId - Partner ID\n * @returns Total paid in cents\n */\n async sumPaidByPartner(partnerId: string): Promise<number> {\n const completed = await this.findCompletedByPartner(partnerId);\n return completed.reduce((sum, p) => sum + p.totalAmount, 0);\n }\n\n /**\n * Sum total pending for a partner\n *\n * @param partnerId - Partner ID\n * @returns Total pending in cents\n */\n async sumPendingByPartner(partnerId: string): Promise<number> {\n const pending = await this.findPendingByPartner(partnerId);\n return pending.reduce((sum, p) => sum + p.totalAmount, 0);\n }\n\n /**\n * Get most recent payout for a partner\n *\n * @param partnerId - Partner ID\n * @returns Most recent payout or null\n */\n async findLatestByPartner(partnerId: string): Promise<Payout | null> {\n const results = await this.list({\n where: { partnerId },\n orderBy: 'period_end DESC',\n limit: 1,\n });\n return results[0] || null;\n }\n\n /**\n * Get payout statistics\n *\n * @returns Stats object\n */\n async getStats(): Promise<{\n pending: number;\n approved: number;\n processing: number;\n completed: number;\n failed: number;\n totalPaid: number;\n totalPending: number;\n }> {\n const all = await this.list({});\n\n const stats = {\n pending: 0,\n approved: 0,\n processing: 0,\n completed: 0,\n failed: 0,\n totalPaid: 0,\n totalPending: 0,\n };\n\n for (const p of all) {\n switch (p.status) {\n case PayoutStatus.PENDING:\n stats.pending++;\n stats.totalPending += p.totalAmount;\n break;\n case PayoutStatus.APPROVED:\n stats.approved++;\n stats.totalPending += p.totalAmount;\n break;\n case PayoutStatus.PROCESSING:\n stats.processing++;\n break;\n case PayoutStatus.COMPLETED:\n stats.completed++;\n stats.totalPaid += p.totalAmount;\n break;\n case PayoutStatus.FAILED:\n stats.failed++;\n break;\n }\n }\n\n return stats;\n }\n}\n"],"names":["PartnerType","PartnerStatus","CommissionType","CommissionStatus","PayoutStatus","PayoutMethod","__decorateClass"],"mappings":";AAsBA,eAAe;AAAA,EACb,IAAA,IAAA,mBAAA,YAAA,GAAA;AACF;ACjBO,IAAK,gCAAAA,iBAAL;AACLA,eAAA,WAAA,IAAY;AACZA,eAAA,aAAA,IAAc;AACdA,eAAA,UAAA,IAAW;AAHD,SAAAA;AAAA,GAAA,eAAA,CAAA,CAAA;AASL,IAAK,kCAAAC,mBAAL;AACLA,iBAAA,SAAA,IAAU;AACVA,iBAAA,QAAA,IAAS;AACTA,iBAAA,WAAA,IAAY;AAHF,SAAAA;AAAA,GAAA,iBAAA,CAAA,CAAA;AASL,IAAK,mCAAAC,oBAAL;AACLA,kBAAA,SAAA,IAAU;AACVA,kBAAA,UAAA,IAAW;AACXA,kBAAA,OAAA,IAAQ;AACRA,kBAAA,QAAA,IAAS;AACTA,kBAAA,UAAA,IAAW;AALD,SAAAA;AAAA,GAAA,kBAAA,CAAA,CAAA;AAWL,IAAK,qCAAAC,sBAAL;AACLA,oBAAA,SAAA,IAAU;AACVA,oBAAA,UAAA,IAAW;AACXA,oBAAA,MAAA,IAAO;AAHG,SAAAA;AAAA,GAAA,oBAAA,CAAA,CAAA;AASL,IAAK,iCAAAC,kBAAL;AACLA,gBAAA,SAAA,IAAU;AACVA,gBAAA,UAAA,IAAW;AACXA,gBAAA,YAAA,IAAa;AACbA,gBAAA,WAAA,IAAY;AACZA,gBAAA,QAAA,IAAS;AALC,SAAAA;AAAA,GAAA,gBAAA,CAAA,CAAA;AAWL,IAAK,iCAAAC,kBAAL;AACLA,gBAAA,eAAA,IAAgB;AAChBA,gBAAA,OAAA,IAAQ;AACRA,gBAAA,QAAA,IAAS;AACTA,gBAAA,QAAA,IAAS;AAJC,SAAAA;AAAA,GAAA,gBAAA,CAAA,CAAA;;;;;;;;;;;ACkBL,IAAM,aAAN,cAAyB,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAazC,OAAO,gBAAgB,cAAsB,MAAsB;AACjE,WAAO,KAAK,MAAM,eAAe,IAAI;AAAA,EACvC;AAAA,EAKA,UAAkB;AAAA,EAMlB,YAAoB;AAAA;AAAA;AAAA;AAAA,EAKpB,iBAAiC,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA,EAMhD,eAAuB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMvB,iBAAyB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMzB,mBAA2B;AAAA;AAAA;AAAA;AAAA;AAAA,EAM3B,WAAmB;AAAA,EAMnB,WAAmB;AAAA;AAAA;AAAA;AAAA,EAKnB,SAA2B,iBAAiB;AAAA;AAAA;AAAA;AAAA,EAK5C,qCAA2B,KAAA;AAAA;AAAA;AAAA;AAAA,EAK3B,YAAoB;AAAA;AAAA;AAAA;AAAA,EAKpB,SAAiB;AAAA;AAAA;AAAA;AAAA,EAKjB,aAAqB;AAAA;AAAA;AAAA;AAAA,EAKrB,WAAmB;AAAA,EAEnB,YAAY,UAA6B,IAAI;AAC3C,UAAM,OAAO;AACb,QAAI,QAAQ,YAAY,OAAW,MAAK,UAAU,QAAQ;AAC1D,QAAI,QAAQ,cAAc,OAAW,MAAK,YAAY,QAAQ;AAC9D,QAAI,QAAQ,mBAAmB;AAC7B,WAAK,iBAAiB,QAAQ;AAChC,QAAI,QAAQ,iBAAiB;AAC3B,WAAK,eAAe,QAAQ;AAC9B,QAAI,QAAQ,mBAAmB;AAC7B,WAAK,iBAAiB,QAAQ;AAChC,QAAI,QAAQ,qBAAqB;AAC/B,WAAK,mBAAmB,QAAQ;AAClC,QAAI,QAAQ,aAAa,OAAW,MAAK,WAAW,QAAQ;AAC5D,QAAI,QAAQ,aAAa,OAAW,MAAK,WAAW,QAAQ;AAC5D,QAAI,QAAQ,WAAW,OAAW,MAAK,SAAS,QAAQ;AACxD,QAAI,QAAQ,mBAAmB;AAC7B,WAAK,iBAAiB,QAAQ;AAChC,QAAI,QAAQ,cAAc,OAAW,MAAK,YAAY,QAAQ;AAC9D,QAAI,QAAQ,WAAW,OAAW,MAAK,SAAS,QAAQ;AACxD,QAAI,QAAQ,eAAe,OAAW,MAAK,aAAa,QAAQ;AAChE,QAAI,QAAQ,aAAa,OAAW,MAAK,WAAW,QAAQ;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA,EAKA,YAAqB;AACnB,WAAO,KAAK,WAAW,iBAAiB;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,aAAsB;AACpB,WAAO,KAAK,WAAW,iBAAiB;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,SAAkB;AAChB,WAAO,KAAK,WAAW,iBAAiB;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,YAAqB;AACnB,WAAO,KAAK,mBAAmB,eAAe;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,aAAsB;AACpB,WAAO,KAAK,mBAAmB,eAAe;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,UAAmB;AACjB,WAAO,KAAK,mBAAmB,eAAe;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,WAAoB;AAClB,WAAO,KAAK,mBAAmB,eAAe;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,aAAsB;AACpB,WAAO,KAAK,mBAAmB,eAAe;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKA,qBAA6B;AAC3B,WAAO,KAAK,mBAAmB;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,2BAAmC;AACjC,WAAO,KAAK,eAAe;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,cAAuC;AACrC,QAAI,CAAC,KAAK,SAAU,QAAO,CAAA;AAC3B,QAAI;AACF,aAAO,KAAK,MAAM,KAAK,QAAQ;AAAA,IACjC,QAAQ;AACN,aAAO,CAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,MAAqC;AAC/C,SAAK,WAAW,KAAK,UAAU,IAAI;AAAA,EACrC;AACF;AAxLEC,kBAAA;AAAA,EADC,gBAAgB,iCAAiC;AAAA,GAnBvC,WAoBX,WAAA,WAAA,CAAA;AAMAA,kBAAA;AAAA,EADC,WAAW,SAAS;AAAA,GAzBV,WA0BX,WAAA,aAAA,CAAA;AAmCAA,kBAAA;AAAA,EADC,WAAW,QAAQ;AAAA,GA5DT,WA6DX,WAAA,YAAA,CAAA;AA7DW,aAANA,kBAAA;AAAA,EALN,KAAK;AAAA,IACJ,KAAK,EAAE,SAAS,CAAC,UAAU,QAAQ,KAAK,EAAA;AAAA;AAAA,IACxC,KAAK,EAAE,SAAS,CAAC,UAAU,MAAM,EAAA;AAAA,IACjC,KAAK;AAAA;AAAA,EAAA,CACN;AAAA,GACY,UAAA;ACjEN,MAAM,6BAA6B,eAA2B;AAAA,EACnE,OAAgB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ7B,MAAM,cAAc,WAA0C;AAC5D,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,UAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,YAAY,SAAwC;AACxD,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,QAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aAAa,UAAyC;AAC1D,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,SAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aAAa,QAAiD;AAClE,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,OAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAqC;AACzC,WAAO,MAAM,KAAK,aAAa,iBAAiB,OAAO;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,qBAAqB,WAA0C;AACnE,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,WAAW,QAAQ,iBAAiB,QAAA;AAAA,MAC7C,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,WAAW,gBAAuD;AACtE,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,eAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,gBAAgB,OAAa,KAAkC;AACnE,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO;AAAA,QACL,sBAAsB,MAAM,YAAA;AAAA,QAC5B,sBAAsB,IAAI,YAAA;AAAA,MAAY;AAAA,MAExC,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,0BACJ,WACA,OACA,KACuB;AACvB,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO;AAAA,QACL;AAAA,QACA,sBAAsB,MAAM,YAAA;AAAA,QAC5B,sBAAsB,IAAI,YAAA;AAAA,MAAY;AAAA,MAExC,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,cAAc,WAA0C;AAC5D,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,UAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,qBACJ,WACA,gBACuB;AACvB,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,WAAW,eAAA;AAAA,MACpB,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,qBAAqB,WAA0C;AACnE,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,WAAW,QAAQ,iBAAiB,QAAA;AAAA,MAC7C,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,oBACJ,WACA,UAKI,IAMH;AACD,UAAM,QAAiC,EAAE,UAAA;AACzC,QAAI,QAAQ,OAAQ,OAAM,SAAS,QAAQ;AAC3C,QAAI,QAAQ,eAAgB,OAAM,iBAAiB,QAAQ;AAC3D,QAAI,QAAQ,KAAM,OAAM,oBAAoB,IAAI,QAAQ,KAAK,YAAA;AAC7D,QAAI,QAAQ,GAAI,OAAM,oBAAoB,IAAI,QAAQ,GAAG,YAAA;AAEzD,UAAM,WAAW,MAAM,KAAK,KAAK,EAAE,OAAO;AAE1C,UAAM,SAAiC;AAAA,MACrC,UAAU;AAAA,MACV,SAAS;AAAA,MACT,UAAU;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,IAAA;AAEV,UAAM,SAAiC,CAAA;AACvC,QAAI,QAAQ;AAEZ,eAAW,KAAK,UAAU;AACxB,aAAO,EAAE,cAAc,KACpB,OAAO,EAAE,cAAc,KAAK,KAAK,EAAE;AACtC,UAAI,EAAE,QAAQ;AACZ,eAAO,EAAE,MAAM,KAAK,OAAO,EAAE,MAAM,KAAK,KAAK,EAAE;AAAA,MACjD;AACA,eAAS,EAAE;AAAA,IACb;AAEA,WAAO,EAAE,QAAQ,QAAQ,OAAO,OAAO,SAAS,OAAA;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,2BAA2B,WAc/B;AACA,UAAM,UAAU,MAAM,KAAK,qBAAqB,SAAS;AAGzD,UAAM,cAAc,QAAQ;AAAA,MAC1B,CAAC,MAAM,EAAE,aAAa,EAAE,cAAc;AAAA,IAAA;AAIxC,UAAM,8BAAc,IAAA;AACpB,eAAW,KAAK,aAAa;AAC3B,YAAM,WAAW,QAAQ,IAAI,EAAE,SAAS,KAAK,CAAA;AAC7C,eAAS,KAAK,CAAC;AACf,cAAQ,IAAI,EAAE,WAAW,QAAQ;AAAA,IACnC;AAEA,UAAM,UAYD,CAAA;AACL,eAAW,CAAC,WAAW,KAAK,KAAK,SAAS;AACxC,YAAM,eAAe,MAAM;AAAA,QACzB,CAAC,KAAK,MAAM,MAAM,EAAE;AAAA,QACpB;AAAA,MAAA;AAEF,YAAM,WAAW,MAAM,CAAC,GAAG,YAAY;AAEvC,cAAQ,KAAK;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,QACA,YAAY,MAAM;AAAA,QAClB,SAAS,MAAM,IAAI,CAAC,OAAO;AAAA,UACzB,IAAI,EAAE,MAAM;AAAA,UACZ,gBAAgB,EAAE;AAAA,UAClB,kBAAkB,EAAE;AAAA,UACpB,YAAY,EAAE;AAAA,UACd,QAAQ,EAAE;AAAA,QAAA,EACV;AAAA,MAAA,CACH;AAAA,IACH;AAGA,YAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,eAAe,EAAE,YAAY;AAEtD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,oBAAoB,WAAoC;AAC5D,UAAM,UAAU,MAAM,KAAK,qBAAqB,SAAS;AACzD,WAAO,QAAQ,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,kBAAkB,CAAC;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,oBACJ,WACA,gBACiB;AACjB,UAAM,cAAc,MAAM,KAAK,KAAK;AAAA,MAClC,OAAO,EAAE,WAAW,eAAA;AAAA,IAAe,CACpC;AACD,WAAO,YAAY,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,kBAAkB,CAAC;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,qBAAqB,WAOxB;AACD,UAAM,cAAc,MAAM,KAAK,cAAc,SAAS;AACtD,UAAM,YAAY;AAAA,MAChB,SAAS;AAAA,MACT,UAAU;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,OAAO;AAAA,IAAA;AAGT,eAAW,KAAK,aAAa;AAC3B,UAAI,EAAE,OAAA,KAAY,EAAE,cAAc;AAChC,gBAAQ,EAAE,gBAAA;AAAA,UACR,KAAK,eAAe;AAClB,sBAAU,WAAW,EAAE;AACvB;AAAA,UACF,KAAK,eAAe;AAClB,sBAAU,YAAY,EAAE;AACxB;AAAA,UACF,KAAK,eAAe;AAClB,sBAAU,SAAS,EAAE;AACrB;AAAA,UACF,KAAK,eAAe;AAClB,sBAAU,UAAU,EAAE;AACtB;AAAA,UACF,KAAK,eAAe;AAClB,sBAAU,YAAY,EAAE;AACxB;AAAA,QAAA;AAAA,MAEN;AAAA,IACF;AAEA,cAAU,QACR,UAAU,UACV,UAAU,WACV,UAAU,QACV,UAAU,SACV,UAAU;AACZ,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,oBAAoB,WAOvB;AACD,UAAM,UAAU,MAAM,KAAK,qBAAqB,SAAS;AACzD,UAAM,YAAY;AAAA,MAChB,SAAS;AAAA,MACT,UAAU;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,OAAO;AAAA,IAAA;AAGT,eAAW,KAAK,SAAS;AACvB,cAAQ,EAAE,gBAAA;AAAA,QACR,KAAK,eAAe;AAClB,oBAAU,WAAW,EAAE;AACvB;AAAA,QACF,KAAK,eAAe;AAClB,oBAAU,YAAY,EAAE;AACxB;AAAA,QACF,KAAK,eAAe;AAClB,oBAAU,SAAS,EAAE;AACrB;AAAA,QACF,KAAK,eAAe;AAClB,oBAAU,UAAU,EAAE;AACtB;AAAA,QACF,KAAK,eAAe;AAClB,oBAAU,YAAY,EAAE;AACxB;AAAA,MAAA;AAAA,IAEN;AAEA,cAAU,QACR,UAAU,UACV,UAAU,WACV,UAAU,QACV,UAAU,SACV,UAAU;AACZ,WAAO;AAAA,EACT;AACF;;;;;;;;;;;AC/WO,IAAM,UAAN,cAAsB,WAAW;AAAA,EAKtC,YAAoB;AAAA,EAOpB,aAAqB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMrB,eAAuB;AAAA,EAOvB,kBAA0B;AAAA,EAO1B,eAAuB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMvB,wBAAgC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMhC,wBAAgC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMhC,yBAAiC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMjC,sBAA8B;AAAA;AAAA;AAAA;AAAA;AAAA,EAM9B,kBAA0B;AAAA;AAAA;AAAA;AAAA,EAK1B,eAA6B,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA,EAM1C,WAAmB;AAAA;AAAA;AAAA;AAAA,EAKnB,SAAwB,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA,EAMtC,WAAmB;AAAA,EAEnB,YAAY,UAA0B,IAAI;AACxC,UAAM,OAAO;AACb,QAAI,QAAQ,cAAc,OAAW,MAAK,YAAY,QAAQ;AAC9D,QAAI,QAAQ,eAAe,OAAW,MAAK,aAAa,QAAQ;AAChE,QAAI,QAAQ,iBAAiB;AAC3B,WAAK,eAAe,QAAQ;AAC9B,QAAI,QAAQ,oBAAoB;AAC9B,WAAK,kBAAkB,QAAQ;AACjC,QAAI,QAAQ,iBAAiB;AAC3B,WAAK,eAAe,QAAQ;AAC9B,QAAI,QAAQ,0BAA0B;AACpC,WAAK,wBAAwB,QAAQ;AACvC,QAAI,QAAQ,0BAA0B;AACpC,WAAK,wBAAwB,QAAQ;AACvC,QAAI,QAAQ,2BAA2B;AACrC,WAAK,yBAAyB,QAAQ;AACxC,QAAI,QAAQ,wBAAwB;AAClC,WAAK,sBAAsB,QAAQ;AACrC,QAAI,QAAQ,oBAAoB;AAC9B,WAAK,kBAAkB,QAAQ;AACjC,QAAI,QAAQ,iBAAiB;AAC3B,WAAK,eAAe,QAAQ;AAC9B,QAAI,QAAQ,aAAa,OAAW,MAAK,WAAW,QAAQ;AAC5D,QAAI,QAAQ,WAAW,OAAW,MAAK,SAAS,QAAQ;AACxD,QAAI,QAAQ,aAAa,OAAW,MAAK,WAAW,QAAQ;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAiC;AAC/B,QAAI,CAAC,KAAK,aAAc,QAAO,CAAA;AAC/B,QAAI;AACF,aAAO,KAAK,MAAM,KAAK,YAAY;AAAA,IACrC,QAAQ;AACN,aAAO,CAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,OAA4B;AAC1C,SAAK,eAAe,KAAK,UAAU,KAAK;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,MAA4B;AAClC,WAAO,KAAK,kBAAkB,SAAS,IAAI;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,cAAuB;AACrB,WAAO,KAAK,QAAQ,YAAY,SAAS;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAyB;AACvB,WAAO,KAAK,QAAQ,YAAY,WAAW;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,aAAsB;AACpB,WAAO,KAAK,QAAQ,YAAY,QAAQ;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,WAAoB;AAClB,WAAO,KAAK,WAAW,cAAc;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,YAAqB;AACnB,WAAO,KAAK,WAAW,cAAc;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,cAAuB;AACrB,WAAO,KAAK,WAAW,cAAc;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA,EAKA,YAAqB;AACnB,WAAO,CAAC,CAAC,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,cAAuB;AACrB,WAAO,CAAC,CAAC,KAAK;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA,EAKA,cAAuC;AACrC,QAAI,CAAC,KAAK,SAAU,QAAO,CAAA;AAC3B,QAAI;AACF,aAAO,KAAK,MAAM,KAAK,QAAQ;AAAA,IACjC,QAAQ;AACN,aAAO,CAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,MAAqC;AAC/C,SAAK,WAAW,KAAK,UAAU,IAAI;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,wBAAgC;AAC9B,QAAI,KAAK,mBAAmB,KAAK,wBAAwB,GAAG;AAC1D,aAAO,KAAK,uBAAuB,IAAI,KAAK;AAAA,IAC9C;AACA,WAAO,KAAK;AAAA,EACd;AACF;AA1NEA,kBAAA;AAAA,EADC,gBAAgB,sCAAsC;AAAA,GAJ5C,QAKX,WAAA,aAAA,CAAA;AAOAA,kBAAA;AAAA,EADC,gBAAgB,yCAAyC;AAAA,GAX/C,QAYX,WAAA,cAAA,CAAA;AAaAA,kBAAA;AAAA,EADC,WAAW,SAAS;AAAA,GAxBV,QAyBX,WAAA,mBAAA,CAAA;AAOAA,kBAAA;AAAA,EADC,WAAW,SAAS;AAAA,GA/BV,QAgCX,WAAA,gBAAA,CAAA;AAhCW,UAANA,kBAAA;AAAA,EALN,KAAK;AAAA,IACJ,KAAK,EAAE,SAAS,CAAC,QAAQ,OAAO,UAAU,QAAQ,EAAA;AAAA,IAClD,KAAK,EAAE,SAAS,CAAC,QAAQ,OAAO,QAAQ,EAAA;AAAA,IACxC,KAAK;AAAA,EAAA,CACN;AAAA,GACY,OAAA;ACvEN,MAAM,0BAA0B,eAAwB;AAAA,EAC7D,OAAgB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ7B,MAAM,cAAc,WAAuC;AACzD,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,UAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,eAAe,YAA6C;AAChE,UAAM,UAAU,MAAM,KAAK,KAAK;AAAA,MAC9B,OAAO,EAAE,WAAA;AAAA,MACT,OAAO;AAAA,IAAA,CACR;AACD,WAAO,QAAQ,CAAC,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aAAa,iBAA6C;AAC9D,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,gBAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,eAAe,cAA0C;AAC7D,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,aAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aAAa,QAA2C;AAC5D,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,OAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAiC;AACrC,WAAO,MAAM,KAAK,aAAa,cAAc,MAAM;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAkC;AACtC,WAAO,MAAM,KAAK,aAAa,cAAc,OAAO;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAoC;AACxC,WAAO,MAAM,KAAK,aAAa,cAAc,SAAS;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,WAAW,MAAuC;AACtD,UAAM,MAAM,MAAM,KAAK,KAAK,CAAA,CAAE;AAC9B,WAAO,IAAI,OAAO,CAAC,YAAY,QAAQ,QAAQ,IAAI,CAAC;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAqC;AACzC,WAAO,MAAM,KAAK,WAAW,YAAY,SAAS;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBAAsC;AAC1C,WAAO,MAAM,KAAK,WAAW,YAAY,WAAW;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAoC;AACxC,WAAO,MAAM,KAAK,WAAW,YAAY,QAAQ;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,uBAA2C;AAC/C,UAAM,aAAa,MAAM,KAAK,eAAA;AAC9B,WAAO,WAAW,OAAO,CAAC,MAAM,EAAE,UAAU;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,qBAAqB,YAA6C;AACtE,UAAM,UAAU,MAAM,KAAK,eAAe,UAAU;AACpD,QAAI,SAAS,SAAA,KAAc,QAAQ,eAAe;AAChD,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,wBAA4C;AAChD,UAAM,SAAS,MAAM,KAAK,WAAA;AAG1B,WAAO;AAAA,EACT;AACF;;;;;;;;;;;AC5FO,IAAM,SAAN,cAAqB,WAAW;AAAA,EAKrC,YAAoB;AAAA;AAAA;AAAA;AAAA,EAKpB,kCAAwB,KAAA;AAAA;AAAA;AAAA;AAAA,EAKxB,gCAAsB,KAAA;AAAA;AAAA;AAAA;AAAA,EAKtB,kBAA0B;AAAA;AAAA;AAAA;AAAA,EAK1B,mBAA2B;AAAA;AAAA;AAAA;AAAA,EAK3B,gBAAwB;AAAA;AAAA;AAAA;AAAA,EAKxB,iBAAyB;AAAA;AAAA;AAAA;AAAA,EAKzB,mBAA2B;AAAA;AAAA;AAAA;AAAA;AAAA,EAM3B,cAAsB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMtB,WAAmB;AAAA,EAOnB,YAAoB;AAAA;AAAA;AAAA;AAAA,EAKpB,SAAuB,aAAa;AAAA;AAAA;AAAA;AAAA,EAKpC,mBAA2B;AAAA;AAAA;AAAA;AAAA,EAK3B,SAAsB;AAAA;AAAA;AAAA;AAAA,EAKtB,QAAgB;AAAA;AAAA;AAAA;AAAA,EAKhB,WAAmB;AAAA,EAEnB,YAAY,UAAyB,IAAI;AACvC,UAAM,OAAO;AACb,QAAI,QAAQ,cAAc,OAAW,MAAK,YAAY,QAAQ;AAC9D,QAAI,QAAQ,gBAAgB;AAC1B,WAAK,cAAc,QAAQ;AAC7B,QAAI,QAAQ,cAAc,OAAW,MAAK,YAAY,QAAQ;AAC9D,QAAI,QAAQ,oBAAoB;AAC9B,WAAK,kBAAkB,QAAQ;AACjC,QAAI,QAAQ,qBAAqB;AAC/B,WAAK,mBAAmB,QAAQ;AAClC,QAAI,QAAQ,kBAAkB;AAC5B,WAAK,gBAAgB,QAAQ;AAC/B,QAAI,QAAQ,mBAAmB;AAC7B,WAAK,iBAAiB,QAAQ;AAChC,QAAI,QAAQ,qBAAqB;AAC/B,WAAK,mBAAmB,QAAQ;AAClC,QAAI,QAAQ,gBAAgB;AAC1B,WAAK,cAAc,QAAQ;AAC7B,QAAI,QAAQ,aAAa,OAAW,MAAK,WAAW,QAAQ;AAC5D,QAAI,QAAQ,cAAc,OAAW,MAAK,YAAY,QAAQ;AAC9D,QAAI,QAAQ,WAAW,OAAW,MAAK,SAAS,QAAQ;AACxD,QAAI,QAAQ,qBAAqB;AAC/B,WAAK,mBAAmB,QAAQ;AAClC,QAAI,QAAQ,WAAW,OAAW,MAAK,SAAS,QAAQ;AACxD,QAAI,QAAQ,UAAU,OAAW,MAAK,QAAQ,QAAQ;AACtD,QAAI,QAAQ,aAAa,OAAW,MAAK,WAAW,QAAQ;AAAA,EAC9D;AAAA;AAAA;AAAA;AAAA,EAKA,YAAqB;AACnB,WAAO,KAAK,WAAW,aAAa;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,aAAsB;AACpB,WAAO,KAAK,WAAW,aAAa;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,eAAwB;AACtB,WAAO,KAAK,WAAW,aAAa;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,cAAuB;AACrB,WAAO,KAAK,WAAW,aAAa;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,WAAoB;AAClB,WAAO,KAAK,WAAW,aAAa;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,oBAA4B;AAC1B,WAAO,KAAK,cAAc;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA,EAKA,8BAAsC;AACpC,WAAO,KAAK,kBAAkB;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,+BAAuC;AACrC,WAAO,KAAK,mBAAmB;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,4BAAoC;AAClC,WAAO,KAAK,gBAAgB;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA,EAKA,6BAAqC;AACnC,WAAO,KAAK,iBAAiB;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,+BAAuC;AACrC,WAAO,KAAK,mBAAmB;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAyB;AACvB,WACE,KAAK,kBACL,KAAK,mBACL,KAAK,gBACL,KAAK,iBACL,KAAK;AAAA,EAET;AAAA;AAAA;AAAA;AAAA,EAKA,kBAA0B;AACxB,UAAM,QAAQ,KAAK,YAAY,YAAA,EAAc,MAAM,GAAG,EAAE,CAAC;AACzD,UAAM,MAAM,KAAK,UAAU,YAAA,EAAc,MAAM,GAAG,EAAE,CAAC;AACrD,WAAO,GAAG,KAAK,OAAO,GAAG;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,cAAuC;AACrC,QAAI,CAAC,KAAK,SAAU,QAAO,CAAA;AAC3B,QAAI;AACF,aAAO,KAAK,MAAM,KAAK,QAAQ;AAAA,IACjC,QAAQ;AACN,aAAO,CAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,MAAqC;AAC/C,SAAK,WAAW,KAAK,UAAU,IAAI;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,UAAgB;AACd,QAAI,KAAK,WAAW,aAAa,SAAS;AACxC,YAAM,IAAI;AAAA,QACR,sCAAsC,KAAK,MAAM;AAAA,MAAA;AAAA,IAErD;AACA,SAAK,SAAS,aAAa;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,iBAAuB;AACrB,QAAI,KAAK,WAAW,aAAa,UAAU;AACzC,YAAM,IAAI;AAAA,QACR,iDAAiD,KAAK,MAAM;AAAA,MAAA;AAAA,IAEhE;AACA,SAAK,SAAS,aAAa;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,SAAS,kBAAgC;AACvC,QAAI,KAAK,WAAW,aAAa,YAAY;AAC3C,YAAM,IAAI;AAAA,QACR,uCAAuC,KAAK,MAAM;AAAA,MAAA;AAAA,IAEtD;AACA,SAAK,SAAS,aAAa;AAC3B,SAAK,mBAAmB;AACxB,SAAK,6BAAa,KAAA;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,KAAK,QAAsB;AACzB,QACE,KAAK,WAAW,aAAa,YAC7B,KAAK,WAAW,aAAa,YAC7B;AACA,YAAM,IAAI;AAAA,QACR,mCAAmC,KAAK,MAAM;AAAA,MAAA;AAAA,IAElD;AACA,SAAK,SAAS,aAAa;AAC3B,SAAK,QAAQ;AAAA,EACf;AACF;AArSE,gBAAA;AAAA,EADC,WAAW,SAAS;AAAA,GAJV,OAKX,WAAA,aAAA,CAAA;AAsDA,gBAAA;AAAA,EADC,gBAAgB,sCAAsC;AAAA,GA1D5C,OA2DX,WAAA,aAAA,CAAA;AA3DW,SAAN,gBAAA;AAAA,EALN,KAAK;AAAA,IACJ,KAAK,EAAE,SAAS,CAAC,QAAQ,OAAO,UAAU,QAAQ,EAAA;AAAA,IAClD,KAAK,EAAE,SAAS,CAAC,QAAQ,OAAO,QAAQ,EAAA;AAAA,IACxC,KAAK;AAAA,EAAA,CACN;AAAA,GACY,MAAA;AChEN,MAAM,yBAAyB,eAAuB;AAAA,EAC3D,OAAgB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ7B,MAAM,cAAc,WAAsC;AACxD,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,UAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,aAAa,QAAyC;AAC1D,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,OAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAiC;AACrC,WAAO,MAAM,KAAK,aAAa,aAAa,OAAO;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAkC;AACtC,WAAO,MAAM,KAAK,aAAa,aAAa,QAAQ;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAAoC;AACxC,WAAO,MAAM,KAAK,aAAa,aAAa,UAAU;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBAAmC;AACvC,WAAO,MAAM,KAAK,aAAa,aAAa,SAAS;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAgC;AACpC,WAAO,MAAM,KAAK,aAAa,aAAa,MAAM;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,cAAc,WAAsC;AACxD,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,UAAA;AAAA,MACT,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,aAAa,OAAa,KAA8B;AAC5D,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO;AAAA,QACL,mBAAmB,MAAM,YAAA;AAAA,QACzB,iBAAiB,IAAI,YAAA;AAAA,MAAY;AAAA,MAEnC,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,uBACJ,WACA,QACmB;AACnB,WAAO,MAAM,KAAK,KAAK;AAAA,MACrB,OAAO,EAAE,WAAW,OAAA;AAAA,MACpB,SAAS;AAAA,IAAA,CACV;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,qBAAqB,WAAsC;AAC/D,WAAO,MAAM,KAAK,uBAAuB,WAAW,aAAa,OAAO;AAAA,EAC1E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,uBAAuB,WAAsC;AACjE,WAAO,MAAM,KAAK,uBAAuB,WAAW,aAAa,SAAS;AAAA,EAC5E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,iBAAiB,WAAoC;AACzD,UAAM,YAAY,MAAM,KAAK,uBAAuB,SAAS;AAC7D,WAAO,UAAU,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,aAAa,CAAC;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,oBAAoB,WAAoC;AAC5D,UAAM,UAAU,MAAM,KAAK,qBAAqB,SAAS;AACzD,WAAO,QAAQ,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,aAAa,CAAC;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,oBAAoB,WAA2C;AACnE,UAAM,UAAU,MAAM,KAAK,KAAK;AAAA,MAC9B,OAAO,EAAE,UAAA;AAAA,MACT,SAAS;AAAA,MACT,OAAO;AAAA,IAAA,CACR;AACD,WAAO,QAAQ,CAAC,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,WAQH;AACD,UAAM,MAAM,MAAM,KAAK,KAAK,CAAA,CAAE;AAE9B,UAAM,QAAQ;AAAA,MACZ,SAAS;AAAA,MACT,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,cAAc;AAAA,IAAA;AAGhB,eAAW,KAAK,KAAK;AACnB,cAAQ,EAAE,QAAA;AAAA,QACR,KAAK,aAAa;AAChB,gBAAM;AACN,gBAAM,gBAAgB,EAAE;AACxB;AAAA,QACF,KAAK,aAAa;AAChB,gBAAM;AACN,gBAAM,gBAAgB,EAAE;AACxB;AAAA,QACF,KAAK,aAAa;AAChB,gBAAM;AACN;AAAA,QACF,KAAK,aAAa;AAChB,gBAAM;AACN,gBAAM,aAAa,EAAE;AACrB;AAAA,QACF,KAAK,aAAa;AAChB,gBAAM;AACN;AAAA,MAAA;AAAA,IAEN;AAEA,WAAO;AAAA,EACT;AACF;"}
|
package/dist/manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "1.0.0",
|
|
3
|
-
"timestamp":
|
|
3
|
+
"timestamp": 1782335230685,
|
|
4
4
|
"packageName": "@happyvertical/smrt-affiliates",
|
|
5
|
-
"packageVersion": "0.
|
|
5
|
+
"packageVersion": "0.35.1",
|
|
6
6
|
"objects": {
|
|
7
7
|
"@happyvertical/smrt-affiliates:CommissionCollection": {
|
|
8
8
|
"name": "commissioncollection",
|
|
@@ -1012,7 +1012,7 @@
|
|
|
1012
1012
|
"name": "getMetadata",
|
|
1013
1013
|
"async": false,
|
|
1014
1014
|
"parameters": [],
|
|
1015
|
-
"returnType": "Record<string
|
|
1015
|
+
"returnType": "Record<string>",
|
|
1016
1016
|
"isStatic": false,
|
|
1017
1017
|
"isPublic": true
|
|
1018
1018
|
},
|
|
@@ -1022,7 +1022,7 @@
|
|
|
1022
1022
|
"parameters": [
|
|
1023
1023
|
{
|
|
1024
1024
|
"name": "data",
|
|
1025
|
-
"type": "Record<string
|
|
1025
|
+
"type": "Record<string>",
|
|
1026
1026
|
"optional": false
|
|
1027
1027
|
}
|
|
1028
1028
|
],
|
|
@@ -1362,7 +1362,7 @@
|
|
|
1362
1362
|
"name": "getMetadata",
|
|
1363
1363
|
"async": false,
|
|
1364
1364
|
"parameters": [],
|
|
1365
|
-
"returnType": "Record<string
|
|
1365
|
+
"returnType": "Record<string>",
|
|
1366
1366
|
"isStatic": false,
|
|
1367
1367
|
"isPublic": true
|
|
1368
1368
|
},
|
|
@@ -1372,7 +1372,7 @@
|
|
|
1372
1372
|
"parameters": [
|
|
1373
1373
|
{
|
|
1374
1374
|
"name": "data",
|
|
1375
|
-
"type": "Record<string
|
|
1375
|
+
"type": "Record<string>",
|
|
1376
1376
|
"optional": false
|
|
1377
1377
|
}
|
|
1378
1378
|
],
|
|
@@ -1735,7 +1735,7 @@
|
|
|
1735
1735
|
"name": "getMetadata",
|
|
1736
1736
|
"async": false,
|
|
1737
1737
|
"parameters": [],
|
|
1738
|
-
"returnType": "Record<string
|
|
1738
|
+
"returnType": "Record<string>",
|
|
1739
1739
|
"isStatic": false,
|
|
1740
1740
|
"isPublic": true
|
|
1741
1741
|
},
|
|
@@ -1745,7 +1745,7 @@
|
|
|
1745
1745
|
"parameters": [
|
|
1746
1746
|
{
|
|
1747
1747
|
"name": "data",
|
|
1748
|
-
"type": "Record<string
|
|
1748
|
+
"type": "Record<string>",
|
|
1749
1749
|
"optional": false
|
|
1750
1750
|
}
|
|
1751
1751
|
],
|
package/dist/smrt-knowledge.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"generatedAt": "2026-06-
|
|
3
|
+
"generatedAt": "2026-06-24T21:07:11.883Z",
|
|
4
4
|
"packageName": "@happyvertical/smrt-affiliates",
|
|
5
|
-
"packageVersion": "0.
|
|
5
|
+
"packageVersion": "0.35.1",
|
|
6
6
|
"sourceManifestPath": "dist/manifest.json",
|
|
7
7
|
"agentDocPath": "AGENTS.md",
|
|
8
8
|
"sourceHashes": {
|
|
9
|
-
"manifest": "
|
|
10
|
-
"packageJson": "
|
|
9
|
+
"manifest": "12e87f633e10ba99319dadf4f0160254fbc0d4326a9ec58a82f7f64a90133afe",
|
|
10
|
+
"packageJson": "b6290881e8fc30491d63b18123c5831cbaab9b4c32c467a078fdb22066c7db2e",
|
|
11
11
|
"agents": "402004f8c7cbaed180ca4f81673883002b64aab2700648ae31cfa372ee9ca1b6"
|
|
12
12
|
},
|
|
13
13
|
"exports": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@happyvertical/smrt-affiliates",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.35.1",
|
|
4
4
|
"description": "Affiliate partner and commission tracking models for SMRT framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"./manifest.json": "./dist/manifest.json"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@happyvertical/smrt-core": "0.
|
|
22
|
+
"@happyvertical/smrt-core": "0.35.1"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@happyvertical/sql": "^0.74.7",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"typescript": "^5.9.3",
|
|
29
29
|
"vite": "^7.3.1",
|
|
30
30
|
"vitest": "^4.0.17",
|
|
31
|
-
"@happyvertical/smrt-vitest": "0.
|
|
31
|
+
"@happyvertical/smrt-vitest": "0.35.1"
|
|
32
32
|
},
|
|
33
33
|
"keywords": [
|
|
34
34
|
"smrt",
|