Subversion Repositories SmartDukaan

Rev

Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

package com.spice.profitmandi.dao.entity.fofo;

import com.spice.profitmandi.dao.convertor.LocalDateTimeAttributeConverter;
import com.spice.profitmandi.dao.enumuration.pinelabs.PinelabsPaymentStatus;

import javax.persistence.*;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * Entity representing Pinelabs order lifecycle.
 * Replaces the old payment.pine_labs table with enhanced tracking capabilities.
 *
 * @author Pinelabs Integration Team
 * @since 1.0
 */
@Entity
@Table(name = "pinelabs_orders", schema = "fofo")
public class PinelabsOrder implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    /**
     * Reference to internal pending order (fofo.pending_order.id)
     */
    @Column(name = "pending_order_id", nullable = false)
    private Integer pendingOrderId;

    /**
     * Order ID generated by Pinelabs API
     */
    @Column(name = "pinelabs_order_id", nullable = false, unique = true, length = 100)
    private String pinelabsOrderId;

    /**
     * Merchant reference for the order (optional, for reconciliation)
     */
    @Column(name = "pinelabs_merchant_order_ref", length = 100)
    private String pinelabsMerchantOrderRef;

    /**
     * Reference to Pinelabs customer (null for guest checkout)
     */
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "pinelabs_customer_id")
    private PinelabsCustomer pinelabsCustomer;

    /**
     * Payment method used for this order (null if not using saved card)
     */
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "payment_method_id")
    private PinelabsPaymentMethod paymentMethod;

    /**
     * Order amount in INR
     */
    @Column(name = "order_amount", nullable = false, precision = 12, scale = 2)
    private BigDecimal orderAmount;

    /**
     * Currency code (default: INR)
     */
    @Column(name = "currency", nullable = false, length = 3)
    private String currency = "INR";

    /**
     * Payment status
     */
    @Column(name = "payment_status", nullable = false, length = 50)
    @Enumerated(EnumType.STRING)
    private PinelabsPaymentStatus paymentStatus = PinelabsPaymentStatus.PENDING;

    /**
     * Payment method type (CARD, UPI, WALLET, NETBANKING, BNPL)
     */
    @Column(name = "payment_method_type", length = 50)
    private String paymentMethodType;

    /**
     * Transaction ID from Pinelabs
     */
    @Column(name = "transaction_id", length = 100)
    private String transactionId;

    /**
     * Pinelabs checkout URL (for redirect)
     */
    @Column(name = "payment_url", columnDefinition = "TEXT")
    private String paymentUrl;

    /**
     * Amount actually captured (for partial captures)
     */
    @Column(name = "captured_amount", precision = 12, scale = 2)
    private BigDecimal capturedAmount = BigDecimal.ZERO;

    /**
     * Amount refunded
     */
    @Column(name = "refunded_amount", precision = 12, scale = 2)
    private BigDecimal refundedAmount = BigDecimal.ZERO;

    /**
     * Applied offer/EMI code
     */
    @Column(name = "offer_code", length = 100)
    private String offerCode;

    /**
     * EMI tenure in months (if EMI selected)
     */
    @Column(name = "emi_tenure")
    private Integer emiTenure;

    /**
     * When the order expires (for payment link expiry)
     */
    @Convert(converter = LocalDateTimeAttributeConverter.class)
    @Column(name = "order_expiry_timestamp")
    private LocalDateTime orderExpiryTimestamp;

    /**
     * When payment callback was received from Pinelabs
     */
    @Convert(converter = LocalDateTimeAttributeConverter.class)
    @Column(name = "callback_received_timestamp")
    private LocalDateTime callbackReceivedTimestamp;

    /**
     * Raw JSON response from Pinelabs (for debugging/audit)
     */
    @Column(name = "response_data", columnDefinition = "TEXT")
    private String responseData;

    /**
     * Order creation timestamp
     */
    @Convert(converter = LocalDateTimeAttributeConverter.class)
    @Column(name = "create_timestamp", nullable = false, updatable = false)
    private LocalDateTime createTimestamp = LocalDateTime.now();

    /**
     * Last update timestamp
     */
    @Convert(converter = LocalDateTimeAttributeConverter.class)
    @Column(name = "update_timestamp", nullable = false)
    private LocalDateTime updateTimestamp = LocalDateTime.now();

    /**
     * Default constructor
     */
    public PinelabsOrder() {
    }

    /**
     * Constructor with essential fields
     *
     * @param pendingOrderId   Internal order ID
     * @param pinelabsOrderId  Pinelabs order ID
     * @param orderAmount      Order amount
     */
    public PinelabsOrder(Integer pendingOrderId, String pinelabsOrderId, BigDecimal orderAmount) {
        this.pendingOrderId = pendingOrderId;
        this.pinelabsOrderId = pinelabsOrderId;
        this.orderAmount = orderAmount;
    }

    // ==================== Getters and Setters ====================

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Integer getPendingOrderId() {
        return pendingOrderId;
    }

    public void setPendingOrderId(Integer pendingOrderId) {
        this.pendingOrderId = pendingOrderId;
    }

    public String getPinelabsOrderId() {
        return pinelabsOrderId;
    }

    public void setPinelabsOrderId(String pinelabsOrderId) {
        this.pinelabsOrderId = pinelabsOrderId;
    }

    public String getPinelabsMerchantOrderRef() {
        return pinelabsMerchantOrderRef;
    }

    public void setPinelabsMerchantOrderRef(String pinelabsMerchantOrderRef) {
        this.pinelabsMerchantOrderRef = pinelabsMerchantOrderRef;
    }

    public PinelabsCustomer getPinelabsCustomer() {
        return pinelabsCustomer;
    }

    public void setPinelabsCustomer(PinelabsCustomer pinelabsCustomer) {
        this.pinelabsCustomer = pinelabsCustomer;
    }

    public PinelabsPaymentMethod getPaymentMethod() {
        return paymentMethod;
    }

    public void setPaymentMethod(PinelabsPaymentMethod paymentMethod) {
        this.paymentMethod = paymentMethod;
    }

    public BigDecimal getOrderAmount() {
        return orderAmount;
    }

    public void setOrderAmount(BigDecimal orderAmount) {
        this.orderAmount = orderAmount;
    }

    public String getCurrency() {
        return currency;
    }

    public void setCurrency(String currency) {
        this.currency = currency;
    }

    public PinelabsPaymentStatus getPaymentStatus() {
        return paymentStatus;
    }

    public void setPaymentStatus(PinelabsPaymentStatus paymentStatus) {
        this.paymentStatus = paymentStatus;
    }

    public String getPaymentMethodType() {
        return paymentMethodType;
    }

    public void setPaymentMethodType(String paymentMethodType) {
        this.paymentMethodType = paymentMethodType;
    }

    public String getTransactionId() {
        return transactionId;
    }

    public void setTransactionId(String transactionId) {
        this.transactionId = transactionId;
    }

    public String getPaymentUrl() {
        return paymentUrl;
    }

    public void setPaymentUrl(String paymentUrl) {
        this.paymentUrl = paymentUrl;
    }

    public BigDecimal getCapturedAmount() {
        return capturedAmount;
    }

    public void setCapturedAmount(BigDecimal capturedAmount) {
        this.capturedAmount = capturedAmount;
    }

    public BigDecimal getRefundedAmount() {
        return refundedAmount;
    }

    public void setRefundedAmount(BigDecimal refundedAmount) {
        this.refundedAmount = refundedAmount;
    }

    public String getOfferCode() {
        return offerCode;
    }

    public void setOfferCode(String offerCode) {
        this.offerCode = offerCode;
    }

    public Integer getEmiTenure() {
        return emiTenure;
    }

    public void setEmiTenure(Integer emiTenure) {
        this.emiTenure = emiTenure;
    }

    public LocalDateTime getOrderExpiryTimestamp() {
        return orderExpiryTimestamp;
    }

    public void setOrderExpiryTimestamp(LocalDateTime orderExpiryTimestamp) {
        this.orderExpiryTimestamp = orderExpiryTimestamp;
    }

    public LocalDateTime getCallbackReceivedTimestamp() {
        return callbackReceivedTimestamp;
    }

    public void setCallbackReceivedTimestamp(LocalDateTime callbackReceivedTimestamp) {
        this.callbackReceivedTimestamp = callbackReceivedTimestamp;
    }

    public String getResponseData() {
        return responseData;
    }

    public void setResponseData(String responseData) {
        this.responseData = responseData;
    }

    public LocalDateTime getCreateTimestamp() {
        return createTimestamp;
    }

    public void setCreateTimestamp(LocalDateTime createTimestamp) {
        this.createTimestamp = createTimestamp;
    }

    public LocalDateTime getUpdateTimestamp() {
        return updateTimestamp;
    }

    public void setUpdateTimestamp(LocalDateTime updateTimestamp) {
        this.updateTimestamp = updateTimestamp;
    }

    // ==================== Helper Methods ====================

    /**
     * Check if order has expired
     *
     * @return true if order has expired
     */
    public boolean isExpired() {
        if (orderExpiryTimestamp == null) {
            return false;
        }
        return LocalDateTime.now().isAfter(orderExpiryTimestamp);
    }

    /**
     * Check if payment is successful
     *
     * @return true if payment status is CAPTURED
     */
    public boolean isPaymentSuccessful() {
        return paymentStatus == PinelabsPaymentStatus.CAPTURED;
    }

    /**
     * Check if refund is possible
     *
     * @return true if order can be refunded
     */
    public boolean canBeRefunded() {
        if (paymentStatus != PinelabsPaymentStatus.CAPTURED) {
            return false;
        }
        if (refundedAmount == null) {
            return true;
        }
        // Can refund if not fully refunded
        return refundedAmount.compareTo(capturedAmount != null ? capturedAmount : orderAmount) < 0;
    }

    /**
     * Get remaining refundable amount
     *
     * @return Amount that can still be refunded
     */
    public BigDecimal getRefundableAmount() {
        BigDecimal totalPaid = capturedAmount != null ? capturedAmount : orderAmount;
        BigDecimal alreadyRefunded = refundedAmount != null ? refundedAmount : BigDecimal.ZERO;
        return totalPaid.subtract(alreadyRefunded);
    }

    // ==================== Object Methods ====================

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        result = prime * result + ((pinelabsOrderId == null) ? 0 : pinelabsOrderId.hashCode());
        result = prime * result + ((pendingOrderId == null) ? 0 : pendingOrderId.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        PinelabsOrder other = (PinelabsOrder) obj;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        if (pinelabsOrderId == null) {
            if (other.pinelabsOrderId != null)
                return false;
        } else if (!pinelabsOrderId.equals(other.pinelabsOrderId))
            return false;
        if (pendingOrderId == null) {
            if (other.pendingOrderId != null)
                return false;
        } else if (!pendingOrderId.equals(other.pendingOrderId))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "PinelabsOrder [id=" + id + ", pendingOrderId=" + pendingOrderId + ", pinelabsOrderId="
                + pinelabsOrderId + ", orderAmount=" + orderAmount + ", currency=" + currency + ", paymentStatus="
                + paymentStatus + ", paymentMethodType=" + paymentMethodType + ", transactionId=" + transactionId
                + ", capturedAmount=" + capturedAmount + ", refundedAmount=" + refundedAmount + ", createTimestamp="
                + createTimestamp + "]";
    }
}