Bladeren bron

add bill detail view, add currency checks to promotions

tags/v0.8.0
Jonathan Cobb 5 jaren geleden
bovenliggende
commit
6adc073605
14 gewijzigde bestanden met toevoegingen van 145 en 37 verwijderingen
  1. +2
    -1
      bubble-server/src/main/java/bubble/cloud/payment/promo/PromotionalPaymentServiceDriver.java
  2. +7
    -0
      bubble-server/src/main/java/bubble/dao/bill/BubblePlanDAO.java
  3. +28
    -8
      bubble-server/src/main/java/bubble/dao/bill/PromotionDAO.java
  4. +1
    -0
      bubble-server/src/main/java/bubble/model/bill/AccountPayment.java
  5. +2
    -0
      bubble-server/src/main/java/bubble/model/bill/Bill.java
  6. +4
    -0
      bubble-server/src/main/java/bubble/model/bill/Promotion.java
  7. +12
    -2
      bubble-server/src/main/java/bubble/resources/account/AuthResource.java
  8. +4
    -3
      bubble-server/src/main/java/bubble/resources/bill/AccountPlansResource.java
  9. +25
    -10
      bubble-server/src/main/java/bubble/resources/bill/BillsResource.java
  10. +6
    -1
      bubble-server/src/main/java/bubble/resources/bill/PromotionsResource.java
  11. +13
    -9
      bubble-server/src/main/java/bubble/service/bill/PromotionService.java
  12. +39
    -1
      bubble-server/src/main/resources/message_templates/en_US/server/post_auth/ResourceMessages.properties
  13. +1
    -1
      bubble-web
  14. +1
    -1
      utils/cobbzilla-utils

+ 2
- 1
bubble-server/src/main/java/bubble/cloud/payment/promo/PromotionalPaymentServiceDriver.java Bestand weergeven

@@ -30,8 +30,9 @@ public interface PromotionalPaymentServiceDriver extends PaymentServiceDriver {
AccountPlan accountPlan, AccountPlan accountPlan,
AccountPaymentMethod paymentMethod) { AccountPaymentMethod paymentMethod) {
// do not use if deleted (should never happen) // do not use if deleted (should never happen)
// do not use if wrong currency (should never happen)
// do not use if other higher priority promotions are usable // do not use if other higher priority promotions are usable
return paymentMethod.notDeleted() && usable.isEmpty();
return paymentMethod.notDeleted() && promo.isCurrency(bill.getCurrency()) && usable.isEmpty();
} }


} }

+ 7
- 0
bubble-server/src/main/java/bubble/dao/bill/BubblePlanDAO.java Bestand weergeven

@@ -8,6 +8,9 @@ import org.hibernate.criterion.Order;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;


import java.util.Set;
import java.util.stream.Collectors;

@Repository @Repository
public class BubblePlanDAO extends AccountOwnedEntityDAO<BubblePlan> { public class BubblePlanDAO extends AccountOwnedEntityDAO<BubblePlan> {


@@ -38,4 +41,8 @@ public class BubblePlanDAO extends AccountOwnedEntityDAO<BubblePlan> {
return findByName(id); return findByName(id);
} }


public Set<String> getSupportedCurrencies () {
return findAll().stream().map(BubblePlan::getCurrency).collect(Collectors.toSet());
}

} }

+ 28
- 8
bubble-server/src/main/java/bubble/dao/bill/PromotionDAO.java Bestand weergeven

@@ -25,27 +25,47 @@ public class PromotionDAO extends AbstractCRUDDAO<Promotion> {
return found != null ? found : findByName(id); return found != null ? found : findByName(id);
} }


public Promotion findEnabledAndActiveWithCode(String code) {
return filterActive(findByUniqueFields("enabled", true, "code", code, "referral", false, "adminAssignOnly", false));
public Promotion findEnabledAndActiveWithCode(String code, String currency) {
return filterActive(findByUniqueFields(
"enabled", true,
"code", code,
"referral", false,
"currency", currency,
"adminAssignOnly", false));
} }


public List<Promotion> findEnabledAndActiveWithNoCode() {
return filterActive(findByFields("enabled", true, "code", null, "referral", false, "adminAssignOnly", false));
public List<Promotion> findEnabledAndActiveWithNoCode(String currency) {
return filterActive(findByFields(
"enabled", true,
"code", null,
"referral", false,
"currency", currency,
"adminAssignOnly", false));
} }


