Support pro plan discounts

This commit is contained in:
Hillel Coren 2016-12-14 16:19:16 +02:00
parent 8015b88c31
commit cc8959626f
12 changed files with 220 additions and 15 deletions

View File

@ -212,7 +212,7 @@ class AccountController extends BaseController
$days_total = $planDetails['paid']->diff($planDetails['expires'])->days;
$percent_used = $days_used / $days_total;
$credit = $planDetails['plan_price'] * (1 - $percent_used);
$credit = floatval($company->payment->amount) * (1 - $percent_used);
}
if ($newPlan['price'] > $credit) {
@ -224,7 +224,9 @@ class AccountController extends BaseController
}
} else {
if ($plan != PLAN_FREE) {
if ($plan == PLAN_FREE) {
$company->discount = 0;
} else {
$company->plan_term = $term;
$company->plan_price = $newPlan['price'];
$company->num_users = $numUsers;

View File

@ -1,7 +1,10 @@
<?php namespace App\Models;
use Carbon;
use Utils;
use Eloquent;
use Illuminate\Database\Eloquent\SoftDeletes;
use Laracasts\Presenter\PresentableTrait;
/**
* Class Company
@ -9,11 +12,21 @@ use Illuminate\Database\Eloquent\SoftDeletes;
class Company extends Eloquent
{
use SoftDeletes;
use PresentableTrait;
/**
* @var string
*/
protected $presenter = 'App\Ninja\Presenters\CompanyPresenter';
/**
* @var array
*/
protected $dates = ['deleted_at'];
protected $dates = [
'deleted_at',
'promo_expires',
'discount_expires',
];
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
@ -30,4 +43,64 @@ class Company extends Eloquent
{
return $this->belongsTo('App\Models\Payment');
}
public function hasActivePromo()
{
if ($this->discount_expires) {
return false;
}
return $this->promo_expires && $this->promo_expires->gte(Carbon::today());
}
// handle promos and discounts
public function hasActiveDiscount()
{
if ( ! $this->discount) {
return false;
}
return $this->discount_expires && $this->discount_expires->gt(Carbon::today());
}
public function discountedPrice($price)
{
if ( ! $this->hasActivePromo() && ! $this->hasActiveDiscount()) {
return $price;
}
return $price - ($price * $this->discount);
}
public function hasEarnedPromo()
{
if ( ! Utils::isNinjaProd() || Utils::isPro()) {
return false;
}
// if they've already had a discount or a promotion is active return false
if ($this->discount_expires || $this->hasActivePromo()) {
return false;
}
// after 52 weeks, offer a 50% discount for 3 days
$discounts = [
52 => [.5, 3],
16 => [.5, 3],
10 => [.25, 5],
];
foreach ($discounts as $weeks => $promo) {
list($discount, $validFor) = $promo;
$difference = $this->created_at->diffInWeeks();
if ($difference >= $weeks) {
$this->discount = $discount;
$this->promo_expires = date_create()->modify($validFor . ' days')->format('Y-m-d');
$this->save();
return true;
}
}
return false;
}
}

View File

@ -667,6 +667,11 @@ class BasePaymentDriver
$company->plan_expires = DateTime::createFromFormat('Y-m-d', $account->company->plan_paid)
->modify($term == PLAN_TERM_MONTHLY ? '+1 month' : '+1 year')->format('Y-m-d');
if ($company->hasActivePromo()) {
$company->discount_expires = date_create()->modify('1 year')->format('Y-m-d');
$company->promo_expires = null;
}
$company->save();
}
}

View File

@ -0,0 +1,29 @@
<?php namespace App\Ninja\Presenters;
class CompanyPresenter extends EntityPresenter
{
public function promoMessage()
{
if ( ! $this->entity->hasActivePromo()) {
return '';
}
return trans('texts.promo_message', [
'expires' => $this->entity->promo_expires->format('M dS, Y'),
'amount' => (int)($this->discount * 100)
]);
}
public function discountMessage()
{
if ( ! $this->entity->hasActiveDiscount()) {
return '';
}
return trans('texts.discount_message', [
'expires' => $this->entity->discount_expires->format('M dS, Y'),
'amount' => (int)($this->discount * 100)
]);
}
}

View File

