Browse Source

move MockStripe driver to main, add UI support for bills

tags/v0.8.0
Jonathan Cobb 4 years ago
parent
commit
9c49e4c6f4
9 changed files with 44 additions and 28 deletions
  1. +1
    -1
      bubble-server/src/main/java/bubble/cloud/payment/stripe/mock/MockStripePaymentDriver.java
  2. +1
    -3
      bubble-server/src/main/java/bubble/dao/bill/BillDAO.java
  3. +10
    -20
      bubble-server/src/main/java/bubble/model/bill/Bill.java
  4. +13
    -0
      bubble-server/src/main/java/bubble/resources/bill/BillsResource.java
  5. +12
    -0
      bubble-server/src/main/resources/message_templates/en_US/server/post_auth/ResourceMessages.properties
  6. +4
    -1
      bubble-server/src/main/resources/message_templates/en_US/server/pre_auth/ResourceMessages.properties
  7. +1
    -1
      bubble-server/src/test/java/bubble/test/BubbleApiRunnerListener.java
  8. +1
    -1
      bubble-server/src/test/resources/models/system/cloudService_test.json
  9. +1
    -1
      bubble-web

+ 1
- 1
bubble-server/src/main/java/bubble/cloud/payment/stripe/mock/MockStripePaymentDriver.java View File

@@ -1,4 +1,4 @@
package bubble.mock;
package bubble.cloud.payment.stripe.mock;

import bubble.cloud.payment.ChargeResult;
import bubble.cloud.payment.stripe.StripePaymentDriver;


+ 1
- 3
bubble-server/src/main/java/bubble/dao/bill/BillDAO.java View File

@@ -55,13 +55,11 @@ public class BillDAO extends AccountOwnedEntityDAO<Bill> {
.setAccount(accountPlan.getAccount())
.setPlan(plan.getUuid())
.setAccountPlan(accountPlan.getUuid())
.setPrice(plan.getPrice())
.setTotal(plan.getPrice())
.setCurrency(plan.getCurrency())
.setPeriodLabel(period.periodLabel(periodStartMillis))
.setPeriodStart(period.periodStart(periodStartMillis))
.setPeriodEnd(period.periodEnd(periodStartMillis))
.setQuantity(1L)
.setType(BillItemType.compute)
.setStatus(BillStatus.unpaid);
}



+ 10
- 20
bubble-server/src/main/java/bubble/model/bill/Bill.java View File

@@ -2,7 +2,6 @@ package bubble.model.bill;

import bubble.model.account.Account;
import bubble.model.account.HasAccountNoName;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@@ -14,8 +13,8 @@ import org.hibernate.annotations.Type;

import javax.persistence.*;

import static org.cobbzilla.util.daemon.ZillaRuntime.big;
import static org.cobbzilla.wizard.model.crypto.EncryptedTypes.*;
import static org.cobbzilla.wizard.model.crypto.EncryptedTypes.ENCRYPTED_LONG;
import static org.cobbzilla.wizard.model.crypto.EncryptedTypes.ENC_LONG;

