package com.wyrs.admin.entity; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.PrePersist; import jakarta.persistence.Table; import jakarta.persistence.Transient; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.LinkedHashMap; import java.util.Map; import org.hibernate.annotations.JdbcTypeCode; @Entity @Table(name = "membership_price") public class MembershipPrice { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false, length = 32) private String appCode; /** applicationId / package name; empty = default for appCode. @Transient avoids ddl=validate schema change; still persisted in prices.json via Jackson. */ @Transient private String packageName; @Column(length = 64) private String productId; @Column(length = 128) private String name; @Column(precision = 10, scale = 2) private BigDecimal price; @Column(precision = 10, scale = 2) private BigDecimal originalPrice; private Integer durationDays; @Column(length = 32) private String billingType; @JdbcTypeCode(value = 3001) @Column(columnDefinition = "TEXT") private Map channelProductCodes; private Boolean enabled; private LocalDateTime createdAt; @PrePersist void prePersist() { if (this.createdAt == null) { this.createdAt = LocalDateTime.now(); } if (this.enabled == null) { this.enabled = true; } if (this.billingType == null || this.billingType.isBlank()) { this.billingType = this.durationDays != null && this.durationDays > 0 ? "subscription" : "one_time"; } if (this.channelProductCodes == null) { this.channelProductCodes = new LinkedHashMap<>(); } if (this.packageName == null) { this.packageName = ""; } } private static Map defaultChannelProductCodes() { return new LinkedHashMap<>(); } public static MembershipPriceBuilder builder() { return new MembershipPriceBuilder(); } public Long getId() { return this.id; } public String getAppCode() { return this.appCode; } public String getPackageName() { return this.packageName == null ? "" : this.packageName; } public String getProductId() { return this.productId; } public String getName() { return this.name; } public BigDecimal getPrice() { return this.price; } public BigDecimal getOriginalPrice() { return this.originalPrice; } public Integer getDurationDays() { return this.durationDays; } public String getBillingType() { return this.billingType; } public Map getChannelProductCodes() { return this.channelProductCodes; } public Boolean getEnabled() { return this.enabled; } public LocalDateTime getCreatedAt() { return this.createdAt; } public void setId(Long id) { this.id = id; } public void setAppCode(String appCode) { this.appCode = appCode; } public void setPackageName(String packageName) { this.packageName = packageName == null ? "" : packageName.trim(); } public void setProductId(String productId) { this.productId = productId; } public void setName(String name) { this.name = name; } public void setPrice(BigDecimal price) { this.price = price; } public void setOriginalPrice(BigDecimal originalPrice) { this.originalPrice = originalPrice; } public void setDurationDays(Integer durationDays) { this.durationDays = durationDays; } public void setBillingType(String billingType) { this.billingType = billingType; } public void setChannelProductCodes(Map channelProductCodes) { this.channelProductCodes = channelProductCodes; } public void setEnabled(Boolean enabled) { this.enabled = enabled; } public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; } public MembershipPrice() { this.channelProductCodes = MembershipPrice.defaultChannelProductCodes(); this.packageName = ""; } public MembershipPrice(Long id, String appCode, String packageName, String productId, String name, BigDecimal price, BigDecimal originalPrice, Integer durationDays, String billingType, Map channelProductCodes, Boolean enabled, LocalDateTime createdAt) { this.id = id; this.appCode = appCode; this.packageName = packageName == null ? "" : packageName; this.productId = productId; this.name = name; this.price = price; this.originalPrice = originalPrice; this.durationDays = durationDays; this.billingType = billingType; this.channelProductCodes = channelProductCodes; this.enabled = enabled; this.createdAt = createdAt; } public static class MembershipPriceBuilder { private Long id; private String appCode; private String packageName = ""; private String productId; private String name; private BigDecimal price; private BigDecimal originalPrice; private Integer durationDays; private String billingType; private Map channelProductCodes = MembershipPrice.defaultChannelProductCodes(); private Boolean enabled; private LocalDateTime createdAt; public MembershipPriceBuilder id(Long id) { this.id = id; return this; } public MembershipPriceBuilder appCode(String appCode) { this.appCode = appCode; return this; } public MembershipPriceBuilder packageName(String packageName) { this.packageName = packageName; return this; } public MembershipPriceBuilder productId(String productId) { this.productId = productId; return this; } public MembershipPriceBuilder name(String name) { this.name = name; return this; } public MembershipPriceBuilder price(BigDecimal price) { this.price = price; return this; } public MembershipPriceBuilder originalPrice(BigDecimal originalPrice) { this.originalPrice = originalPrice; return this; } public MembershipPriceBuilder durationDays(Integer durationDays) { this.durationDays = durationDays; return this; } public MembershipPriceBuilder billingType(String billingType) { this.billingType = billingType; return this; } public MembershipPriceBuilder channelProductCodes(Map m) { this.channelProductCodes = m; return this; } public MembershipPriceBuilder enabled(Boolean enabled) { this.enabled = enabled; return this; } public MembershipPriceBuilder createdAt(LocalDateTime createdAt) { this.createdAt = createdAt; return this; } public MembershipPrice build() { return new MembershipPrice(id, appCode, packageName, productId, name, price, originalPrice, durationDays, billingType, channelProductCodes, enabled, createdAt); } } }