Skip to content

Releases: Foysal50x/tashil

v1.1.0-beta

05 Jun 20:23

Choose a tag to compare

v1.1.0-beta Pre-release
Pre-release

Adds a host-reported transaction ledger, an invoice/transaction read API, and a gateway-scoping fix for generated transaction ids. Tashil still never moves money — it records what the host's gateway reports.

Added

  • Transaction ledger API on Tashil::billing():
    • recordPayment($invoice, …) — writes a success transaction and settles the invoice in one DB transaction (routes through InvoiceObserver → activate / advancePeriod / reactivate). Idempotent on UNIQUE(gateway, transaction_id), so replayed at-least-once webhooks never double-settle.
    • recordFailedPayment($invoice, …) — writes a failed transaction; leaves the invoice Pending for dunning.
    • recordRefund($transaction, …) — accumulates refunded_amount (partials supported); a full refund flips the transaction and invoice to Refunded.
  • TransactionRepositoryInterface + EloquentTransactionRepository — the ledger sits behind an overridable repository like every other persistence concern.
  • Events PaymentRecorded, PaymentFailed, PaymentRefunded — carry the transaction + invoice, dispatched after commit.
  • Invoice::markAsRefunded() / Invoice::isRefunded(), plus a gateway_response array cast on Transaction.
  • Invoice/transaction read APIlatestInvoice($sub, ?InvoiceKind), pendingInvoice($sub), overdueInvoice($sub), successfulTransaction($invoice) — read through the (overridable) repository instead of querying the Invoice model directly. Read paths are uncached (per-subscription invoices change on every payment/dunning step).

Changed

  • Cookbook examples now use the ledger API instead of hand-written Transaction::create() + markAsPaid(); added a RefundController example. CheckoutController / TrialController / SuspensionController read invoices via the billing API. Docs (package + website) cover the ledger, refunds, and read API.

Fixed

  • TransactionIdGenerator uniqueness is now scoped to the gateway — it takes the row's gateway via a constructor argument (passed by TransactionObserver) and checks the composite (gateway, transaction_id), matching the DB constraint. The old global check wrongly rejected an id already used under a different gateway; the same id can legitimately exist per gateway.

Full Changelog: v1.0.0-beta...v1.1.0-beta

v1.0.0-beta

05 Jun 12:35

Choose a tag to compare

v1.0.0-beta Pre-release
Pre-release

First public beta of Tashil — subscription + feature management for Laravel.

Tashil owns the plan catalog, subscription state, feature gating, atomic usage counters, trial lifecycle, invoice issuance, and the activate → renew → dunning → reactivate state machine with proration on in-place plan changes. It does not move money — payment capture, dunning retry charges, refunds, gateway sync, and wallet balances are delegated to the host app.

Highlights

  • Plan catalog — fluent builders; 5 feature types (Boolean, Limit, Consumable, Enum, Metered).
  • Lifecycle — subscribe, grace/immediate cancel, resume, pause (banks time), switchPlan, in-place prorated changePlan, deferred scheduleDowngrade.
  • Activation gating — priced plans start Pending (no access) → activate() on first paid invoice; free plans go straight Active.
  • Trials — strict isOnTrial(), host-triggered convertTrial() anchoring the first paid period, scheduled warning/expiry jobs.
  • Dunning — bounded Active → PastDue → Suspended → Expired state machine (host performs the charge).
  • Atomic usage — conditional-UPDATE limit increments (no over-limit races), absolute reportStorage, once-per-period 80% warning, period-anchored resets.
  • Metered billing — per-unit charges via host MeteredBilling (self-impl or container), charge-before-write, caller-supplied idempotency keys.
  • Immutable event log — monotonic per-subscription sequence_num under row lock, idempotency keys, paginated read API.
  • Analytics — MRR, churn rate + trend, trial conversion, revenue, dashboard (cross-DB, no raw SQL).
  • Subscribable trait + middleware + Blade directives with one overridable resolver.
  • Six idempotent scheduled commands, auto-registered, version-agnostic across Laravel 10–13.

Requirements

  • PHP 8.2 – 8.5
  • Laravel 10.x / 11.x / 12.x / 13.x
  • Redis (optional, only with the caching layer)

Install

```bash
composer require foysal50x/tashil:^1.0.0-beta
```

Quality

363 tests / 1067 assertions, green on SQLite, MySQL 8, and PostgreSQL 16.

Beta: the public API is feature-complete but subject to refinement before `1.0.0` stable.

See the CHANGELOG for the full list.