Releases: a2zwebltd/laravel-affiliate
v1.1.2 — Eligibility-to-apply notification + attribution fix
Highlights
- New
PartnerEligibleToApplynotification — emails the user the moment they crossaffiliate.min_referred_usersand don't already have an open application. Links to/dashboard/affiliateso they can apply, accept terms, and provide payout details. affiliate:notify-eligiblebackfill command — one-shot, mails every user who is currently eligible at upgrade time. Supports--dry-run(lists recipients without sending) and--force(skips the confirm prompt).- Attribution filter fix —
ReferralAttributor::captureFromRequestand::attributeNewUsernow attribute referrals when the partner isSTATUS_PENDINGorSTATUS_APPROVED, instead of approved-only. This unblocks the documented flow where a user shares their link via the share-only stub (STATUS_PENDING + applied_at=null) to gather referrals before applying. Rejected and suspended codes are still ignored.
Behaviour
The notification fires from both attributeNewUser (cookie / query attribution at signup) and manuallyAttach (admin tool). The trigger compares the partner's referred-count before and after the new AffiliateReferral::create() and only fires on the crossing — repeat referrals after the threshold do not re-email. Last-touch swaps notify the new partner-of-record when the swap puts them at or past the threshold.
Upgrade
composer update a2zwebltd/laravel-affiliate. No migrations.
After deploying, optionally run:
php artisan affiliate:notify-eligible --dry-run
php artisan affiliate:notify-eligible --forceTests
PartnerEligibilityNotificationTest (4 cases) and NotifyEligiblePartnersCommandTest (2 cases). Full pest suite: 37 passed.
v1.1.1 — Partner-specific revenue share in hero, drop in-progress badge
Two small dashboard polish items.
Changed
- Hero headline "Earn :pct% lifetime revenue share" now reads from the partner's
effectiveRevenueShareBp()(with the package config default as fallback). Partners on custom rates now see their own percentage instead of the global default. - Removed the redundant "in progress" pill on the "Current month so far" KPI — the "not yet closed" caption already conveys it.
v1.1.0 — Current-month running commission KPI
Adds an in-progress current-month commission estimate to the partner dashboard, alongside fully-closed historical periods.
New
RevenueResolver::currentMonthRunningRevenueCents(int $userId): int— returns running source revenue from month start to now. Existing implementations must add this method;NullRevenueResolverreturns 0.current_month_running_cents— new key on thePartnerStatistics::for()payload. Partner's currenteffectiveRevenueShareBp()is applied (correct for an unclosed month — there is no historical rate yet).monthly[*].is_current— new bool flag on chart entries; true for the in-progress current month, false for closed periods.- Dashboard view — "Current month so far" KPI tile and a greyed in-progress bar at the right edge of the earnings chart.
total_earned_centscontinues to reflect only fully-closed periods.
Migration notes
- Stats cache key bumped to
:stats:v2— old v1 payloads are ignored on upgrade, no manual cache clear needed. - Interface change: any custom
RevenueResolverimplementation in your app must implement the new method. Return0to opt out of the live KPI.
v1.0.2 — Per-referral 12mo earnings net of adjustments
Fixes per-referral "Earned (12 mo)" column so it reconciles with the partner-level "Total earned" tile.
What changed
- Per-referral 12mo earnings are now net of attributable adjustments (previously gross only). Each (year, month) adjustment is distributed across that month's referrals proportionally to each referral's share of the month's gross commission.
- Adjustments in months where no commissions exist remain at the partner level (cannot be attributed to a specific referral) and only affect
total_earned_cents. - Per-referral display caps at zero (the partner-level tile still reflects negatives).
Historical fidelity
Aggregations always use stored affiliate_commissions.commission_amount_cents and the row-snapshotted affiliate_adjustments.commission_rate_bp via AffiliateAdjustment::commissionAmountCents(). The partner's current revenue_share_bp is never used in historical totals — pinned by a regression test that mutates the partner's current rate and asserts identical output.
Tests
tests/Feature/PartnerStatisticsAdjustmentsTest.php covers distribution and the no-commissions edge case. tests/Feature/PartnerStatisticsHistoricalRatesTest.php covers historical-rate fidelity.
v1.0.1
Fixes
- Name all migration indexes explicitly so they stay under the MySQL 64-character identifier limit. The auto-generated names for the compound
[partner_user_id, period_year, period_month]indexes onaffiliate_commissionsandaffiliate_adjustmentsexceeded the limit and brokemigrateon MySQL.
Full Changelog: v1.0.0...v1.0.1
v1.0.0
Changelog
All notable changes to a2zwebltd/laravel-affiliate will be documented in this file.
[1.0.0] - 2026-04-30
Added
- Engine:
AffiliatePartner,AffiliateReferral,AffiliateCommission,AffiliateCommissionStatement,AffiliateCommissionStatementLine,AffiliateAdjustment,AffiliatePayoutRequest,AffiliateTermsAcceptancemodels with 13 timestamped migrations. - Opt-in partner workflow: application form, terms acceptance, eligibility check (
EligibilityChecker), affiliate code generation (AffiliateCodeGenerator). - Referral attribution via
CaptureAffiliateReferralmiddleware and theHasAffiliateProgrammodel concern, with cookie-based attribution and pluggable resolvers. - Pluggable contracts:
RevenueResolver(your billing source of truth) andReferredUserInfoResolver(display data for the partner dashboard), with null defaults shipped. - Monthly commission closure (
CloseMonthCommand,MonthlyCloser,CommissionCalculator) producing immutable statements that snapshot partner billing and rates at issue time. - Commission statement generation (
CommissionStatementGenerator,CommissionStatementIssuer,CommissionStatementPaymentRecorder,StatementNumberGenerator) with PDF export viabarryvdh/laravel-dompdf. - Admin adjustments via
AffiliateAdjustment, includingcommission_rate_bpoverrides per adjustment. - Partner-initiated payout requests with admin completion workflow (
PayoutRequestService,PayoutCompletionWorkflow). - Events:
ApplicationSubmitted,ApplicationApproved,ApplicationRejected,MonthClosed,StatementIssued,StatementCancelled,StatementPaid,PayoutRequested,PayoutApproved,PayoutPaid— with admin and partner notifications. - Blade + Alpine partner dashboard (routes opt-in via config) and supporting views: partner detail, statements list, payout request flow, emails.
- Optional Nova 5 layer: resources, actions, admin menu — registered automatically when
laravel/novais installed. - Optional Livewire layer (auto-registered only when
livewire/livewireis installed):PartnerDashboard,ApplicationForm,PayoutDetailsForm,PayoutRequestForm. - Artisan commands:
affiliate:close-month,affiliate:recalc-partner,affiliate:migrate-from-jijunair(legacy migration helper). - Auto-discovered service provider with publishable config, migrations, views, and translations.
- Two config files:
affiliate.php(engine, attribution, routes, defaults) andaffiliate_statements.php(issuing entity snapshot, PDF settings). - Translation scaffolding under
resources/lang/.