package com.whenling.extension.mall.order.model; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.FetchType; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.OneToOne; import javax.persistence.OrderBy; import javax.persistence.PrePersist; import javax.persistence.PreRemove; import javax.persistence.PreUpdate; import javax.persistence.Table; import javax.persistence.Transient; import javax.validation.Valid; import javax.validation.constraints.Digits; import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.NotEmpty; import com.whenling.centralize.model.Area; import com.whenling.centralize.model.Areable; import com.whenling.centralize.model.User; import com.whenling.extension.mall.MallSetting; import com.whenling.extension.mall.market.Coupon; import com.whenling.extension.mall.market.CouponCode; import com.whenling.extension.mall.market.Deposit; import com.whenling.module.domain.model.BizEntity; /** * 订单 * * @作者 孔祥溪 * @博客 http://ken.whenling.com * @创建时间 2016年3月2日 下午4:20:26 */ @Entity @Table(name = "mall_order") public class Order extends BizEntity<User, Long> implements Areable { private static final long serialVersionUID = -8159429771441170371L; /** 订单名称分隔符 */ private static final String NAME_SEPARATOR = " "; /** * 订单状态 */ public enum OrderStatus { /** 未确认 */ unconfirmed, /** 已确认 */ confirmed, /** 已完成 */ completed, /** 已取消 */ cancelled } /** * 支付状态 */ public enum PaymentStatus { /** 未支付 */ unpaid, /** 部分支付 */ partialPayment, /** 已支付 */ paid, /** 部分退款 */ partialRefunds, /** 已退款 */ refunded } /** * 配送状态 */ public enum ShippingStatus { /** 未发货 */ unshipped, /** 部分发货 */ partialShipment, /** 已发货 */ shipped, /** 部分退货 */ partialReturns, /** 已退货 */ returned } /** 订单编号 */ @Column(nullable = false, updatable = false, unique = true, length = 100) private String sn; /** 订单状态 */ @Enumerated(EnumType.STRING) @Column(nullable = false) private OrderStatus orderStatus; /** 支付状态 */ @Enumerated(EnumType.STRING) @Column(nullable = false) private PaymentStatus paymentStatus; /** 配送状态 */ @Enumerated(EnumType.STRING) @Column(nullable = false) private ShippingStatus shippingStatus; /** 支付手续费 */ @Column(nullable = false, precision = 21, scale = 6) private BigDecimal fee; /** 运费 */ @NotNull @Min(0) @Digits(integer = 12, fraction = 3) @Column(nullable = false, precision = 21, scale = 6) private BigDecimal freight; /** 促销折扣 */ @Column(nullable = false, updatable = false, precision = 21, scale = 6) private BigDecimal promotionDiscount; /** 优惠券折扣 */ @Column(nullable = false, updatable = false, precision = 21, scale = 6) private BigDecimal couponDiscount; /** 调整金额 */ @NotNull @Digits(integer = 12, fraction = 3) @Column(nullable = false, precision = 21, scale = 6) private BigDecimal offsetAmount; /** 已付金额 */ @Column(nullable = false, precision = 21, scale = 6) private BigDecimal amountPaid; /** 赠送积分 */ @NotNull @Min(0) @Column(nullable = false) private Long point; /** 收货人 */ @NotEmpty @Length(max = 200) @Column(nullable = false) private String consignee; /** 地区名称 */ @Column(nullable = false) private String areaName; /** 地址 */ @NotEmpty @Length(max = 200) @Column(nullable = false) private String address; /** 邮编 */ @NotEmpty @Length(max = 200) @Column(nullable = false) private String zipCode; /** 电话 */ @NotEmpty @Length(max = 200) @Column(nullable = false) private String phone; /** 是否开据发票 */ @NotNull @Column(nullable = false) private Boolean isInvoice; /** 发票抬头 */ @Length(max = 200) private String invoiceTitle; /** 税金 */ @Min(0) @Digits(integer = 12, fraction = 3) @Column(nullable = false, precision = 21, scale = 6) private BigDecimal tax; /** 附言 */ @Length(max = 200) private String memo; /** 促销 */ @Column(updatable = false) private String promotion; /** 到期时间 */ private Date expire; /** 锁定到期时间 */ private Date lockExpire; /** 是否已分配库存 */ @Column(nullable = false) private Boolean isAllocatedStock; /** 支付方式名称 */ @Column(nullable = false) private String paymentMethodName; /** 配送方式名称 */ @Column(nullable = false) private String shippingMethodName; /** 地区 */ @NotNull @ManyToOne(fetch = FetchType.LAZY) private Area area; /** 支付方式 */ @NotNull @ManyToOne(fetch = FetchType.LAZY) private PaymentMethod paymentMethod; /** 配送方式 */ @NotNull @ManyToOne(fetch = FetchType.LAZY) private ShippingMethod shippingMethod; /** 操作员 */ @ManyToOne(fetch = FetchType.LAZY) private User operator; /** 会员 */ @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(nullable = false, updatable = false) private User member; /** 优惠码 */ @OneToOne(fetch = FetchType.LAZY) private CouponCode couponCode; /** 优惠券 */ @ManyToMany(fetch = FetchType.LAZY) @JoinTable(name = "mall_order_coupon") private List<Coupon> coupons = new ArrayList<Coupon>(); /** 订单项 */ @Valid @NotEmpty @OneToMany(mappedBy = "order", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) @OrderBy("isGift asc") private List<OrderItem> orderItems = new ArrayList<OrderItem>(); /** 订单日志 */ @OneToMany(mappedBy = "order", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) @OrderBy("createDate asc") private Set<OrderLog> orderLogs = new HashSet<OrderLog>(); /** 预存款 */ @OneToMany(mappedBy = "order", fetch = FetchType.LAZY) private Set<Deposit> deposits = new HashSet<Deposit>(); /** 收款单 */ @OneToMany(mappedBy = "order", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) @OrderBy("createDate asc") private Set<Payment> payments = new HashSet<Payment>(); /** 退款单 */ @OneToMany(mappedBy = "order", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) @OrderBy("createDate asc") private Set<Refunds> refunds = new HashSet<Refunds>(); /** 发货单 */ @OneToMany(mappedBy = "order", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) @OrderBy("createdDate asc") private Set<Shipping> shippings = new HashSet<Shipping>(); /** 退货单 */ @OneToMany(mappedBy = "order", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) @OrderBy("createdDate asc") private Set<Returns> returns = new HashSet<Returns>(); public String getSn() { return sn; } public void setSn(String sn) { this.sn = sn; } public OrderStatus getOrderStatus() { return orderStatus; } public void setOrderStatus(OrderStatus orderStatus) { this.orderStatus = orderStatus; } public PaymentStatus getPaymentStatus() { return paymentStatus; } public void setPaymentStatus(PaymentStatus paymentStatus) { this.paymentStatus = paymentStatus; } public ShippingStatus getShippingStatus() { return shippingStatus; } public void setShippingStatus(ShippingStatus shippingStatus) { this.shippingStatus = shippingStatus; } public BigDecimal getFee() { return fee; } public void setFee(BigDecimal fee) { this.fee = fee; } public BigDecimal getFreight() { return freight; } public void setFreight(BigDecimal freight) { this.freight = freight; } public BigDecimal getPromotionDiscount() { return promotionDiscount; } public void setPromotionDiscount(BigDecimal promotionDiscount) { this.promotionDiscount = promotionDiscount; } public BigDecimal getCouponDiscount() { return couponDiscount; } public void setCouponDiscount(BigDecimal couponDiscount) { this.couponDiscount = couponDiscount; } public BigDecimal getOffsetAmount() { return offsetAmount; } public void setOffsetAmount(BigDecimal offsetAmount) { this.offsetAmount = offsetAmount; } public BigDecimal getAmountPaid() { return amountPaid; } public void setAmountPaid(BigDecimal amountPaid) { this.amountPaid = amountPaid; } public Long getPoint() { return point; } public void setPoint(Long point) { this.point = point; } public String getConsignee() { return consignee; } public void setConsignee(String consignee) { this.consignee = consignee; } public String getAreaName() { return areaName; } public void setAreaName(String areaName) { this.areaName = areaName; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getZipCode() { return zipCode; } public void setZipCode(String zipCode) { this.zipCode = zipCode; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public Boolean getIsInvoice() { return isInvoice; } public void setIsInvoice(Boolean isInvoice) { this.isInvoice = isInvoice; } public String getInvoiceTitle() { return invoiceTitle; } public void setInvoiceTitle(String invoiceTitle) { this.invoiceTitle = invoiceTitle; } public BigDecimal getTax() { return tax; } public void setTax(BigDecimal tax) { this.tax = tax; } public String getMemo() { return memo; } public void setMemo(String memo) { this.memo = memo; } public String getPromotion() { return promotion; } public void setPromotion(String promotion) { this.promotion = promotion; } public Date getExpire() { return expire; } public void setExpire(Date expire) { this.expire = expire; } public Date getLockExpire() { return lockExpire; } public void setLockExpire(Date lockExpire) { this.lockExpire = lockExpire; } public Boolean getIsAllocatedStock() { return isAllocatedStock; } public void setIsAllocatedStock(Boolean isAllocatedStock) { this.isAllocatedStock = isAllocatedStock; } public String getPaymentMethodName() { return paymentMethodName; } public void setPaymentMethodName(String paymentMethodName) { this.paymentMethodName = paymentMethodName; } public String getShippingMethodName() { return shippingMethodName; } public void setShippingMethodName(String shippingMethodName) { this.shippingMethodName = shippingMethodName; } public Area getArea() { return area; } public void setArea(Area area) { this.area = area; } public PaymentMethod getPaymentMethod() { return paymentMethod; } public void setPaymentMethod(PaymentMethod paymentMethod) { this.paymentMethod = paymentMethod; } public ShippingMethod getShippingMethod() { return shippingMethod; } public void setShippingMethod(ShippingMethod shippingMethod) { this.shippingMethod = shippingMethod; } public User getOperator() { return operator; } public void setOperator(User operator) { this.operator = operator; } public User getMember() { return member; } public void setMember(User member) { this.member = member; } public CouponCode getCouponCode() { return couponCode; } public void setCouponCode(CouponCode couponCode) { this.couponCode = couponCode; } public List<Coupon> getCoupons() { return coupons; } public void setCoupons(List<Coupon> coupons) { this.coupons = coupons; } public List<OrderItem> getOrderItems() { return orderItems; } public void setOrderItems(List<OrderItem> orderItems) { this.orderItems = orderItems; } public Set<OrderLog> getOrderLogs() { return orderLogs; } public void setOrderLogs(Set<OrderLog> orderLogs) { this.orderLogs = orderLogs; } public Set<Deposit> getDeposits() { return deposits; } public void setDeposits(Set<Deposit> deposits) { this.deposits = deposits; } public Set<Payment> getPayments() { return payments; } public void setPayments(Set<Payment> payments) { this.payments = payments; } public Set<Refunds> getRefunds() { return refunds; } public void setRefunds(Set<Refunds> refunds) { this.refunds = refunds; } public Set<Shipping> getShippings() { return shippings; } public void setShippings(Set<Shipping> shippings) { this.shippings = shippings; } public Set<Returns> getReturns() { return returns; } public void setReturns(Set<Returns> returns) { this.returns = returns; } /** * 获取订单名称 * * @return 订单名称 */ @Transient public String getName() { StringBuffer name = new StringBuffer(); if (getOrderItems() != null) { for (OrderItem orderItem : getOrderItems()) { if (orderItem != null && orderItem.getFullName() != null) { name.append(NAME_SEPARATOR).append(orderItem.getFullName()); } } if (name.length() > 0) { name.deleteCharAt(0); } } return name.toString(); } /** * 获取商品重量 * * @return 商品重量 */ @Transient public int getWeight() { int weight = 0; if (getOrderItems() != null) { for (OrderItem orderItem : getOrderItems()) { if (orderItem != null) { weight += orderItem.getTotalWeight(); } } } return weight; } /** * 获取商品数量 * * @return 商品数量 */ @Transient public int getQuantity() { int quantity = 0; if (getOrderItems() != null) { for (OrderItem orderItem : getOrderItems()) { if (orderItem != null && orderItem.getQuantity() != null) { quantity += orderItem.getQuantity(); } } } return quantity; } /** * 获取已发货数量 * * @return 已发货数量 */ @Transient public int getShippedQuantity() { int shippedQuantity = 0; if (getOrderItems() != null) { for (OrderItem orderItem : getOrderItems()) { if (orderItem != null && orderItem.getShippedQuantity() != null) { shippedQuantity += orderItem.getShippedQuantity(); } } } return shippedQuantity; } /** * 获取已退货数量 * * @return 已退货数量 */ @Transient public int getReturnQuantity() { int returnQuantity = 0; if (getOrderItems() != null) { for (OrderItem orderItem : getOrderItems()) { if (orderItem != null && orderItem.getReturnQuantity() != null) { returnQuantity += orderItem.getReturnQuantity(); } } } return returnQuantity; } /** * 获取商品价格 * * @return 商品价格 */ @Transient public BigDecimal getPrice() { BigDecimal price = new BigDecimal(0); if (getOrderItems() != null) { for (OrderItem orderItem : getOrderItems()) { if (orderItem != null && orderItem.getSubtotal() != null) { price = price.add(orderItem.getSubtotal()); } } } return price; } /** * 获取订单金额 * * @return 订单金额 */ @Transient public BigDecimal getAmount() { BigDecimal amount = getPrice(); if (getFee() != null) { amount = amount.add(getFee()); } if (getFreight() != null) { amount = amount.add(getFreight()); } if (getPromotionDiscount() != null) { amount = amount.subtract(getPromotionDiscount()); } if (getCouponDiscount() != null) { amount = amount.subtract(getCouponDiscount()); } if (getOffsetAmount() != null) { amount = amount.add(getOffsetAmount()); } if (getTax() != null) { amount = amount.add(getTax()); } return amount.compareTo(new BigDecimal(0)) > 0 ? amount : new BigDecimal(0); } /** * 获取应付金额 * * @return 应付金额 */ @Transient public BigDecimal getAmountPayable() { BigDecimal amountPayable = getAmount().subtract(getAmountPaid()); return amountPayable.compareTo(new BigDecimal(0)) > 0 ? amountPayable : new BigDecimal(0); } /** * 是否已过期 * * @return 是否已过期 */ @Transient public boolean isExpired() { return getExpire() != null && new Date().after(getExpire()); } /** * 获取订单项 * * @param sn * 商品编号 * @return 订单项 */ @Transient public OrderItem getOrderItem(String sn) { if (sn != null && getOrderItems() != null) { for (OrderItem orderItem : getOrderItems()) { if (orderItem != null && sn.equalsIgnoreCase(orderItem.getSn())) { return orderItem; } } } return null; } /** * 判断是否已锁定 * * @param operator * 操作员 * @return 是否已锁定 */ @Transient public boolean isLocked(User operator) { return getLockExpire() != null && new Date().before(getLockExpire()) && ((operator != null && !operator.equals(getOperator())) || (operator == null && getOperator() != null)); } /** * 计算税金 * * @return 税金 */ @Transient public BigDecimal calculateTax() { BigDecimal tax = new BigDecimal(0); MallSetting setting = MallSetting.get(); if (setting.getIsTaxPriceEnabled()) { BigDecimal amount = getPrice(); if (getPromotionDiscount() != null) { amount = amount.subtract(getPromotionDiscount()); } if (getCouponDiscount() != null) { amount = amount.subtract(getCouponDiscount()); } if (getOffsetAmount() != null) { amount = amount.add(getOffsetAmount()); } tax = amount.multiply(new BigDecimal(setting.getTaxRate().toString())); } return setting.setScale(tax); } /** * 持久化前处理 */ @PrePersist public void prePersist() { if (getArea() != null) { setAreaName(getArea().getFullName()); } if (getPaymentMethod() != null) { setPaymentMethodName(getPaymentMethod().getName()); } if (getShippingMethod() != null) { setShippingMethodName(getShippingMethod().getName()); } } /** * 更新前处理 */ @PreUpdate public void preUpdate() { if (getArea() != null) { setAreaName(getArea().getFullName()); } if (getPaymentMethod() != null) { setPaymentMethodName(getPaymentMethod().getName()); } if (getShippingMethod() != null) { setShippingMethodName(getShippingMethod().getName()); } } /** * 删除前处理 */ @PreRemove public void preRemove() { Set<Deposit> deposits = getDeposits(); if (deposits != null) { for (Deposit deposit : deposits) { deposit.setOrder(null); } } } }