Subversion Repositories SmartDukaan

Rev

Rev 35403 | 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;
import java.util.Objects;

/**
 * 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 = "fofo.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, cascade = CascadeType.ALL)
    @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 boolean equals(Object o) {
        if (!(o instanceof PinelabsOrder)) return false;
        PinelabsOrder that = (PinelabsOrder) o;
        return id == that.id && Objects.equals(pendingOrderId, that.pendingOrderId) && Objects.equals(pinelabsOrderId, that.pinelabsOrderId) && Objects.equals(pinelabsMerchantOrderRef, that.pinelabsMerchantOrderRef) && Objects.equals(pinelabsCustomer, that.pinelabsCustomer) && Objects.equals(paymentMethod, that.paymentMethod) && Objects.equals(orderAmount, that.orderAmount) && Objects.equals(currency, that.currency) && paymentStatus == that.paymentStatus && Objects.equals(paymentMethodType, that.paymentMethodType) && Objects.equals(transactionId, that.transactionId) && Objects.equals(paymentUrl, that.paymentUrl) && Objects.equals(capturedAmount, that.capturedAmount) && Objects.equals(refundedAmount, that.refundedAmount) && Objects.equals(offerCode, that.offerCode) && Objects.equals(emiTenure, that.emiTenure) && Objects.equals(orderExpiryTimestamp, that.orderExpiryTimestamp) && Objects.equals(callbackReceivedTimestamp, that.callbackReceivedTimestamp) && Objects.equals(responseData, that.responseData) && Objects.equals(createTimestamp, that.createTimestamp) && Objects.equals(updateTimestamp, that.updateTimestamp);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, pendingOrderId, pinelabsOrderId, pinelabsMerchantOrderRef, pinelabsCustomer, paymentMethod, orderAmount, currency, paymentStatus, paymentMethodType, transactionId, paymentUrl, capturedAmount, refundedAmount, offerCode, emiTenure, orderExpiryTimestamp, callbackReceivedTimestamp, responseData, createTimestamp, updateTimestamp);
    }

    @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 + "]";
    }
}