Add math calculator. Revise Rateable interface#4
Open
akDeveloper wants to merge 20 commits into
Open
Conversation
Resolved Issues:
- Null Pointer Risk in receivePayment()
Fixed by adding null coalescing assignment to initialize paidThrough
if null before modification: $this->paidThrough ??= new DateTime('today');
- DateTime Mutation in receivePayment() (Removed)
Determined to be working as designed - mutation is intentional with DateTime
Add defensive null check for paidThrough in getRemainingDays() method. Returns 0 for free plans which don't have a paidThrough date, preventing null pointer exceptions when calculating remaining days.
- Add status reset to ACTIVE in receivePayment() method When a subscription receives payment, the status is now properly reset to ACTIVE, fixing the issue where subscriptions remained in PAST_DUE status after successful payment recovery. - Fix DateTime mutation in expireAfterGrace() method Cloned the DateTime object before modification to prevent unintended side effects on the paidThrough date when calculating grace period. - Fix coupon sorting inconsistency Replaced incomplete comparison with spaceship operator (<=>) to ensure stable and deterministic sorting when multiple coupons have the same discount value. - Fix null return type in Freemium::getExpiredPlan() Updated return type annotation to ?SubscriptionPlan to accurately reflect that the method can return null.
- Fix potential division by zero in CreditRemainingValueCalculator Added check for zero daily rate before division to prevent fatal error when calculating credit for plan changes involving free plans. When daily rate is zero, the paidThrough date is set to today and the calculation is skipped. - Add validation in setSubscriptionPlan() to prevent unnecessary changes Skip plan change processing if the new plan is the same as the current plan, preventing unnecessary audit trail entries and subscription change records.
abf8062 to
30212d0
Compare
… usage - Add Subscription::$daysTrial and $daysGrace (default 0) with getters; use in expireAfterGrace() and NewPaidSubscriptionCalculator - Set status to CANCELED (not PAST_DUE) in Subscription::expireNow(); add getStatus() - Introduce GatewayFactory::getGatewayFor(Subscribable); inject into ChargeSubscriptionHandler and StoreCreditCardHandler - Add daysTrial and daysGrace to NewSubscription command; NewSubscriptionHandler passes them into Subscription constructor - Remove Freemium::$daysGrace, $daysFreeTrial, and getGateway() usage from domain and handlers; tests use BogusGatewayFactory and assert CANCELED on expiration
…er errors, drop Freemium - Subscription: per-subscription daysTrial and daysGrace (default 0), getStatus(); expireNow() sets CANCELED; NewPaidSubscriptionCalculator uses getDaysTrial() - GatewayFactory::getGatewayFor(Subscribable); ChargeSubscriptionHandler and StoreCreditCardHandler use it instead of Freemium::getGateway() - NewSubscription command and handler: daysTrial and daysGrace from command - TrialEligibilityChecker and NewSubscriptionHandler: when daysTrial > 0, require eligibility or throw; SubscriptionRepository::hasCompletedOrUsedTrial(Subscribable, SubscriptionPlan) - Exceptions include subscription token and customer id in ChargeSubscriptionHandler, StoreCreditCardHandler, and Subscription - Remove Freemium.php; document trial/grace and gateway in TECHNICAL.md - Tests: BogusGatewayFactory, AlwaysEligibleTrialChecker, RepositoryTrialEligibilityChecker, CANCELED on expiration, trial eligible/not-eligible, simple exception message assert
- Make Subscription::remainingAmount() use original plan rate (or zero when no original plan) - Convert remaining value to new-plan days via CreditRemainingValueCalculator using new plan’s daily rate - Add regressions for premium↔basic plan changes and strengthen ChangePlanHandlerTest assertions - Update tests that used remainingAmount() outside plan-change flow to expect zero in new-subscription cases - Clean up ISSUES.md discussion points (remove null-handling concern; mark credit calculation clarified)
…llections - Migrate all DateTime to DateTimeImmutable across domain and tests - Introduce Larium state machine for subscription status (pay, past_due, cancel) - Rename expireNow→cancel, expireAfterGrace→markPastDue, isExpired→isCancellationDue - Rename $expireOn→$cancelAt, getExpireOn→getCancelAt - Remove Subscription::$transactions; handler manages via TransactionRepository - Remove Subscription::$subscriptionChanges; setSubscriptionPlan returns ?SubscriptionChange - Remove Subscription::$couponRedemptions; billingAmount(?Coupon), ApplyCouponHandler - Remove Coupon::$subscriptionPlans; appliesToPlan(SubscriptionPlan, array $applicablePlans) - Remove Coupon::$couponRedemptions; hasExpired(int $redemptionCount) - Add SubscriptionChangeRepository, CouponRedemptionRepository, CouponPlanRepository - Fix fixtures DateTimeImmutable use-statement warning
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.