@ -289,6 +289,16 @@ class AccountRepository
$invoice->invoice_date = $clientAccount->getRenewalDate();
$invoice->amount = $invoice->balance = $plan_cost - $credit;
$invoice->invoice_type_id = INVOICE_TYPE_STANDARD;
// check for promo/discount
$clientCompany = $clientAccount->company;
if ($clientCompany->hasActivePromo() || $clientCompany->hasActiveDiscount()) {
$discount = $invoice->amount * $clientCompany->discount;
$invoice->discount = $clientCompany->discount * 100;
$invoice->amount -= $discount;
$invoice->balance -= $discount;
}
$invoice->save();
if ($credit) {

View File

@ -0,0 +1,37 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddProPlanDiscount extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('companies', function ($table)
{
$table->float('discount');
$table->date('discount_expires')->nullable();
$table->date('promo_expires')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('companies', function ($table)
{
$table->dropColumn('discount');
$table->dropColumn('discount_expires');
$table->dropColumn('promo_expires');
});
}
}

View File

@ -2267,6 +2267,8 @@ $LANG = array(
'contact_us' => 'Contact Us',
'support_forum' => 'Support Forum',
'user_guide' => 'User Guide',
'promo_message' => 'Upgrade before :expires and get :amount% OFF your first year of our Pro or Enterprise packages.',
'discount_message' => ':amount% off expires :expires',
);

View File

@ -50,6 +50,12 @@
</p>
</div>
</div>
@if ($account->company->hasActiveDiscount())
{!! Former::plaintext('discount')
->value($account->company->present()->discountMessage) !!}
@endif
@if (Utils::isNinjaProd())
{!! Former::actions( Button::info(trans('texts.plan_change'))->large()->withAttributes(['onclick' => 'showChangePlan()'])->appendIcon(Icon::create('edit'))) !!}
@endif
@ -120,6 +126,9 @@
->addOption(trans('texts.plan_term_yearly'), PLAN_TERM_YEARLY)
->inlineHelp(trans('texts.enterprise_plan_features', ['link' => link_to(NINJA_WEB_URL . '/plans-pricing', trans('texts.click_here'), ['target' => '_blank'])])) !!}
{!! Former::plaintext(' ')
->inlineHelp($account->company->present()->promoMessage) !!}
</div>
<div class="modal-footer" style="margin-top: 0px">
@if (Utils::isPro())
@ -272,18 +281,18 @@
$('#plan_term').closest('.form-group').toggle(plan!='free');
if(plan=='{{PLAN_PRO}}'){
$('#plan_term option[value=month]').text({!! json_encode(trans('texts.plan_price_monthly', ['price'=>PLAN_PRICE_PRO_MONTHLY])) !!});
$('#plan_term option[value=year]').text({!! json_encode(trans('texts.plan_price_yearly', ['price'=>PLAN_PRICE_PRO_MONTHLY * 10])) !!});
$('#plan_term option[value=month]').text({!! json_encode(trans('texts.plan_price_monthly', ['price'=>$account->company->discountedPrice(PLAN_PRICE_PRO_MONTHLY)])) !!});
$('#plan_term option[value=year]').text({!! json_encode(trans('texts.plan_price_yearly', ['price'=>$account->company->discountedPrice(PLAN_PRICE_PRO_MONTHLY) * 10])) !!});
} else if(plan=='{{PLAN_ENTERPRISE}}') {
if (numUsers == 2) {
$('#plan_term option[value=month]').text({!! json_encode(trans('texts.plan_price_monthly', ['price'=>PLAN_PRICE_ENTERPRISE_MONTHLY_2])) !!});
$('#plan_term option[value=year]').text({!! json_encode(trans('texts.plan_price_yearly', ['price'=>PLAN_PRICE_ENTERPRISE_MONTHLY_2 * 10])) !!});
$('#plan_term option[value=month]').text({!! json_encode(trans('texts.plan_price_monthly', ['price'=>$account->company->discountedPrice(PLAN_PRICE_ENTERPRISE_MONTHLY_2)])) !!});
$('#plan_term option[value=year]').text({!! json_encode(trans('texts.plan_price_yearly', ['price'=>$account->company->discountedPrice(PLAN_PRICE_ENTERPRISE_MONTHLY_2) * 10])) !!});
} else if (numUsers == 5) {
$('#plan_term option[value=month]').text({!! json_encode(trans('texts.plan_price_monthly', ['price'=>PLAN_PRICE_ENTERPRISE_MONTHLY_5])) !!});
$('#plan_term option[value=year]').text({!! json_encode(trans('texts.plan_price_yearly', ['price'=>PLAN_PRICE_ENTERPRISE_MONTHLY_5 * 10])) !!});
$('#plan_term option[value=month]').text({!! json_encode(trans('texts.plan_price_monthly', ['price'=>$account->company->discountedPrice(PLAN_PRICE_ENTERPRISE_MONTHLY_5)])) !!});
$('#plan_term option[value=year]').text({!! json_encode(trans('texts.plan_price_yearly', ['price'=>$account->company->discountedPrice(PLAN_PRICE_ENTERPRISE_MONTHLY_5) * 10])) !!});
} else {
$('#plan_term option[value=month]').text({!! json_encode(trans('texts.plan_price_monthly', ['price'=>PLAN_PRICE_ENTERPRISE_MONTHLY_10])) !!});
$('#plan_term option[value=year]').text({!! json_encode(trans('texts.plan_price_yearly', ['price'=>PLAN_PRICE_ENTERPRISE_MONTHLY_10 * 10])) !!});
$('#plan_term option[value=month]').text({!! json_encode(trans('texts.plan_price_monthly', ['price'=>$account->company->discountedPrice(PLAN_PRICE_ENTERPRISE_MONTHLY_10)])) !!});
$('#plan_term option[value=year]').text({!! json_encode(trans('texts.plan_price_yearly', ['price'=>$account->company->discountedPrice(PLAN_PRICE_ENTERPRISE_MONTHLY_10) * 10])) !!});
}
}
}

View File