@ECType(root=true) @ECTypeCreate(method="DISABLED")
@ECTypeURIs(listFields={"name", "status", "type", "quantity", "price", "periodStart"})
@@ -47,42 +46,33 @@ public class Bill extends IdentifiableBase implements HasAccountNoName {
public boolean paid() { return status == BillStatus.paid; }
public boolean unpaid() { return !paid(); }

@ECSearchable @ECField(index=50)
@ECIndex @Enumerated(EnumType.STRING)
@Column(nullable=false, updatable=false, length=20)
@Getter @Setter private BillItemType type;

@ECSearchable @ECField(index=60, type=EntityFieldType.opaque_string)
@ECSearchable @ECField(index=50, type=EntityFieldType.opaque_string)
@Column(nullable=false, updatable=false, length=20)
@ECIndex @Getter @Setter private String periodLabel;

@ECSearchable @ECField(index=70, type=EntityFieldType.opaque_string)
@ECSearchable @ECField(index=60, type=EntityFieldType.opaque_string)
@Column(nullable=false, updatable=false, length=20)
@Getter @Setter private String periodStart;

@ECSearchable @ECField(index=80, type=EntityFieldType.opaque_string)
@ECSearchable @ECField(index=70, type=EntityFieldType.opaque_string)
@Column(nullable=false, updatable=false, length=20)
@Getter @Setter private String periodEnd;

public int daysInPeriod () { return BillPeriod.daysInPeriod(periodStart, periodEnd); }

@ECSearchable @ECField(index=90)
@Type(type=ENCRYPTED_LONG) @Column(updatable=false, columnDefinition="varchar("+(ENC_LONG)+") NOT NULL")
@Getter @Setter private Long quantity = 0L;

@ECSearchable @ECField(index=100)
@ECSearchable @ECField(index=80)
@Type(type=ENCRYPTED_LONG) @Column(updatable=false, columnDefinition="varchar("+(ENC_LONG)+") NOT NULL")
@Getter @Setter private Long price = 0L;
@Getter @Setter private Long total = 0L;

@ECSearchable @ECField(index=110)
@ECSearchable @ECField(index=90)
@ECIndex @Column(nullable=false, updatable=false, length=10)
@Getter @Setter private String currency;

@ECSearchable @ECField(index=120)
@ECSearchable @ECField(index=100)
@Type(type=ENCRYPTED_LONG) @Column(columnDefinition="varchar("+(ENC_LONG)+")")
@Getter @Setter private Long refundedAmount = 0L;
public boolean hasRefundedAmount () { return refundedAmount != null && refundedAmount > 0L; }

@JsonIgnore @Transient public long getTotal() { return big(quantity).multiply(big(price)).longValue(); }
@Transient @Getter @Setter private transient BubblePlan planObject;

}

+ 13
- 0
bubble-server/src/main/java/bubble/resources/bill/BillsResource.java View File

@@ -4,14 +4,18 @@ import bubble.cloud.payment.PaymentServiceDriver;
import bubble.dao.bill.AccountPaymentMethodDAO;
import bubble.dao.bill.AccountPlanDAO;
import bubble.dao.bill.BillDAO;
import bubble.dao.bill.BubblePlanDAO;
import bubble.dao.cloud.CloudServiceDAO;
import bubble.model.account.Account;
import bubble.model.bill.AccountPaymentMethod;
import bubble.model.bill.AccountPlan;
import bubble.model.bill.Bill;
import bubble.model.bill.BubblePlan;
import bubble.model.cloud.CloudService;
import bubble.resources.account.ReadOnlyAccountOwnedResource;
import lombok.extern.slf4j.Slf4j;
import org.cobbzilla.util.collection.ExpirationEvictionPolicy;
import org.cobbzilla.util.collection.ExpirationMap;
import org.cobbzilla.wizard.validation.ValidationResult;
import org.glassfish.jersey.server.ContainerRequest;
import org.springframework.beans.factory.annotation.Autowired;
@@ -22,6 +26,7 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import java.util.List;
import java.util.Map;