public List<Promotion> findVisibleAndEnabledAndActiveWithNoCodeOrWithCode(String code) {
public List<Promotion> findVisibleAndEnabledAndActiveWithNoCodeOrWithCode(String code, String currency) {
if (empty(code)) { if (empty(code)) {
return filterActive(findByFields("enabled", true, "code", null, "visible", true, "adminAssignOnly", false));
return filterActive(findByFields(
"enabled", true,
"code", null,
"visible", true,
"currency", currency,
"adminAssignOnly", false));
} else { } else {
return filterActive(list(criteria().add(and( return filterActive(list(criteria().add(and(
eq("enabled", true), eq("enabled", true),
eq("visible", true), eq("visible", true),
eq("currency", currency),
or(isNull("code"), eq("code", code)))))); or(isNull("code"), eq("code", code))))));
} }
} }


public List<Promotion> findEnabledAndActiveWithReferral() {
return filterActive(findByFields("enabled", true, "referral", true, "adminAssignOnly", false));
public List<Promotion> findEnabledAndActiveWithReferral(String currency) {
return filterActive(findByFields(
"enabled", true,
"referral", true,
"currency", currency,
"adminAssignOnly", false));
} }


public Promotion filterActive(Promotion promo) { return promo != null && promo.active() ? promo : null; } public Promotion filterActive(Promotion promo) { return promo != null && promo.active() ? promo : null; }


+ 1
- 0
bubble-server/src/main/java/bubble/model/bill/AccountPayment.java Bestand weergeven

@@ -98,6 +98,7 @@ public class AccountPayment extends IdentifiableBase implements HasAccountNoName
} }


@Transient @Getter @Setter private transient Bill billObject; @Transient @Getter @Setter private transient Bill billObject;
@Transient @Getter @Setter private transient AccountPaymentMethod paymentMethodObject;


