Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions app/app/Http/Controllers/MergedController.php
Original file line number Diff line number Diff line change
Expand Up @@ -375,14 +375,30 @@ public function dashboard(Request $request)
$checklist['added_billing_info'] = TRUE;
}

// Add metrics to API result
$today = date('Y-m-d');
$callsToday = Call::where('workspace_id', $workspace->id)
->whereDate('created_at', '=', $today)
->count();

$activeDIDs = DIDNumber::where('workspace_id', $workspace->id)->count();

$activeMembers = WorkspaceUser::where('workspace_id', $workspace->id)->count();

$metrics = [
'calls_today' => $callsToday,
'active_did_numbers' => $activeDIDs,
'active_members' => $activeMembers
];

return $this->response->array([
$graph,
$billing,
$self->toArray(TRUE),
$checklist,
$plan,
$workspace->toArrayWithRoles($user)
$workspace->toArrayWithRoles($user),
$metrics
]);
}

Expand Down Expand Up @@ -1015,7 +1031,6 @@ public function getServicePlans(Request $request) {
$trialInterval = new \DateInterval('P' . $trialDurationDays . 'D');

$nextMonthlyDateWithTrial = clone $currentDate;
$nextMonthlyDateWithTrial->add(new \DateInterval('P1M'));

// Handle date clamping for monthly
$originalDay = $currentDate->format('d');
Expand All @@ -1029,7 +1044,6 @@ public function getServicePlans(Request $request) {
$billingDates['next_monthly_billing_date_w_trial_formatted'] = $nextMonthlyDateWithTrial->format('M d, Y');

$nextAnnualDateWithTrial = clone $currentDate;
$nextAnnualDateWithTrial->add(new \DateInterval('P1Y'));

// Handle date clamping for annual (leap years)
$originalDay = $currentDate->format('d');
Expand Down
88 changes: 62 additions & 26 deletions app/app/Http/Controllers/RegisterController.php
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ public function userSpinup(Request $request)
'default_region' => $region->code
]);

$billingFlow = $customizations['billing_flow'];
Log::info('adding new user to SIP proxy database tables.');
$result = SIPRouterHelper::updateProxyToEnableWorkspace($user, $workspace, $info['proxy']);

Expand All @@ -247,37 +248,70 @@ public function userSpinup(Request $request)

$now = new DateTime();
$anchorDay = (int)$now->format('j');
$isTrial = false;

if ($customizations['is_trial_enabled'] && !$plan['free_trial_exempt']) {
$isTrial = TRUE;
}

