Skip to content

Releases: a2zwebltd/laravel-affiliate

v1.1.2 — Eligibility-to-apply notification + attribution fix

01 May 09:39

Choose a tag to compare

Highlights

  • New PartnerEligibleToApply notification — emails the user the moment they cross affiliate.min_referred_users and don't already have an open application. Links to /dashboard/affiliate so they can apply, accept terms, and provide payout details.
  • affiliate:notify-eligible backfill 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 fixReferralAttributor::captureFromRequest and ::attributeNewUser now attribute referrals when the partner is STATUS_PENDING or STATUS_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 --force

Tests

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

30 Apr 10:58

Choose a tag to compare

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

30 Apr 10:58

Choose a tag to compare

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; NullRevenueResolver returns 0.
  • current_month_running_cents — new key on the PartnerStatistics::for() payload. Partner's current effectiveRevenueShareBp() 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_cents continues 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 RevenueResolver implementation in your app must implement the new method. Return 0 to opt out of the live KPI.

v1.0.2 — Per-referral 12mo earnings net of adjustments

30 Apr 10:58

Choose a tag to compare

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

30 Apr 07:19

Choose a tag to compare

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 on affiliate_commissions and affiliate_adjustments exceeded the limit and broke migrate on MySQL.

Full Changelog: v1.0.0...v1.0.1

v1.0.0

30 Apr 06:38

Choose a tag to compare

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, AffiliateTermsAcceptance models with 13 timestamped migrations.
  • Opt-in partner workflow: application form, terms acceptance, eligibility check (EligibilityChecker), affiliate code generation (AffiliateCodeGenerator).
  • Referral attribution via CaptureAffiliateReferral middleware and the HasAffiliateProgram model concern, with cookie-based attribution and pluggable resolvers.
  • Pluggable contracts: RevenueResolver (your billing source of truth) and ReferredUserInfoResolver (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 via barryvdh/laravel-dompdf.
  • Admin adjustments via AffiliateAdjustment, including commission_rate_bp overrides 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/nova is installed.
  • Optional Livewire layer (auto-registered only when livewire/livewire is 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) and affiliate_statements.php (issuing entity snapshot, PDF settings).
  • Translation scaffolding under resources/lang/.