public static int totalPayments (List<AccountPayment> payments) { public static int totalPayments (List<AccountPayment> payments) {
return empty(payments) ? 0 : payments.stream().mapToInt(AccountPayment::getAmountInt).sum(); return empty(payments) ? 0 : payments.stream().mapToInt(AccountPayment::getAmountInt).sum();


+ 2
- 0
bubble-server/src/main/java/bubble/model/bill/Bill.java Bestand weergeven

@@ -12,6 +12,7 @@ import org.cobbzilla.wizard.model.entityconfig.annotations.*;
import org.hibernate.annotations.Type; import org.hibernate.annotations.Type;


import javax.persistence.*; import javax.persistence.*;
import java.util.List;


import static org.cobbzilla.wizard.model.crypto.EncryptedTypes.ENCRYPTED_LONG; import static org.cobbzilla.wizard.model.crypto.EncryptedTypes.ENCRYPTED_LONG;
import static org.cobbzilla.wizard.model.crypto.EncryptedTypes.ENC_LONG; import static org.cobbzilla.wizard.model.crypto.EncryptedTypes.ENC_LONG;
@@ -74,5 +75,6 @@ public class Bill extends IdentifiableBase implements HasAccountNoName {
public boolean hasRefundedAmount () { return refundedAmount != null && refundedAmount > 0L; } public boolean hasRefundedAmount () { return refundedAmount != null && refundedAmount > 0L; }


@Transient @Getter @Setter private transient BubblePlan planObject; @Transient @Getter @Setter private transient BubblePlan planObject;
@Transient @Getter @Setter private transient List<AccountPayment> payments;


} }

+ 4
- 0
bubble-server/src/main/java/bubble/model/bill/Promotion.java Bestand weergeven

@@ -114,6 +114,10 @@ public class Promotion extends IdentifiableBase
@ECIndex @Column(nullable=false, updatable=false, length=10) @ECIndex @Column(nullable=false, updatable=false, length=10)
@Getter @Setter private String currency; @Getter @Setter private String currency;


public boolean isCurrency(String currency) {
return currency != null && currency.equalsIgnoreCase(this.currency);
}

@ECSearchable @ECField(index=120) @ECSearchable @ECField(index=120)
@ECIndex @Column(nullable=false, updatable=false) @ECIndex @Column(nullable=false, updatable=false)
@Getter @Setter private Integer minValue = 100; @Getter @Setter private Integer minValue = 100;


+ 12
- 2
bubble-server/src/main/java/bubble/resources/account/AuthResource.java Bestand weergeven

@@ -4,6 +4,7 @@ import bubble.dao.SessionDAO;
import bubble.dao.account.AccountDAO; import bubble.dao.account.AccountDAO;
import bubble.dao.account.AccountPolicyDAO; import bubble.dao.account.AccountPolicyDAO;
import bubble.dao.account.message.AccountMessageDAO; import bubble.dao.account.message.AccountMessageDAO;
import bubble.dao.bill.BubblePlanDAO;
import bubble.dao.cloud.BubbleNodeDAO; import bubble.dao.cloud.BubbleNodeDAO;
import bubble.model.CertType; import bubble.model.CertType;
import bubble.model.account.*; import bubble.model.account.*;
@@ -47,11 +48,13 @@ import static bubble.model.account.Account.validatePassword;
import static bubble.model.cloud.BubbleNetwork.TAG_ALLOW_REGISTRATION; import static bubble.model.cloud.BubbleNetwork.TAG_ALLOW_REGISTRATION;
import static bubble.model.cloud.BubbleNetwork.TAG_PARENT_ACCOUNT; import static bubble.model.cloud.BubbleNetwork.TAG_PARENT_ACCOUNT;
import static bubble.model.cloud.notify.NotificationType.retrieve_backup; import static bubble.model.cloud.notify.NotificationType.retrieve_backup;
import static bubble.server.BubbleConfiguration.getDEFAULT_LOCALE;
import static bubble.server.BubbleServer.getRestoreKey; import static bubble.server.BubbleServer.getRestoreKey;
import static java.util.concurrent.TimeUnit.SECONDS; import static java.util.concurrent.TimeUnit.SECONDS;
import static org.cobbzilla.util.daemon.ZillaRuntime.*; import static org.cobbzilla.util.daemon.ZillaRuntime.*;
import static org.cobbzilla.util.http.HttpContentTypes.APPLICATION_JSON; import static org.cobbzilla.util.http.HttpContentTypes.APPLICATION_JSON;
import static org.cobbzilla.util.http.HttpContentTypes.CONTENT_TYPE_ANY; import static org.cobbzilla.util.http.HttpContentTypes.CONTENT_TYPE_ANY;
import static org.cobbzilla.util.string.LocaleUtil.currencyForLocale;
import static org.cobbzilla.util.system.Sleep.sleep; import static org.cobbzilla.util.system.Sleep.sleep;
import static org.cobbzilla.wizard.resources.ResourceUtil.*; import static org.cobbzilla.wizard.resources.ResourceUtil.*;


@@ -70,6 +73,7 @@ public class AuthResource {
@Autowired private ActivationService activationService; @Autowired private ActivationService activationService;
@Autowired private AccountMessageDAO accountMessageDAO; @Autowired private AccountMessageDAO accountMessageDAO;
@Autowired private StandardAccountMessageService messageService; @Autowired private StandardAccountMessageService messageService;
@Autowired private BubblePlanDAO planDAO;
@Autowired private BubbleNodeDAO nodeDAO; @Autowired private BubbleNodeDAO nodeDAO;
@Autowired private BubbleConfiguration configuration; @Autowired private BubbleConfiguration configuration;
@Autowired private AuthenticatorService authenticatorService; @Autowired private AuthenticatorService authenticatorService;
@@ -197,8 +201,14 @@ public class AuthResource {
request.getContact().validate(errors); request.getContact().validate(errors);
} }


String currency = null;
if (configuration.paymentsEnabled()) { if (configuration.paymentsEnabled()) {
errors.addAll(promoService.validatePromotions(request.getPromoCode()));
currency = currencyForLocale(request.getLocale(), getDEFAULT_LOCALE());
// do we have any plans with this currency?
if (!planDAO.getSupportedCurrencies().contains(currency)) {
currency = currencyForLocale(getDEFAULT_LOCALE());
}
errors.addAll(promoService.validatePromotions(request.getPromoCode(), currency));
} }


if (errors.isInvalid()) return invalid(errors); if (errors.isInvalid()) return invalid(errors);
@@ -211,7 +221,7 @@ public class AuthResource {
SimpleViolationException promoEx = null; SimpleViolationException promoEx = null;
if (configuration.paymentsEnabled()) { if (configuration.paymentsEnabled()) {
try { try {
promoService.applyPromotions(account, request.getPromoCode());
promoService.applyPromotions(account, request.getPromoCode(), currency);
} catch (SimpleViolationException e) { } catch (SimpleViolationException e) {
promoEx = e; promoEx = e;
} }


+ 4
- 3
bubble-server/src/main/java/bubble/resources/bill/AccountPlansResource.java Bestand weergeven

@@ -6,14 +6,16 @@ import bubble.dao.account.AccountSshKeyDAO;
import bubble.dao.bill.AccountPaymentMethodDAO; import bubble.dao.bill.AccountPaymentMethodDAO;
import bubble.dao.bill.AccountPlanDAO; import bubble.dao.bill.AccountPlanDAO;
import bubble.dao.bill.BubblePlanDAO; import bubble.dao.bill.BubblePlanDAO;
import bubble.dao.bill.PromotionDAO;
import bubble.dao.cloud.BubbleDomainDAO; import bubble.dao.cloud.BubbleDomainDAO;
import bubble.dao.cloud.BubbleFootprintDAO; import bubble.dao.cloud.BubbleFootprintDAO;
import bubble.dao.cloud.BubbleNetworkDAO; import bubble.dao.cloud.BubbleNetworkDAO;
import bubble.dao.cloud.CloudServiceDAO; import bubble.dao.cloud.CloudServiceDAO;
import bubble.model.account.Account; import bubble.model.account.Account;
import bubble.model.account.AccountSshKey; import bubble.model.account.AccountSshKey;
import bubble.model.bill.*;
import bubble.model.bill.AccountPaymentMethod;
import bubble.model.bill.AccountPlan;
import bubble.model.bill.BubblePlan;
import bubble.model.bill.PaymentMethodType;
import bubble.model.cloud.BubbleDomain; import bubble.model.cloud.BubbleDomain;
import bubble.model.cloud.BubbleFootprint; import bubble.model.cloud.BubbleFootprint;
import bubble.model.cloud.BubbleNetwork; import bubble.model.cloud.BubbleNetwork;
@@ -56,7 +58,6 @@ public class AccountPlansResource extends AccountOwnedResource<AccountPlan, Acco
@Autowired private BubbleConfiguration configuration; @Autowired private BubbleConfiguration configuration;
@Autowired private AuthenticatorService authenticatorService; @Autowired private AuthenticatorService authenticatorService;
@Autowired private GeoService geoService; @Autowired private GeoService geoService;
@Autowired private PromotionDAO promotionDAO;


public AccountPlansResource(Account account) { super(account); } public AccountPlansResource(Account account) { super(account); }




+ 25
- 10
bubble-server/src/main/java/bubble/resources/bill/BillsResource.java Bestand weergeven

@@ -1,16 +1,10 @@
package bubble.resources.bill; package bubble.resources.bill;


import bubble.cloud.payment.PaymentServiceDriver; 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.bill.*;
import bubble.dao.cloud.CloudServiceDAO; import bubble.dao.cloud.CloudServiceDAO;
import bubble.model.account.Account; 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.bill.*;
import bubble.model.cloud.CloudService; import bubble.model.cloud.CloudService;
import bubble.resources.account.ReadOnlyAccountOwnedResource; import bubble.resources.account.ReadOnlyAccountOwnedResource;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -30,14 +24,18 @@ import java.util.Map;


import static bubble.ApiConstants.EP_PAY; import static bubble.ApiConstants.EP_PAY;
import static bubble.ApiConstants.EP_PAYMENTS; import static bubble.ApiConstants.EP_PAYMENTS;
import static org.cobbzilla.util.http.URIUtil.queryParams;
import static org.cobbzilla.wizard.resources.ResourceUtil.*; import static org.cobbzilla.wizard.resources.ResourceUtil.*;


@Slf4j @Slf4j
public class BillsResource extends ReadOnlyAccountOwnedResource<Bill, BillDAO> { public class BillsResource extends ReadOnlyAccountOwnedResource<Bill, BillDAO> {


public static final String PARAM_PAYMENTS = "payments";

@Autowired private BubblePlanDAO planDAO; @Autowired private BubblePlanDAO planDAO;
@Autowired private AccountPlanDAO accountPlanDAO; @Autowired private AccountPlanDAO accountPlanDAO;
@Autowired private AccountPaymentMethodDAO paymentMethodDAO; @Autowired private AccountPaymentMethodDAO paymentMethodDAO;
@Autowired private AccountPaymentDAO paymentDAO;
@Autowired private CloudServiceDAO cloudDAO; @Autowired private CloudServiceDAO cloudDAO;


private AccountPlan accountPlan; private AccountPlan accountPlan;
@@ -51,7 +49,24 @@ public class BillsResource extends ReadOnlyAccountOwnedResource<Bill, BillDAO> {


@Override protected Bill find(ContainerRequest ctx, String id) { @Override protected Bill find(ContainerRequest ctx, String id) {
final Bill bill = super.find(ctx, id); final Bill bill = super.find(ctx, id);
return bill == null || (accountPlan != null && !bill.getAccountPlan().equals(accountPlan.getUuid())) ? null : bill;
if (bill == null || (accountPlan != null && !bill.getAccountPlan().equals(accountPlan.getUuid()))) return null;

final Map<String, String> params = queryParams(ctx.getRequestUri().getQuery());
if (Boolean.parseBoolean(params.get(PARAM_PAYMENTS))) {
final List<AccountPayment> payments = paymentDAO.findByAccountAndAccountPlanAndBill(bill.getAccount(), bill.getAccountPlan(), bill.getUuid());
for (AccountPayment payment : payments) {
final String paymentMethodUuid = payment.getPaymentMethod();
payment.setPaymentMethodObject(findPaymentMethod(paymentMethodUuid));
}
return bill.setPayments(payments);
}

return bill;
}

private Map<String, AccountPaymentMethod> paymentMethodCache = new ExpirationMap<>(ExpirationEvictionPolicy.atime);
private AccountPaymentMethod findPaymentMethod(String paymentMethodUuid) {
return paymentMethodCache.computeIfAbsent(paymentMethodUuid, k -> paymentMethodDAO.findByUuid(k));
} }


@Override protected List<Bill> list(ContainerRequest ctx) { @Override protected List<Bill> list(ContainerRequest ctx) {
@@ -64,7 +79,7 @@ public class BillsResource extends ReadOnlyAccountOwnedResource<Bill, BillDAO> {
} }


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


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


+ 6
- 1
bubble-server/src/main/java/bubble/resources/bill/PromotionsResource.java Bestand weergeven

@@ -18,7 +18,10 @@ import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;


import static bubble.ApiConstants.PROMOTIONS_ENDPOINT; import static bubble.ApiConstants.PROMOTIONS_ENDPOINT;
import static bubble.server.BubbleConfiguration.getDEFAULT_LOCALE;
import static org.cobbzilla.util.daemon.ZillaRuntime.empty;
import static org.cobbzilla.util.http.HttpContentTypes.APPLICATION_JSON; import static org.cobbzilla.util.http.HttpContentTypes.APPLICATION_JSON;
import static org.cobbzilla.util.string.LocaleUtil.currencyForLocale;
import static org.cobbzilla.wizard.resources.ResourceUtil.*; import static org.cobbzilla.wizard.resources.ResourceUtil.*;


@Consumes(APPLICATION_JSON) @Consumes(APPLICATION_JSON)
@@ -35,12 +38,14 @@ public class PromotionsResource {


@GET @GET
public Response listPromos(@Context ContainerRequest ctx, public Response listPromos(@Context ContainerRequest ctx,
@QueryParam("currency") String currency,
@QueryParam("code") String code) { @QueryParam("code") String code) {
if (empty(currency)) currency = currencyForLocale(getDEFAULT_LOCALE());
final Account caller = optionalUserPrincipal(ctx); final Account caller = optionalUserPrincipal(ctx);
if (caller != null && caller.admin()) { if (caller != null && caller.admin()) {
return ok(promotionDAO.findAll()); return ok(promotionDAO.findAll());
} }
return ok(promotionDAO.findVisibleAndEnabledAndActiveWithNoCodeOrWithCode(code));
return ok(promotionDAO.findVisibleAndEnabledAndActiveWithNoCodeOrWithCode(code, currency));
} }


@GET @Path("/{id}") @GET @Path("/{id}")


+ 13
- 9
bubble-server/src/main/java/bubble/service/bill/PromotionService.java Bestand weergeven

@@ -42,19 +42,19 @@ public class PromotionService {
@Autowired protected AccountPaymentMethodDAO accountPaymentMethodDAO; @Autowired protected AccountPaymentMethodDAO accountPaymentMethodDAO;
@Autowired private BubbleConfiguration configuration; @Autowired private BubbleConfiguration configuration;


public void applyPromotions(Account account, String code) {
public void applyPromotions(Account account, String code, String currency) {
// apply promo code (or default) promotion // apply promo code (or default) promotion
final Set<Promotion> promos = new TreeSet<>(); final Set<Promotion> promos = new TreeSet<>();
ReferralCode referralCode = null; ReferralCode referralCode = null;
if (!empty(code)) { if (!empty(code)) {
Promotion promo = promotionDAO.findEnabledAndActiveWithCode(code);
Promotion promo = promotionDAO.findEnabledAndActiveWithCode(code, currency);
if (promo == null) { if (promo == null) {
// check referral codes // check referral codes
// it might be a referral code // it might be a referral code
referralCode = referralCodeDAO.findByName(code); referralCode = referralCodeDAO.findByName(code);
if (referralCode != null && !referralCode.claimed()) { if (referralCode != null && !referralCode.claimed()) {
// is there a referral promotion we can use? // is there a referral promotion we can use?
for (Promotion p : promotionDAO.findEnabledAndActiveWithReferral()) {
for (Promotion p : promotionDAO.findEnabledAndActiveWithReferral(currency)) {
promos.add(p); promos.add(p);
break; break;
} }
@@ -66,7 +66,7 @@ public class PromotionService {
} }


// everyone gets the highest-priority default promotion, if there are any enabled and active // everyone gets the highest-priority default promotion, if there are any enabled and active
for (Promotion p : promotionDAO.findEnabledAndActiveWithNoCode()) {
for (Promotion p : promotionDAO.findEnabledAndActiveWithNoCode(currency)) {
promos.add(p); promos.add(p);
break; break;
} }
@@ -105,9 +105,9 @@ public class PromotionService {
} }
} }


public ValidationResult validatePromotions(String code) {
public ValidationResult validatePromotions(String code, String currency) {
if (!empty(code)) { if (!empty(code)) {
Promotion promo = promotionDAO.findEnabledAndActiveWithCode(code);
Promotion promo = promotionDAO.findEnabledAndActiveWithCode(code, currency);
if (promo == null) { if (promo == null) {
// it might be a referral code // it might be a referral code
final ReferralCode referralCode = referralCodeDAO.findByName(code); final ReferralCode referralCode = referralCodeDAO.findByName(code);
@@ -116,7 +116,7 @@ public class PromotionService {
if (referer == null || referer.deleted()) return new ValidationResult("err.promoCode.notFound"); if (referer == null || referer.deleted()) return new ValidationResult("err.promoCode.notFound");


// is there a referral promotion we can use? // is there a referral promotion we can use?
for (Promotion p : promotionDAO.findEnabledAndActiveWithReferral()) {
for (Promotion p : promotionDAO.findEnabledAndActiveWithReferral(currency)) {
// todo: add JS check? // todo: add JS check?
promo = p; promo = p;
break; break;
@@ -167,11 +167,15 @@ public class PromotionService {
final CloudService promoCloud = cloudDAO.findByUuid(promo.getCloud()); final CloudService promoCloud = cloudDAO.findByUuid(promo.getCloud());
final String prefix = getClass().getSimpleName()+": "; final String prefix = getClass().getSimpleName()+": ";
if (promoCloud == null) { if (promoCloud == null) {
reportError(prefix+"purchase: cloud "+promo.getCloud()+" not found for promotion "+promo.getUuid());
reportError(prefix+"purchase: cloud "+promo.getCloud()+" not found for promotion "+promo.getName());
continue; continue;
} }
if (promoCloud.getType() != CloudServiceType.payment) { if (promoCloud.getType() != CloudServiceType.payment) {
reportError(prefix+"purchase: cloud "+promo.getCloud()+" for promotion "+promo.getUuid()+" has wrong type (expected 'payment'): "+promoCloud.getType());
reportError(prefix+"purchase: cloud "+promo.getCloud()+" for promotion "+promo.getName()+" has wrong type (expected 'payment'): "+promoCloud.getType());
continue;
}
if (!promo.getCurrency().equals(plan.getCurrency())) {
reportError(prefix+"purchase: promotion "+promo.getName()+" has wrong currency (expected "+plan.getCurrency()+" for plan "+plan.getName()+"): "+promoCloud.getType());
continue; continue;
} }
log.info("purchase: using Promotion: "+promo.getName()); log.info("purchase: using Promotion: "+promo.getName());


+ 39
- 1
bubble-server/src/main/resources/message_templates/en_US/server/post_auth/ResourceMessages.properties Bestand weergeven

@@ -242,10 +242,48 @@ label_bill_status=Status
bill_status_paid=Paid bill_status_paid=Paid
bill_status_unpaid=Unpaid bill_status_unpaid=Unpaid
bill_status_partial_payment=Partial payment bill_status_partial_payment=Partial payment
label_bill_period=Period
bill_status_undefined=Unknown
bill_status_null=Unknown
bill_status_=Unknown
label_bill_period=Date
label_bill_period_start=From
label_bill_period_end=To
label_bill_total=Amount label_bill_total=Amount
label_bill_total_format={{messages['currency_symbol_'+currency.toUpperCase()]}}{{totalMajorUnits}}{{totalMinorUnits === 0 ? '' : totalMinorUnits < 10 ? '.0'+totalMinorUnits : '.'+totalMinorUnits}} label_bill_total_format={{messages['currency_symbol_'+currency.toUpperCase()]}}{{totalMajorUnits}}{{totalMinorUnits === 0 ? '' : totalMinorUnits < 10 ? '.0'+totalMinorUnits : '.'+totalMinorUnits}}
label_bill_refunded=refunded label_bill_refunded=refunded
label_payment_type=Type
label_payment_method=Paid By
label_payment_status=Status
label_payment_amount=Amount
label_payment_amount_format={{messages['currency_symbol_'+currency.toUpperCase()]}}{{amountMajorUnits}}{{amountMinorUnits === 0 ? '' : amountMinorUnits < 10 ? '.0'+amountMinorUnits : '.'+amountMinorUnits}}
label_payment_action=Action
button_label_close_bill_detail=Close

payment_method_credit=Credit/Debit Card
payment_method_code=Invitation Code
payment_method_free=Free!
payment_method_promotional_credit=Promotion
payment_method_undefined=
payment_method_null=
payment_method_=

payment_status_init=Created
payment_status_success=Success
payment_status_failure=Failure
payment_status_unknown=Unknown
payment_status_undefined=Unknown
payment_status_null=Unknown
payment_status_=Unknown

payment_type_payment=payment
payment_type_credit_applied=credit applied
payment_type_refund=refund

label_promotion_FirstMonthFree=First Month Free
label_promotion_ReferralMonthFree=Referral Bonus
label_promotion_AccountCredit1=$1 Bonus
label_promotion_AccountCredit5=$5 Bonus
label_promotion_AccountCreditBill=Full Bill Bonus ($100 max value)


# Bubble Plans # Bubble Plans
plan_name_bubble=Bubble Standard plan_name_bubble=Bubble Standard


+ 1
- 1
bubble-web

@@ -1 +1 @@
Subproject commit c194f2c575af7d7735759759ee3dbfda5c768a15
Subproject commit ddbe7e69b39138c458766c82ee616c31fa7980d1

+ 1
- 1
utils/cobbzilla-utils

@@ -1 +1 @@
Subproject commit d1d485b1a8dcd51da565ca21886a95a728f3a832
Subproject commit 77831c8f23574ebdc8476dd835f8bbfbd8404338

Laden…
Annuleren
Opslaan