import static bubble.ApiConstants.EP_PAY;
import static bubble.ApiConstants.EP_PAYMENTS;
@@ -30,6 +35,7 @@ import static org.cobbzilla.wizard.resources.ResourceUtil.*;
@Slf4j
public class BillsResource extends ReadOnlyAccountOwnedResource<Bill, BillDAO> {

@Autowired private BubblePlanDAO planDAO;
@Autowired private AccountPlanDAO accountPlanDAO;
@Autowired private AccountPaymentMethodDAO paymentMethodDAO;
@Autowired private CloudServiceDAO cloudDAO;
@@ -53,6 +59,13 @@ public class BillsResource extends ReadOnlyAccountOwnedResource<Bill, BillDAO> {
return getDao().findByAccountAndAccountPlan(getAccountUuid(ctx), accountPlan.getUuid());
}

@Override protected Bill populate(ContainerRequest ctx, Bill bill) {
return super.populate(ctx, bill.setPlanObject(findPlan(bill.getPlan())));
}

private Map<String, BubblePlan> planCache = new ExpirationMap<>(ExpirationEvictionPolicy.atime);
private BubblePlan findPlan(String planUuid) { return planCache.computeIfAbsent(planUuid, k -> planDAO.findByUuid(planUuid)); }

@Path("/{id}"+EP_PAYMENTS)
public AccountPaymentsResource getPayments(@Context ContainerRequest ctx,
@PathParam("id") String id) {


+ 12
- 0
bubble-server/src/main/resources/message_templates/en_US/server/post_auth/ResourceMessages.properties View File

@@ -235,6 +235,18 @@ link_network_action_stop_description=Stop this Bubble. If you have downloaded yo
link_network_action_delete=Delete
link_network_action_delete_description=Delete this Bubble and all backups. You will not be able to restore this Bubble. This action cannot be undone.

# Billing and Payment
title_bills=Bills
label_bill_plan=Plan
label_bill_status=Status
bill_status_paid=Paid
bill_status_unpaid=Unpaid
bill_status_partial_payment=Partial payment
label_bill_period=Period
label_bill_total=Amount
label_bill_total_format={{messages['currency_symbol_'+currency.toUpperCase()]}}{{totalMajorUnits}}{{totalMinorUnits === 0 ? '' : totalMinorUnits < 10 ? '.0'+totalMinorUnits : '.'+totalMinorUnits}}
label_bill_refunded=refunded

# Bubble Plans
plan_name_bubble=Bubble Standard
plan_description_bubble=Try this one first. Most users probably don't need anything more


+ 4
- 1
bubble-server/src/main/resources/message_templates/en_US/server/pre_auth/ResourceMessages.properties View File

@@ -133,7 +133,10 @@ price_period_monthly_name=monthly
price_period_monthly_unit=month
price_period_yearly_name=annually
price_period_yearly_unit=year
price_format=${{priceMajorUnits}}{{priceMinorUnits === 0 ? '' : priceMinorUnits < 10 ? '.0'+priceMinorUnits : '.'+priceMinorUnits}} {{messages['price_period_'+period+'_name']}}
price_format={{messages['currency_symbol_'+currency.toUpperCase()]}}{{priceMajorUnits}}{{priceMinorUnits === 0 ? '' : priceMinorUnits < 10 ? '.0'+priceMinorUnits : '.'+priceMinorUnits}} {{messages['price_period_'+period+'_name']}}

currency_symbol_=
currency_symbol_USD=$

# Token errors
err.approvalToken.invalid=Code is incorrect or no longer valid


+ 1
- 1
bubble-server/src/test/java/bubble/test/BubbleApiRunnerListener.java View File

@@ -6,7 +6,7 @@ import bubble.cloud.payment.stripe.StripePaymentDriver;
import bubble.dao.account.AccountDAO;
import bubble.dao.cloud.BubbleDomainDAO;
import bubble.dao.cloud.CloudServiceDAO;
import bubble.mock.MockStripePaymentDriver;
import bubble.cloud.payment.stripe.mock.MockStripePaymentDriver;
import bubble.model.account.Account;
import bubble.model.cloud.CloudService;
import bubble.server.BubbleConfiguration;


+ 1
- 1
bubble-server/src/test/resources/models/system/cloudService_test.json View File

@@ -78,7 +78,7 @@
"_subst": true,
"name": "StripePayments",
"type": "payment",
"driverClass": "bubble.mock.MockStripePaymentDriver",
"driverClass": "bubble.cloud.payment.stripe.mock.MockStripePaymentDriver",
"driverConfig": {
"publicApiKey": "{{STRIPE_PUBLIC_API_KEY}}"
},


+ 1
- 1
bubble-web

@@ -1 +1 @@
Subproject commit a589fe857769f04f0944d0b5ea0dabb4c14a426c
Subproject commit c194f2c575af7d7735759759ee3dbfda5c768a15

Loading…
Cancel
Save