Rev 37592 | Blame | Compare with Previous | Last modification | View Log | RSS feed
package com.spice.profitmandi.dao.entity.fofo;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.Id;import javax.persistence.Table;import java.io.Serializable;import java.math.BigDecimal;import java.math.RoundingMode;import java.time.LocalDate;import java.time.LocalDateTime;/*** Current investment snapshot for one partner, maintained by the 2-minute sweep.** <p>All the fast-moving columns are written in a single pass so that coupled terms can never be* read at different vintages. Wallet and utilised are coupled (an advance payment swept to a loan* moves both); in-stock and aged-Apple are coupled (the aged units are a subset of stock). Mixing* vintages between any such pair double-counts the money that moved between them.** <p>{@link #getBaseValue()} is the single number the credit-limit tier consumes. The sweep* compares it at 2dp against the stored value to decide whether a partner's limit needs* recomputing, so it must never carry raw double noise.*/@Entity@Table(name = "fofo.partner_investment")public class PartnerInvestment implements Serializable {private static final long serialVersionUID = 1L;/** Money is rounded to paise everywhere; base_value is a comparison key, not an accumulator. */public static final int MONEY_SCALE = 2;@Id@Column(name = "fofo_id")private int fofoId;@Column(name = "wallet_amount")private BigDecimal walletAmount = BigDecimal.ZERO;/** Gross stock value; the live-demo haircut is applied by {@link #getNetInStockAmount()}. */@Column(name = "in_stock_gross_amount")private BigDecimal inStockGrossAmount = BigDecimal.ZERO;@Column(name = "unbilled_amount")private BigDecimal unbilledAmount = BigDecimal.ZERO;@Column(name = "grn_pending_amount")private BigDecimal grnPendingAmount = BigDecimal.ZERO;@Column(name = "activated_stock_amount")private BigDecimal activatedStockAmount = BigDecimal.ZERO;@Column(name = "activated_grn_pending_amount")private BigDecimal activatedGrnPendingAmount = BigDecimal.ZERO;@Column(name = "return_in_transit_amount")private BigDecimal returnInTransitAmount = BigDecimal.ZERO;@Column(name = "utilized_amount")private BigDecimal utilizedAmount = BigDecimal.ZERO;@Column(name = "aged_apple_stock_amount")private BigDecimal agedAppleStockAmount = BigDecimal.ZERO;/** Unit count behind {@link #agedAppleStockAmount}; maintained on the same daily cycle. */@Column(name = "aged_apple_qty")private int agedAppleQty;@Column(name = "demo_excluded_amount")private BigDecimal demoExcludedAmount = BigDecimal.ZERO;@Column(name = "aged_refreshed_on")private LocalDate agedRefreshedOn;@Column(name = "total_investment")private BigDecimal totalInvestment = BigDecimal.ZERO;@Column(name = "base_value")private BigDecimal baseValue = BigDecimal.ZERO;@Column(name = "snapshot_timestamp")private LocalDateTime snapshotTimestamp;public PartnerInvestment() {}public PartnerInvestment(int fofoId) {this.fofoId = fofoId;}private static BigDecimal scaled(BigDecimal value) {return (value == null ? BigDecimal.ZERO : value).setScale(MONEY_SCALE, RoundingMode.HALF_UP);}/*** Recomputes {@code totalInvestment} and {@code baseValue} from the component columns.** <p>Mirrors PartnerDailyInvestment.getTotalInvestment() less the aged-Apple haircut, then less* utilisation — the same chain PartnerLimitHelper.getSuggestedAmount() applies before the tier* multiply. Keeping it here means the limit never has to re-derive it from separate reads.*/public void recalculate() {BigDecimal total = scaled(walletAmount).add(getNetInStockAmount()).add(scaled(unbilledAmount)).add(scaled(grnPendingAmount)).add(scaled(returnInTransitAmount)).subtract(scaled(activatedStockAmount)).subtract(scaled(activatedGrnPendingAmount));this.totalInvestment = scaled(total);this.baseValue = scaled(this.totalInvestment.subtract(scaled(agedAppleStockAmount)).subtract(scaled(utilizedAmount)));}public int getFofoId() {return fofoId;}public void setFofoId(int fofoId) {this.fofoId = fofoId;}public BigDecimal getWalletAmount() {return walletAmount;}public void setWalletAmount(BigDecimal walletAmount) {this.walletAmount = scaled(walletAmount);}public BigDecimal getInStockGrossAmount() {return inStockGrossAmount;}public void setInStockGrossAmount(BigDecimal inStockGrossAmount) {this.inStockGrossAmount = scaled(inStockGrossAmount);}/*** Stock as investment counts it: gross less live-demo units held past 90 days.** <p>This is what {@code InventoryService.getTotalAmountInStock()} returns and what both* original investment paths assigned to {@code PartnerDailyInvestment.inStockAmount} — which is* why {@code getTotalInvestment()} carries no separate demo term. Derived rather than stored so* that the daily demo refresh flows through to stock and base with nothing to keep in sync.*/public BigDecimal getNetInStockAmount() {return scaled(scaled(inStockGrossAmount).subtract(scaled(demoExcludedAmount)));}public BigDecimal getUnbilledAmount() {return unbilledAmount;}public void setUnbilledAmount(BigDecimal unbilledAmount) {this.unbilledAmount = scaled(unbilledAmount);}public BigDecimal getGrnPendingAmount() {return grnPendingAmount;}public void setGrnPendingAmount(BigDecimal grnPendingAmount) {this.grnPendingAmount = scaled(grnPendingAmount);}public BigDecimal getActivatedStockAmount() {return activatedStockAmount;}public void setActivatedStockAmount(BigDecimal activatedStockAmount) {this.activatedStockAmount = scaled(activatedStockAmount);}public BigDecimal getActivatedGrnPendingAmount() {return activatedGrnPendingAmount;}public void setActivatedGrnPendingAmount(BigDecimal activatedGrnPendingAmount) {this.activatedGrnPendingAmount = scaled(activatedGrnPendingAmount);}public BigDecimal getReturnInTransitAmount() {return returnInTransitAmount;}public void setReturnInTransitAmount(BigDecimal returnInTransitAmount) {this.returnInTransitAmount = scaled(returnInTransitAmount);}public BigDecimal getUtilizedAmount() {return utilizedAmount;}public void setUtilizedAmount(BigDecimal utilizedAmount) {this.utilizedAmount = scaled(utilizedAmount);}public BigDecimal getAgedAppleStockAmount() {return agedAppleStockAmount;}public void setAgedAppleStockAmount(BigDecimal agedAppleStockAmount) {this.agedAppleStockAmount = scaled(agedAppleStockAmount);}public int getAgedAppleQty() {return agedAppleQty;}public void setAgedAppleQty(int agedAppleQty) {this.agedAppleQty = agedAppleQty;}public BigDecimal getDemoExcludedAmount() {return demoExcludedAmount;}public void setDemoExcludedAmount(BigDecimal demoExcludedAmount) {this.demoExcludedAmount = scaled(demoExcludedAmount);}public LocalDate getAgedRefreshedOn() {return agedRefreshedOn;}public void setAgedRefreshedOn(LocalDate agedRefreshedOn) {this.agedRefreshedOn = agedRefreshedOn;}public BigDecimal getTotalInvestment() {return totalInvestment;}public void setTotalInvestment(BigDecimal totalInvestment) {this.totalInvestment = scaled(totalInvestment);}public BigDecimal getBaseValue() {return baseValue;}public void setBaseValue(BigDecimal baseValue) {this.baseValue = scaled(baseValue);}public LocalDateTime getSnapshotTimestamp() {return snapshotTimestamp;}public void setSnapshotTimestamp(LocalDateTime snapshotTimestamp) {this.snapshotTimestamp = snapshotTimestamp;}@Overridepublic String toString() {return "PartnerInvestment{fofoId=" + fofoId+ ", wallet=" + walletAmount+ ", inStockGross=" + inStockGrossAmount+ ", inStockNet=" + getNetInStockAmount()+ ", unbilled=" + unbilledAmount+ ", grnPending=" + grnPendingAmount+ ", activatedStock=" + activatedStockAmount+ ", activatedGrnPending=" + activatedGrnPendingAmount+ ", agedApple=" + agedAppleStockAmount+ ", demoExcluded=" + demoExcludedAmount+ ", utilised=" + utilizedAmount+ ", total=" + totalInvestment+ ", base=" + baseValue+ ", at=" + snapshotTimestamp + '}';}}