Commit a99e0eea by Nilu

manage plan upgrades

parent 97062fca
...@@ -36,7 +36,7 @@ public class PullStripeDataBatch extends ORMBatch ...@@ -36,7 +36,7 @@ public class PullStripeDataBatch extends ORMBatch
LogMgr.log (PULL_STRIPE_DATA_BATCH, LogLevel.PROCESSING1, "RUNNING Pull Stripe Data Batch"); LogMgr.log (PULL_STRIPE_DATA_BATCH, LogLevel.PROCESSING1, "RUNNING Pull Stripe Data Batch");
Stripe.apiKey = StripeUtils.STRIPE_KEY; Stripe.apiKey = StripeUtils.STRIPE_KEY;
Map<String, Object> planParams = new HashMap<>(); Map<String, Object> planParams = new HashMap<>();
planParams.put("active", true); planParams.put("active", true);
...@@ -51,7 +51,6 @@ public class PullStripeDataBatch extends ORMBatch ...@@ -51,7 +51,6 @@ public class PullStripeDataBatch extends ORMBatch
for (Plan plan : plansList) for (Plan plan : plansList)
{ {
System.out.println("pllan :: " + plan);
Filter<PaymentPlan> filter = PaymentPlan.SearchByAll().andStripeReference(new EqualsFilter<>(plan.getId())); Filter<PaymentPlan> filter = PaymentPlan.SearchByAll().andStripeReference(new EqualsFilter<>(plan.getId()));
List<PaymentPlan> activePlans = (List<PaymentPlan>) CollectionFilter.filter(Arrays.asList(paymentPlans) , filter); List<PaymentPlan> activePlans = (List<PaymentPlan>) CollectionFilter.filter(Arrays.asList(paymentPlans) , filter);
......
...@@ -54,13 +54,15 @@ public class SaveCompanyFP extends SaveFP ...@@ -54,13 +54,15 @@ public class SaveCompanyFP extends SaveFP
LogMgr.log(HiringTeam.LOG, LogLevel.PROCESSING1,"Hiring Team payment plan updated.", hiringTeam, " payment plan: ", hiringTeam.getPaymentPlan()); LogMgr.log(HiringTeam.LOG, LogLevel.PROCESSING1,"Hiring Team payment plan updated.", hiringTeam, " payment plan: ", hiringTeam.getPaymentPlan());
if(hiringTeam.getCompany().getCardID() != null ) if(hiringTeam.getCompany().getCardID() == null)
{ {
// cannot subscribe a user to a plan without card details throw new BusinessException("Please enter billing details before selecting a payment plan");
StripeUtils.updatePlan(hiringTeam);
LogMgr.log(HiringTeam.LOG, LogLevel.PROCESSING1,"Strpe subscription updated.", hiringTeam, hiringTeam.getStripeSubscription());
} }
// cannot subscribe a user to a plan without card details
StripeUtils.updatePlan(hiringTeam);
LogMgr.log(HiringTeam.LOG, LogLevel.PROCESSING1,"Strpe subscription updated.", hiringTeam, hiringTeam.getStripeSubscription());
} }
// //
// // Update company in intercom // // Update company in intercom
...@@ -77,13 +79,7 @@ public class SaveCompanyFP extends SaveFP ...@@ -77,13 +79,7 @@ public class SaveCompanyFP extends SaveFP
// Company company = process.getAttribute("Company") != null ? (Company) process.getAttribute("Company") : (Company) request.getAttribute("Company"); // Company company = process.getAttribute("Company") != null ? (Company) process.getAttribute("Company") : (Company) request.getAttribute("Company");
Boolean isPayment = (Boolean) request.getAttribute("IsPayment"); Boolean isPayment = (Boolean) request.getAttribute("IsPayment");
HiringTeam hiringTeam = (HiringTeam) process.getAttribute("HiringTeam"); HiringTeam hiringTeam = (HiringTeam) process.getAttribute("HiringTeam");
//to select payment plan when job open
// if(CollectionUtils.equals(isPayment, Boolean.TRUE) && company.getPaymentJobCount()!=null)
// {
// BusinessObjectParser.assertFieldCondition(company.getSelectedPaymentPlan()!= null, company , Company.SINGLEREFERENCE_PaymentPlan, "mandatory", exceptions, true, request);
// }
//
if(hiringTeam != null && !hiringTeam.getManageOwnBilling()) if(hiringTeam != null && !hiringTeam.getManageOwnBilling())
{ {
BusinessObjectParser.assertFieldCondition(hiringTeam.getBillingTeam() != null, hiringTeam , HiringTeam.SINGLEREFERENCE_BillingTeam, "mandatory", exceptions, true, request); BusinessObjectParser.assertFieldCondition(hiringTeam.getBillingTeam() != null, hiringTeam , HiringTeam.SINGLEREFERENCE_BillingTeam, "mandatory", exceptions, true, request);
......
...@@ -50,4 +50,9 @@ public class HiringTeam extends BaseHiringTeam ...@@ -50,4 +50,9 @@ public class HiringTeam extends BaseHiringTeam
return CompanyUserHiringTeamLink.pipesCompanyUserHiringTeamLink(getUsersSet()).toCompanyUser(filter).uniqueVals(); return CompanyUserHiringTeamLink.pipesCompanyUserHiringTeamLink(getUsersSet()).toCompanyUser(filter).uniqueVals();
} }
public boolean isPPJ()
{
return isTrue(getIsPPJ());
}
} }
\ No newline at end of file
package performa.orm; package performa.orm;
import oneit.objstore.rdbms.filters.EqualsFilter;
import oneit.objstore.rdbms.filters.IsNotNullFilter;
import oneit.utils.math.NullArith; import oneit.utils.math.NullArith;
......
...@@ -9,6 +9,7 @@ import com.stripe.model.Event; ...@@ -9,6 +9,7 @@ import com.stripe.model.Event;
import com.stripe.model.Invoice; import com.stripe.model.Invoice;
import com.stripe.model.Plan; import com.stripe.model.Plan;
import com.stripe.model.Subscription; import com.stripe.model.Subscription;
import com.stripe.model.UsageRecord;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
...@@ -16,6 +17,8 @@ import java.util.Date; ...@@ -16,6 +17,8 @@ import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import oneit.appservices.config.ConfigMgr; import oneit.appservices.config.ConfigMgr;
import oneit.logging.LogLevel; import oneit.logging.LogLevel;
...@@ -132,6 +135,23 @@ public class StripeUtils ...@@ -132,6 +135,23 @@ public class StripeUtils
return null; return null;
} }
public static Subscription retrieveSubscription(String subscriptionRef) throws FieldException
{
try
{
// Subscription subscription = Subscription.retrieve(subscriptionRef);
// new Date(subscription.getCurrentPeriodEnd() * 1000)
// new Date(subscription.getCurrentPeriodStart()* 1000)
return Subscription.retrieve(subscriptionRef);
}
catch (StripeException ex)
{
LogMgr.log(LoggingArea.ALL, LogLevel.PROCESSING1, ex, "Error while retrieving a subscription in stripe");
}
return null;
}
public static List<Invoice> retrieveInvoices(Company company) throws FieldException public static List<Invoice> retrieveInvoices(Company company) throws FieldException
{ {
...@@ -239,6 +259,29 @@ public class StripeUtils ...@@ -239,6 +259,29 @@ public class StripeUtils
} }
public static void recordUsage(HiringTeam hiringTeam)
{
try
{
Map<String, Object> params = new HashMap<>();
Date now = new Date();
String subscription = hiringTeam.getManageOwnBilling() ? hiringTeam.getStripeSubscription() : hiringTeam.getBillingTeam().getStripeSubscription();
params.put("quantity", 1);
params.put("timestamp", now.getTime() / 1000L);
params.put("subscription_item", subscription);
params.put("action", "increment");
UsageRecord.create(params, null);
}
catch (StripeException ex)
{
Logger.getLogger(StripeUtils.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void handleWebhook(HttpServletRequest request, ObjectTransaction objTran) throws FieldException public static void handleWebhook(HttpServletRequest request, ObjectTransaction objTran) throws FieldException
{ {
try try
......
...@@ -17,23 +17,15 @@ ...@@ -17,23 +17,15 @@
Debug.assertion(hiringTeam != null , "Invalid Hiring Team in admin portal manage plan"); Debug.assertion(hiringTeam != null , "Invalid Hiring Team in admin portal manage plan");
HiringTeam billingTeam = hiringTeam.getManageOwnBilling() ? hiringTeam : hiringTeam.getBillingTeam(); PaymentPlan[] paymentPlans = PaymentPlan.SearchByAll()
PaymentPlan[] plans = Utils.getPaymentPlansForJobs(transaction); .andDisabled(new EqualsFilter<>(Boolean.FALSE))
Integer maxCount = 0; .andUsageType(new EqualsFilter<>(UsageType.LICENSED))
Integer minCount = 0; .andActiveJobCount(new GreaterThanFilter<>(0))
PaymentPlan[] paymentPlans = PaymentPlan.SearchByAll().andDisabled(new EqualsFilter<>(Boolean.FALSE)).andActiveJobCount(new EqualsFilter<>(10)).search(transaction); .search(transaction);
if(company.getPaymentPlan() != null && company.getPaymentJobCount() == null)
{ List<PaymentPlan> sortedPlans = ObjstoreUtils.sort(Arrays.asList(paymentPlans),
company.setPaymentJobCount(company.getPaymentPlan().getActiveJobCount()); new ObjectTransform[]{PaymentPlan.pipesPaymentPlan().toActiveJobCount()},
} new Comparator[]{CollectionUtils.DEFAULT_COMPARATOR_NULLS_FIRST});
PaymentPlan paymentPlan = PaymentPlan.getPaymentPlanByID(transaction, (long)38021473);
if(plans.length > 0)
{
Collection<Integer> jCounts = PaymentPlan.pipesPaymentPlan(plans).toActiveJobCount().vals();
maxCount = Collections.max(jCounts);
minCount = Collections.min(jCounts);
}
%> %>
<script type="text/javascript"> <script type="text/javascript">
var Popup = null; var Popup = null;
...@@ -109,12 +101,12 @@ ...@@ -109,12 +101,12 @@
<div class="coupon-applied-alert"> <div class="coupon-applied-alert">
coupon applied coupon applied
<span class="coupon_code"> <span class="coupon_code">
<oneit:toString value="ABCD123" mode="EscapeHTML"/> - save <oneit:toString value="ABCD123" mode="EscapeHTML"/> - save
<oneit:toString value="10%" mode="EscapeHTML"/> <oneit:toString value="10%" mode="EscapeHTML"/>
</span> </span>
<span class="expire"> <span class="expire">
Expires Expires
<oneit:toString value="18 Sep 2018" mode="EscapeHTML"/> <oneit:toString value="18 Sep 2018" mode="EscapeHTML"/>
</span> </span>
</div> </div>
<div class="form-group row"> <div class="form-group row">
...@@ -123,7 +115,7 @@ ...@@ -123,7 +115,7 @@
<div class="manage-plan-row"> <div class="manage-plan-row">
<div class="radio"> <div class="radio">
<label> <label>
<oneit:ormInput obj="<%= hiringTeam %>" type="radio" attributeName="IsPPJ" value="true"/> <oneit:ormInput obj="<%= hiringTeam %>" type="radio" attributeName="IsPPJ" value="true"/>
</label> </label>
</div> </div>
<div class="manage-plan-title"> <div class="manage-plan-title">
...@@ -134,10 +126,10 @@ ...@@ -134,10 +126,10 @@
</div> </div>
<div class="manage-plan-payplan"> <div class="manage-plan-payplan">
<div class="per-job-amount"> <div class="per-job-amount">
<oneit:toString value="<%= PaymentPlan.PER_PER_JOB_AMOUNT %>" mode="Currency"/>/ Job <oneit:toString value="<%= PaymentPlan.PER_PER_JOB_AMOUNT %>" mode="Currency"/>/ Job
</div> </div>
<div class="per-job-amount-past"> <div class="per-job-amount-past">
was <oneit:toString value="<%= PaymentPlan.PER_PER_JOB_AMOUNT %>" mode="Currency"/> per job was <oneit:toString value="<%= PaymentPlan.PER_PER_JOB_AMOUNT %>" mode="Currency"/> per job
</div> </div>
</div> </div>
<div class="clearboth"></div> <div class="clearboth"></div>
...@@ -182,100 +174,124 @@ ...@@ -182,100 +174,124 @@
<div class="cost-per-job">Cost Per Job</div> <div class="cost-per-job">Cost Per Job</div>
<div class="monthly-fee">Monthly Fee</div> <div class="monthly-fee">Monthly Fee</div>
</div> </div>
<div class="choose-plan-item "> <%
<div class="jobs"> Subscription subscription = null;
10 Jobs PaymentPlan currentPlan = hiringTeam.getPaymentPlan();
</div>
<div class="cost">
<oneit:toString value="<%= 243.00 %>" mode="Currency"/>
<span class="past-val">
was <oneit:toString value="<%= 270.00 %>" mode="Currency"/>
</span>
</div>
<div class="fee">
<oneit:toString value="<%= 2430.00 %>" mode="Currency"/><span class="month"> / month </span>
<span class="past-val">
was <oneit:toString value="<%= 2700.00 %>" mode="Currency"/>
</span>
</div>
<div class="select-button">
<oneit:button value="Active" name="saveCompany" cssClass="btn active-btn"
requestAttribs="<%= CollectionUtils.mapEntry("nextPage", nextPage)
.toMap() %>" />
<a href="#" class="btn select-btn" data-popupid ="change-plan-popup01" >Select</a>
</div>
<div id="change-plan-popup01" style="display:none" >
<div class="change-plan-content">
<h3>
Upgrade to 20 Jobs per month?
</h3>
<div class="upgrade-info">
Upgrading your plan to 20 jobs per month will incur an additional cost of $2,000 be billed immediately.
<span>
This cose is to cover the differnce between your current active 10 job plan ($2,700) and the new 20 job plan ($4,700).
</span>
</div>
<div class="change-plan-list">
<div class="list-item">
<span class="item-title">Jobs remaining this month</span>
<span class="item-value">10 Job Remaining</span>
</div>
<div class="list-item">
<span class="item-title">Date your plan will reset</span>
<span class="item-value">12 September, 2018</span>
</div>
<div class="list-item">
<span class="item-title">Date of next billing period</span>
<span class="item-value">$4,700 on 12 September, 2018</span>
</div>
</div>
<div class="upgrade-info">
<span> if(!hiringTeam.isPPJ() && currentPlan != null)
Would you like to proceed with upgrading your account? {
</span> subscription = StripeUtils.retrieveSubscription(hiringTeam.getStripeSubscription());
</div> }
for (PaymentPlan paymentPlan : sortedPlans)
{
boolean isSelectedPlan = CollectionUtils.equals(paymentPlan, currentPlan);
%>
<div class="choose-plan-item <%= isSelectedPlan ? "active" : ""%>">
<div class="jobs">
<%= paymentPlan.getActiveJobCount() %> Jobs
</div>
<div class="cost">
<oneit:toString value="<%= paymentPlan.getAmount() / paymentPlan.getActiveJobCount() %>" mode="Currency"/>
<span class="past-val">
was <oneit:toString value="<%= 270.00 %>" mode="Currency"/>
</span>
</div>
<div class="fee">
<oneit:toString value="<%= paymentPlan.getAmount() %>" mode="Currency"/><span class="month"> / month </span>
<span class="past-val">
was <oneit:toString value="<%= 2700.00 %>" mode="Currency"/>
</span>
</div>
<div class="select-button">
<%
if(isSelectedPlan)
{
%>
<span class="btn active-btn">Active</span>
<%
}
else if(currentPlan != null)
{
boolean isUpgrade = paymentPlan.getActiveJobCount() > currentPlan.getActiveJobCount();
%>
<a href="#" class="btn select-btn" data-popupid ="change-plan-popup-<%=paymentPlan.getID()%>" >Select</a>
<div id="change-plan-popup-<%=paymentPlan.getID()%>" style="display:none" >
<div class="change-plan-content">
<h3>
<%= isUpgrade ? "Upgrade" : "Change" %> to <%= paymentPlan.getActiveJobCount() %> Jobs per month?
</h3>
<div class="upgrade-info">
<%
if(isUpgrade)
{
%>
Upgrading your plan to <%= paymentPlan.getActiveJobCount() %> Jobs per month will incur an additional cost of
<%= FormatUtils.stringify(paymentPlan.getAmount() - currentPlan.getAmount(), "Currency", "") %> be billed immediately.
<span>
This cost is to cover the difference between your current active <%= currentPlan.getActiveJobCount() %> job plan (<%= FormatUtils.stringify(currentPlan.getAmount(), "Currency", "") %>)
and the new <%= paymentPlan.getActiveJobCount() %> job plan (<%= FormatUtils.stringify(paymentPlan.getAmount(), "Currency", "") %>).
</span>
<%
}
else
{
%>
Changing your plan down to 5 Jobs per month will not incur any additional costs, and will begin on 1 September, 2018.
<span>
Because your plan has already been billed, your new plan will commence at the beginning of the next billing period.
</span>
<%
}
%>
</div>
<div class="change-plan-list">
<div class="list-item">
<span class="item-title">Jobs remaining this month</span>
<span class="item-value">10 Job Remaining</span>
</div>
<div class="list-item">
<span class="item-title">Date your plan will reset</span>
<span class="item-value">12 September, 2018</span>
</div>
<div class="list-item">
<span class="item-title">Date of next billing period</span>
<span class="item-value">$4,700 on 12 September, 2018</span>
</div>
</div>
<div class="upgrade-info">
<span>
Would you like to proceed with <%= isUpgrade ? "upgrading your account?" : "this change?" %>
</span>
</div>
</div>
<div class="change-plan-button">
<a class="change-plan-no-button popup-no-button">No</a>
<oneit:button skin="link" value="Yes" name="saveCompany" cssClass="change-plan-yes-button"
requestAttribs="<%= CollectionUtils.mapEntry("nextPage", nextPage)
.toMap() %>" />
</div> </div>
<div class="change-plan-button"> </div>
<a class="change-plan-no-button popup-no-button">No</a> <%
<oneit:button skin="link" value="Yes" name="saveCompany" cssClass="change-plan-yes-button" }
requestAttribs="<%= CollectionUtils.mapEntry("nextPage", nextPage) else
.toMap() %>" /> {
%>
</div> <oneit:button skin="link" value="Select" name="saveCompany" cssClass="btn select-btn"
</div> requestAttribs="<%= CollectionUtils.mapEntry("nextPage", nextPage)
.mapEntry ("IsPayment", Boolean.TRUE)
</div> .mapEntry ("PaymentPlan", paymentPlan)
<div class="choose-plan-item active"> .toMap() %>" />
<div class="jobs"> <%
10 Jobs }
</div> %>
<div class="cost"> </div>
<oneit:toString value="<%= 243.00 %>" mode="Currency"/>
<span class="past-val">
was <oneit:toString value="<%= 270.00 %>" mode="Currency"/>
</span>
</div>
<div class="fee">
<oneit:toString value="<%= 2430.00 %>" mode="Currency"/><span class="month"> / month </span>
<span class="past-val">
was <oneit:toString value="<%= 2700.00 %>" mode="Currency"/>
</span>
</div>
<div class="select-button">
<oneit:button value="Active" name="saveCompany1" cssClass="btn active-btn"
requestAttribs="<%= CollectionUtils.mapEntry("nextPage", nextPage)
.toMap() %>" />
<oneit:button value="Select" name="saveCompany" cssClass="btn select-btn"
requestAttribs="<%= CollectionUtils.mapEntry("nextPage", nextPage)
.toMap() %>" />
</div> </div>
</div> <%
}
%>
<div class="additional-jobs-over"> <div class="additional-jobs-over">
<span class="blue-alert"> <span class="blue-alert">
Additional jobs over plan allowance are billed at the Cost Per Job for the subscription level Additional jobs over plan allowance are billed at the Cost Per Job for the subscription level
...@@ -312,7 +328,7 @@ ...@@ -312,7 +328,7 @@
.mapEntry ("restartProcess", Boolean.TRUE) .mapEntry ("restartProcess", Boolean.TRUE)
.mapEntry ("Company", company) .mapEntry ("Company", company)
.mapEntry ("IsPayment", Boolean.TRUE) .mapEntry ("IsPayment", Boolean.TRUE)
.mapEntry ("PaymentPlan", paymentPlan) .mapEntry ("PaymentPlan", null)
.mapEntry ("attribNamesToRestore", Collections.singleton("HiringTeam")) .mapEntry ("attribNamesToRestore", Collections.singleton("HiringTeam"))
.toMap() %>" /> .toMap() %>" />
</div> </div>
......
<%@ page import="performa.orm.*, performa.orm.types.*, performa.form.*, performa.utils.*, performa.search.*"%> <%@ page import="performa.orm.*, performa.orm.types.*, performa.form.*, performa.utils.*, performa.search.*"%>
<%@ page import="performa.intercom.utils.*, performa.intercom.resources.User, com.stripe.model.*"%> <%@ page import="performa.intercom.utils.*, performa.intercom.resources.User, com.stripe.model.*"%>
<%@ page import="oneit.objstore.rdbms.filters.*, oneit.security.jsp.SecUserToNameTransform, oneit.servlets.utils.*, oneit.utils.image.*, oneit.objstore.utils.ObjstoreUtils "%> <%@ page import="oneit.objstore.rdbms.filters.*, oneit.security.jsp.SecUserToNameTransform, oneit.servlets.utils.*, oneit.utils.image.*, oneit.objstore.utils.ObjstoreUtils "%>
<%@ page import="oneit.utils.text.FormatUtils"%>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment