Selaa lähdekoodia

apply credit if launch fails

tags/v0.9.14
Jonathan Cobb 4 vuotta sitten
vanhempi
commit
23cc4dd9d1
12 muutettua tiedostoa jossa 93 lisäystä ja 15 poistoa
  1. +5
    -1
      bubble-server/src/main/java/bubble/cloud/payment/promo/accountCredit/AccountCreditPaymentDriver.java
  2. +9
    -0
      bubble-server/src/main/java/bubble/dao/bill/AccountPlanDAO.java
  3. +10
    -0
      bubble-server/src/main/java/bubble/dao/bill/PromotionDAO.java
  4. +1
    -1
      bubble-server/src/main/java/bubble/model/bill/AccountPaymentMethod.java
  5. +3
    -2
      bubble-server/src/main/java/bubble/model/bill/AccountPlan.java
  6. +10
    -5
      bubble-server/src/main/java/bubble/model/bill/Promotion.java
  7. +7
    -3
      bubble-server/src/main/java/bubble/model/cloud/BubbleNetwork.java
  8. +6
    -1
      bubble-server/src/main/java/bubble/resources/bill/AccountPlansResource.java
  9. +23
    -0
      bubble-server/src/main/java/bubble/service/bill/PromotionService.java
  10. +4
    -0
      bubble-server/src/main/java/bubble/service/cloud/NodeProgressMeter.java
  11. +14
    -1
      bubble-server/src/main/java/bubble/service/cloud/StandardNetworkService.java
  12. +1
    -1
      bubble-web

+ 5
- 1
bubble-server/src/main/java/bubble/cloud/payment/promo/accountCredit/AccountCreditPaymentDriver.java Näytä tiedosto

@@ -9,10 +9,14 @@ import bubble.cloud.payment.promo.PromotionalPaymentDriverBase;
import bubble.cloud.payment.promo.PromotionalPaymentServiceDriver;
import bubble.model.account.Account;
import bubble.model.bill.*;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Set;

import static org.cobbzilla.util.daemon.ZillaRuntime.now;

@Slf4j
public class AccountCreditPaymentDriver extends PromotionalPaymentDriverBase<AccountCreditPaymentConfig> {

@Override public boolean adminAddPromoToAccount(Promotion promo, Account account) {
@@ -20,7 +24,7 @@ public class AccountCreditPaymentDriver extends PromotionalPaymentDriverBase<Acc
.setAccount(account.getUuid())
.setCloud(promo.getCloud())
.setPaymentMethodType(PaymentMethodType.promotional_credit)
.setPaymentInfo(promo.getName())
.setPaymentInfo(promo.getName()+"_"+now())
.setMaskedPaymentInfo(promo.getName())
.setPromotion(promo.getUuid()));
return true;


+ 9
- 0
bubble-server/src/main/java/bubble/dao/bill/AccountPlanDAO.java Näytä tiedosto

@@ -52,12 +52,21 @@ public class AccountPlanDAO extends AccountOwnedEntityDAO<AccountPlan> {
return findByUniqueFields("account", accountUuid, "network", networkUuid);
}

public AccountPlan findByAccountAndNetworkAndNotDeleted(String accountUuid, String networkUuid) {
return findByUniqueFields("account", accountUuid, "network", networkUuid, "deleted", null);
}

public AccountPlan findByNetwork(String networkUuid) { return findByUniqueField("network", networkUuid); }

public List<AccountPlan> findByAccountAndNotDeleted(String account) {
return findByFields("account", account, "deleted", null);
}

public AccountPlan findByAccountAndIdAndNotDeleted(String account, String id) {
final AccountPlan accountPlan = findByUniqueFields("account", account, "uuid", id, "deleted", null);
return accountPlan != null ? accountPlan : findByUniqueFields("account", account, "name", id, "deleted", null);
}

public List<AccountPlan> findByAccountAndPaymentMethodAndNotDeleted(String account, String paymentMethod) {
return findByFields("account", account, "paymentMethod", paymentMethod, "deleted", null);
}


+ 10
- 0
bubble-server/src/main/java/bubble/dao/bill/PromotionDAO.java Näytä tiedosto

@@ -47,6 +47,16 @@ public class PromotionDAO extends AbstractCRUDDAO<Promotion> {
"adminAssignOnly", false));
}

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

public List<Promotion> findVisibleAndEnabledAndActiveWithNoCodeOrWithCode(String code, String currency) {
if (empty(code)) {
return filterActive(findByFields(


+ 1
- 1
bubble-server/src/main/java/bubble/model/bill/AccountPaymentMethod.java Näytä tiedosto

@@ -37,7 +37,7 @@ import static org.cobbzilla.wizard.model.crypto.EncryptedTypes.ENC_PAD;

@Entity @ECType(root=true) @ECTypeCreate(method="DISABLED")
@NoArgsConstructor @Accessors(chain=true)
@ECIndexes({ @ECIndex(unique=true, of={"paymentMethodType", "paymentInfo"}) })
@ECIndexes({ @ECIndex(unique=true, of={"paymentMethodType", "paymentInfo"}, where="deleted IS NULL") })
@Slf4j
public class AccountPaymentMethod extends IdentifiableBase implements HasAccountNoName, Scrubbable {



+ 3
- 2
bubble-server/src/main/java/bubble/model/bill/AccountPlan.java Näytä tiedosto

@@ -15,6 +15,7 @@ import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.cobbzilla.util.collection.ArrayUtil;
import org.cobbzilla.wizard.model.Identifiable;
import org.cobbzilla.wizard.model.IdentifiableBase;
@@ -34,9 +35,9 @@ import static org.cobbzilla.util.reflect.ReflectionUtil.copy;

@ECType(root=true) @ECTypeCreate(method="DISABLED")
@ECTypeURIs(listFields={"account", "plan", "network", "name"})
@Entity @NoArgsConstructor @Accessors(chain=true)
@Entity @NoArgsConstructor @Accessors(chain=true) @Slf4j
@ECIndexes({
@ECIndex(unique=true, of={"account", "name"}),
@ECIndex(unique=true, of={"account", "name"}, where="deleted IS NULL"),
@ECIndex(unique=true, of={"account", "network"}),
@ECIndex(unique=true, of={"plan", "network"})
})


+ 10
- 5
bubble-server/src/main/java/bubble/model/bill/Promotion.java Näytä tiedosto

@@ -99,22 +99,27 @@ public class Promotion extends IdentifiableBase
public boolean notAdminAssignOnly() { return !adminAssignOnly(); }

@ECSearchable @ECField(index=80)
@ECIndex @Column(nullable=false)
@Getter @Setter private Boolean launchFailureCredit = false;
public boolean launchFailureCredit() { return launchFailureCredit != null && launchFailureCredit; }

@ECSearchable @ECField(index=90)
@ECIndex @Getter @Setter private Long validFrom;
public boolean hasStarted () { return validFrom == null || validFrom > now(); }

@ECSearchable @ECField(index=90)
@ECSearchable @ECField(index=100)
@ECIndex @Getter @Setter private Long validTo;
public boolean hasEnded () { return validTo != null && validTo > now(); }

public boolean active () { return enabled() && hasStarted() && !hasEnded(); }
public boolean inactive () { return !active(); }

@ECSearchable @ECField(index=100)
@ECSearchable @ECField(index=110)
@ECIndex @Column(nullable=false)
@Getter @Setter private Boolean referral = false;
public boolean referral () { return referral != null && referral; }

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

@@ -122,11 +127,11 @@ public class Promotion extends IdentifiableBase
return currency != null && currency.equalsIgnoreCase(this.currency);
}

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

@ECSearchable @ECField(index=130)
@ECSearchable @ECField(index=140)
@ECIndex @Column(nullable=false, updatable=false)
@Getter @Setter private Integer maxValue;



+ 7
- 3
bubble-server/src/main/java/bubble/model/cloud/BubbleNetwork.java Näytä tiedosto

@@ -19,6 +19,7 @@ import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.cobbzilla.util.collection.ArrayUtil;
import org.cobbzilla.wizard.model.Identifiable;
import org.cobbzilla.wizard.model.IdentifiableBase;
@@ -51,7 +52,8 @@ import static org.cobbzilla.wizard.model.crypto.EncryptedTypes.ENC_PAD;
@ECTypeChildren(uriPrefix=EP_NETWORKS+"/{BubbleNetwork.name}", value={
@ECTypeChild(type=BubbleNode.class, backref="network")
})
@Entity @NoArgsConstructor @Accessors(chain=true) @ToString(of={"name", "domainName", "installType"})
@Entity @NoArgsConstructor @Accessors(chain=true)
@Slf4j @ToString(of={"name", "domainName", "installType"})
@ECIndexes({
@ECIndex(unique=true, of={"account", "name"}),
@ECIndex(unique=true, of={"name", "domainName"})
@@ -202,12 +204,14 @@ public class BubbleNetwork extends IdentifiableBase implements HasNetwork, HasBu
if (network != null && !network.getUuid().equals(request.getNetwork())) {
continue;
} else {
final Account acct = accountDAO.findByName(name);
final Account acct = accountDAO.findByName(tryName);
if (acct != null && !acct.getUuid().equals(request.getAccount())) {
continue;
}
}
return tryName.equals(name) ? errors : errors.setSuggestedName(tryName);
if (tryName.equals(name)) return errors;
log.info("validateHostname: setting suggested name='"+tryName+"'");
return errors.setSuggestedName(tryName);
}
errors.addViolation("err.name.alreadyInUse");
}


+ 6
- 1
bubble-server/src/main/java/bubble/resources/bill/AccountPlansResource.java Näytä tiedosto

@@ -66,11 +66,15 @@ public class AccountPlansResource extends AccountOwnedResource<AccountPlan, Acco
return getDao().findByAccountAndNotDeleted(account.getUuid());
}

@Override protected AccountPlan find(ContainerRequest ctx, String id) {
return getDao().findByAccountAndIdAndNotDeleted(getAccountUuid(ctx), id);
}

@Override protected AccountPlan findAlternate(ContainerRequest ctx, String id) {
// id might be a network uuid
final String accountUuid = getAccountUuid(ctx);
final BubbleNetwork network = networkDAO.findByAccountAndId(accountUuid, id);
return network == null ? null : getDao().findByAccountAndNetwork(accountUuid, network.getUuid());
return network == null ? null : getDao().findByAccountAndNetworkAndNotDeleted(accountUuid, network.getUuid());
}

@Override protected boolean canCreate(Request req, ContainerRequest ctx, Account caller, AccountPlan request) {
@@ -149,6 +153,7 @@ public class AccountPlansResource extends AccountOwnedResource<AccountPlan, Acco
} else {
validateName(request, errors);
}
log.info("setReferences: after calling validateName, request.name="+request.getName());

final BubblePlan plan = planDAO.findByAccountOrParentAndId(caller, request.getPlan());
if (plan == null) {


+ 23
- 0
bubble-server/src/main/java/bubble/service/bill/PromotionService.java Näytä tiedosto

@@ -290,4 +290,27 @@ public class PromotionService {

return listPromosForAccount(account.getUuid());
}

public void applyLaunchFailurePromo(String accountUuid, String currency) {

final List<AccountPaymentMethod> promos = accountPaymentMethodDAO.findByAccountAndPromoAndNotDeleted(accountUuid);

// only include promos that are not already associated with the account
final List<Promotion> launchFailPromos = promotionDAO.findEnabledAndActiveAndLaunchFailureWithNoCode(currency).stream()
.filter(p -> promos.stream().noneMatch(ap -> ap.getPromotion().equals(p.getUuid())))
.collect(Collectors.toList());

if (!empty(launchFailPromos)) {
final Promotion promo = launchFailPromos.get(0);
log.info("applyLaunchFailurePromo: adding launchFailPromo: "+promo.getName());
accountPaymentMethodDAO.create(new AccountPaymentMethod()
.setAccount(accountUuid)
.setCloud(promo.getCloud())
.setPaymentMethodType(PaymentMethodType.promotional_credit)
.setPaymentInfo(promo.getName())
.setMaskedPaymentInfo(promo.getName())
.setPromotion(promo.getUuid()));
}
}

}

+ 4
- 0
bubble-server/src/main/java/bubble/service/cloud/NodeProgressMeter.java Näytä tiedosto

@@ -40,6 +40,9 @@ public class NodeProgressMeter extends PipedOutputStream implements Runnable {
private int tickPos = 0;
private AtomicBoolean error = new AtomicBoolean(false);
private AtomicBoolean closed = new AtomicBoolean(false);
private AtomicBoolean success = new AtomicBoolean(false);
public boolean success () { return success.get(); }

private final Thread thread;

private RedisService redis;
@@ -159,6 +162,7 @@ public class NodeProgressMeter extends PipedOutputStream implements Runnable {

public void completed() {
closed.set(true);
success.set(true);
background(this::close);
_setCurrentTick(new NodeProgressMeterTick()
.setNetwork(nn.getNetwork())


+ 14
- 1
bubble-server/src/main/java/bubble/service/cloud/StandardNetworkService.java Näytä tiedosto

@@ -29,6 +29,7 @@ import bubble.model.cloud.notify.NotificationType;
import bubble.notify.NewNodeNotification;
import bubble.server.BubbleConfiguration;
import bubble.service.backup.RestoreService;
import bubble.service.bill.PromotionService;
import bubble.service.notify.NotificationService;
import com.github.jknack.handlebars.Handlebars;
import lombok.Cleanup;
@@ -116,6 +117,7 @@ public class StandardNetworkService implements NetworkService {
@Autowired private AccountPolicyDAO policyDAO;
@Autowired private AccountMessageDAO accountMessageDAO;
@Autowired private BubblePlanDAO planDAO;
@Autowired private PromotionService promoService;

@Autowired private NotificationService notificationService;
@Autowired private NodeService nodeService;
@@ -392,7 +394,18 @@ public class StandardNetworkService implements NetworkService {
log.warn("newNode: compute.cleanupStart error: "+e, e);
}
}
if (progressMeter != null) closeQuietly(progressMeter);
if (progressMeter != null) {
if (!progressMeter.success() && configuration.paymentsEnabled()) {
final AccountPlan accountPlan = accountPlanDAO.findByNetwork(nn.getNetwork());
if (accountPlan != null) {
final BubblePlan plan = planDAO.findByUuid(accountPlan.getPlan());
if (plan != null) {
promoService.applyLaunchFailurePromo(nn.getAccount(), plan.getCurrency());
}
}
}
closeQuietly(progressMeter);
}
unlockNetwork(nn.getNetwork(), lock);
}
return node;


+ 1
- 1
bubble-web

@@ -1 +1 @@
Subproject commit d673719b67c685457921fd3e9b8ea693b147c4a0
Subproject commit f5c2a0bdce5e4a9e8d610b1512c7ba4aa8e75828

Ladataan…
Peruuta
Tallenna