@ -194,9 +194,13 @@
@endif
</div>
</div>
@if($showBlueVinePromo)
@if ($account->company->hasEarnedPromo())
@include('partials/discount_promo')
@elseif ($showBlueVinePromo)
@include('partials/bluevine_promo')
@endif
<div class="row">
<div class="col-md-4">
<div class="panel panel-default">

View File

@ -374,7 +374,11 @@
@if (!Auth::user()->registered)
{!! Button::success(trans('texts.sign_up'))->withAttributes(array('id' => 'signUpButton', 'data-toggle'=>'modal', 'data-target'=>'#signUpModal', 'style' => 'max-width:100px;;overflow:hidden'))->small() !!} &nbsp;
@elseif (Utils::isNinjaProd() && (!Auth::user()->isPro() || Auth::user()->isTrial()))
{!! Button::success(trans('texts.plan_upgrade'))->withAttributes(array('onclick' => 'showUpgradeModal()', 'style' => 'max-width:100px;overflow:hidden'))->small() !!} &nbsp;
@if (Auth::user()->account->company->hasActivePromo())
{!! Button::warning(trans('texts.plan_upgrade'))->withAttributes(array('onclick' => 'showUpgradeModal()', 'style' => 'max-width:100px;overflow:hidden'))->small() !!} &nbsp;
@else
{!! Button::success(trans('texts.plan_upgrade'))->withAttributes(array('onclick' => 'showUpgradeModal()', 'style' => 'max-width:100px;overflow:hidden'))->small() !!} &nbsp;
@endif
@endif
@endif

View File

@ -0,0 +1,14 @@
<div class="alert alert-info" id="discountPromo">
{{ $account->company->present()->promoMessage }} &nbsp;&nbsp;
<a href="#" onclick="showUpgradeModal()" class="btn btn-primary btn-sm">{{ trans('texts.plan_upgrade') }}</a>
<a href="#" onclick="hideDiscountMessage()" class="pull-right">{{ trans('texts.hide') }}</a>
</div>
<script type="text/javascript">
function hideDiscountMessage() {
jQuery('#discountPromo').fadeOut();
return false;
}
</script>

View File

@ -49,6 +49,10 @@
vertical-align: super;
}
#upgrade-modal h4 {
color: white;
}
#upgrade-modal ul {
list-style: none;
color: #fff;
@ -135,12 +139,15 @@
<label for="plan_term_year" class="radio-inline">
<input value="year" id="plan_term_year" type="radio" name="plan_term">Annually</label>
</h4>
@if (Auth::user()->account->company->hasActivePromo())
<h4>{{ Auth::user()->account->company->present()->promoMessage }}</h4><br/>
@endif
</div>
<div class="col-md-4 col-md-offset-2 text-center">
<h2>{{ trans('texts.pro_upgrade_title') }}</h2>
<p class="subhead">{{ trans('texts.pay_annually_discount') }}</p>
<img width="65" src="{{ asset('images/pro_plan/border.png') }}"/>
<h3>$<span id="upgrade_pro_price">8</span> <span class="upgrade_frequency">/ {{ trans('texts.plan_term_month') }}</span></h3>
<h3>$<span id="upgrade_pro_price">{{ PLAN_PRICE_PRO_MONTHLY }}</span> <span class="upgrade_frequency">/ {{ trans('texts.plan_term_month') }}</span></h3>
<select style="visibility:hidden">
</select>
<p>&nbsp;</p>
@ -155,7 +162,7 @@
<h2>{{ trans('texts.plan_enterprise') }}</h2>
<p class="subhead">{{ trans('texts.pay_annually_discount') }}</p>
<img width="65" src="{{ asset('images/pro_plan/border.png') }}"/>
<h3>$<span id="upgrade_enterprise_price">12</span> <span class="upgrade_frequency">/ {{ trans('texts.plan_term_month') }}</span></h3>
<h3>$<span id="upgrade_enterprise_price">{{ PLAN_PRICE_ENTERPRISE_MONTHLY_2 }}</span> <span class="upgrade_frequency">/ {{ trans('texts.plan_term_month') }}</span></h3>
<select name="num_users" id="upgrade_num_users" onchange="updateUpgradePrices()">
<option value="2">1 to 2 {{ trans('texts.users') }}</option>
<option value="5">3 to 5 {{ trans('texts.users') }}</option>
@ -214,6 +221,10 @@
}
var label = "{{ trans('texts.freq_annually') }}";
}
@if (Auth::user()->account->company->hasActivePromo())
proPrice = proPrice - (proPrice * {{ Auth::user()->account->company->discount }});
enterprisePrice = enterprisePrice - (enterprisePrice * {{ Auth::user()->account->company->discount }});
@endif
$('#upgrade_pro_price').text(proPrice);
$('#upgrade_enterprise_price').text(enterprisePrice);
$('span.upgrade_frequency').text(label);
@ -225,6 +236,11 @@
}
$(function() {
@if (Auth::user()->account->company->hasActivePromo())
updateUpgradePrices();
@endif
$(document).keyup(function(e) {
if (e.keyCode == 27) { // escape key maps to keycode `27`
hideUpgradeModal();