if ($billingCycle === 'ANNUAL') {
$periodEnd = (clone $now)->modify('+1 year')->setTime(0,0,0);
$recurringCost = $plan->annual_cost_cents;
} else {
// FIXED: Look ahead to prevent native PHP +1 month edge-case rollover anomalies
$nextMonth = (clone $now)->modify('+1 month');
$daysInNextMonth = (int)$nextMonth->format('t');
$trialDurationDays = $customizations['trial_duration_days'];

if ($anchorDay > $daysInNextMonth) {
// Clamp period end to absolute upper bound of the target calendar block
$periodEnd = $nextMonth->setDate((int)$nextMonth->format('Y'), (int)$nextMonth->format('n'), $daysInNextMonth)->setTime(0,0,0);
if ($billingFlow === 'ANNUAL') {
if ($billingCycle === 'ANNUAL') {
$periodEnd = (clone $now)->modify('+1 year')->setTime(0,0,0);
$recurringCost = $plan->annual_cost_cents;
} else {
$periodEnd = (clone $now)->modify('+1 month')->setTime(0,0,0);
// FIXED: Look ahead to prevent native PHP +1 month edge-case rollover anomalies
$nextMonth = (clone $now)->modify('+1 month');
$daysInNextMonth = (int)$nextMonth->format('t');

if ($anchorDay > $daysInNextMonth) {
// Clamp period end to absolute upper bound of the target calendar block
$periodEnd = $nextMonth->setDate((int)$nextMonth->format('Y'), (int)$nextMonth->format('n'), $daysInNextMonth)->setTime(0,0,0);
} else {
$periodEnd = (clone $now)->modify('+1 month')->setTime(0,0,0);
}
$recurringCost = $plan->monthly_cost_cents;
}
} else if ($billingFlow === 'ANNIVERSARY') {

if ($isTrial) {
if ($billingCycle === 'ANNUAL') {
$periodEnd = (clone $now)->modify('+1 year');
$recurringCost = $plan->annual_cost_cents;
} else {
$periodEnd = (clone $now)->modify('+1 month');
$recurringCost = $plan->monthly_cost_cents;
}
} else {
$periodEnd = (clone $now)->modify(sprintf('+%d days', $trialDurationDays));
if ($billingCycle === 'ANNUAL') {
$recurringCost = $plan->annual_cost_cents;
} else {
$recurringCost = $plan->monthly_cost_cents;
}
}
$recurringCost = $plan->monthly_cost_cents;
}

//$billingFlow = MainHelper::getBillingFlow($customizations);
$billingFlow = $customizations['billing_flow'];
$nextBillingDateStr = $periodEnd->format('Y-m-d');

$subscription = Subscription::create([
$subscriptionParams = [
'workspace_id' => $workspace->id,
'current_plan_id' => $plan->id,
'status' => 'ACTIVE',
'billing_cycle' => $billingCycle,
'current_period_end' => $periodEnd,
'next_billing_date' => $nextBillingDateStr,
'billing_anchor_day' => $anchorDay
]);
];

if ($isTrial) {
$subscriptionParams['is_free_trial_active'] = true;
$subscriptionParams['free_trial_start_date'] = $now;
$subscriptionParams['free_trial_end_date'] = $periodEnd;
}

$subscription = Subscription::create($subscriptionParams);

Log::info("Recurring cost: {$recurringCost} cents");
$recurringCostInDollars = $recurringCost / 100;
Expand All @@ -292,16 +326,18 @@ public function userSpinup(Request $request)
Log::info("Amount to charge for signup: {$amountToCharge} dollars");

try {
RabbitMQHelper::dispatchImmediateBilling(
$workspace,
$subscription,
$user,
$plan,
$billingCycle,
$amountToCharge,
$nextBillingDateStr
);
Log::info("Signup Billing Queued: Workspace {$workspace->id}, Amount: {$amountToCharge}");
if (!$isTrial) {
RabbitMQHelper::dispatchImmediateBilling(
$workspace,
$subscription,
$user,
$plan,
$billingCycle,
$amountToCharge,
$nextBillingDateStr
);
Log::info("Signup Billing Queued: Workspace {$workspace->id}, Amount: {$amountToCharge}");
}
} catch (\Exception $e) {
Log::error("RabbitMQ Billing Dispatch Failed: " . $e->getMessage());
}
Expand Down
3 changes: 2 additions & 1 deletion app/app/ServicePlan.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ class ServicePlan extends Model {
'featured_plan' => 'boolean',
'pay_as_you_go' => 'boolean',
'registration_plan' => 'boolean',
'include_in_pricing_pages' => 'boolean'
'include_in_pricing_pages' => 'boolean',
'free_trial_exempt' => 'boolean'
);
protected $table ='service_plans';
public static function sortPlansByFeatures( $plans )
Expand Down
1 change: 1 addition & 0 deletions app/app/Subscription.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class Subscription extends Model {
protected $guarded = array('id');
protected $table = "subscriptions";
protected $casts = array(
'is_free_trial_active' => 'boolean',
);

public function toArray()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class AddFreeTrialFlagToSubscriptions extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('subscriptions', function (Blueprint $table) {
//
$table->boolean('is_free_trial_active')->default(false);
$table->dateTime('free_trial_start_date')->nullable();
$table->dateTime('free_trial_end_date')->nullable();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('subscriptions', function (Blueprint $table) {
$table->dropColumn('is_free_trial_active');
$table->dropColumn('free_trial_start_date');
$table->dropColumn('free_trial_end_date');
});
}
}
Loading