Skip to content

Commit 5d85535

Browse files
committed
RE1-T117 PR#415 fixes
1 parent 8c7da0e commit 5d85535

2 files changed

Lines changed: 22 additions & 0 deletions

File tree

Core/Resgrid.Services/SubscriptionsService.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,12 @@ public async Task<double> GetAdjustedUpgradePriceAsync(int paymentId, int planId
620620
var payment = await GetPaymentByIdAsync(paymentId);
621621
var plan = await GetPlanByIdAsync(planId);
622622

623+
// Sometimes the payment comes back without its Plan navigation populated; hydrate it from PlanId
624+
// before giving up, mirroring GetCurrentPaymentForDepartmentAsync, so a valid payment with a
625+
// missing navigation can still be priced rather than failing immediately.
626+
if (payment != null && payment.Plan == null)
627+
payment.Plan = await GetPlanByIdAsync(payment.PlanId);
628+
623629
// GetPaymentByIdAsync/GetPlanByIdAsync return null when the Billing API is unavailable or the id
624630
// isn't found. Every branch below dereferences payment, payment.Plan and plan and returns a price;
625631
// silently returning 0 would mean a free upgrade, so fail loud rather than bill an outage-derived $0.

Web/Resgrid.Web/Areas/User/Controllers/SubscriptionController.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,11 @@ public async Task<IActionResult> BuyAddon(string planAddonId)
592592
{
593593
var model = new BuyAddonView();
594594
model.PlanAddon = await _subscriptionsService.GetPlanAddonByIdAsync(planAddonId);
595+
// GetPlanAddonByIdAsync returns null when the add-on id isn't found (or the Billing API is
596+
// unavailable). Bail before dereferencing model.PlanAddon below (PlanAddonId / AddonType / PlanId).
597+
if (model.PlanAddon == null)
598+
return NotFound();
599+
595600
model.PlanAddonId = model.PlanAddon.PlanAddonId;
596601
model.Department = await _departmentsService.GetDepartmentByIdAsync(DepartmentId);
597602
var addonTypes = await _subscriptionsService.GetAllAddonPlansAsync();
@@ -620,6 +625,12 @@ public async Task<IActionResult> ManagePTTAddon()
620625
{
621626
var model = new BuyAddonView();
622627
model.PlanAddon = await _subscriptionsService.GetPlanAddonByIdAsync("6f4c5f8b-584d-4291-8a7d-29bf97ae6aa9");
628+
// GetPlanAddonByIdAsync returns null when the Billing API is unavailable / the add-on isn't found.
629+
// The id here is hardcoded (a known product), so a null means a server/billing problem, not a bad
630+
// request — surface a 500 instead of NRE'ing on model.PlanAddon below.
631+
if (model.PlanAddon == null)
632+
return StatusCode(StatusCodes.Status500InternalServerError, "Unable to load the PTT add-on. Please try again.");
633+
623634
model.PlanAddonId = model.PlanAddon.PlanAddonId;
624635
model.Department = await _departmentsService.GetDepartmentByIdAsync(DepartmentId);
625636

@@ -775,6 +786,11 @@ public async Task<IActionResult> GetStripeSession(int id, int count, string disc
775786
var department = await _departmentsService.GetDepartmentByIdAsync(DepartmentId);
776787
var user = _usersService.GetUserById(UserId);
777788
var session = await _subscriptionsService.CreateStripeSessionForSub(DepartmentId, stripeCustomerId, plan.GetExternalKey(), plan.PlanId, user.Email, department.Name, count, discountCode);
789+
// CreateStripeSessionForSub returns null when the Billing API is unavailable / Stripe session
790+
// creation fails. Fail with a clear error instead of NRE'ing on session.CustomerId/SessionId below.
791+
if (session == null)
792+
return StatusCode(StatusCodes.Status500InternalServerError, "Unable to start the checkout session. Please try again.");
793+
778794
var subscription = await _subscriptionsService.GetActiveStripeSubscriptionAsync(session.CustomerId);
779795

780796
bool hasActiveSub = false;

0 commit comments

Comments
 (0)