Subversion Repositories SmartDukaan

Rev

Blame | Last modification | View Log | RSS feed

package com.spice.profitmandi.common.document;

import com.spice.profitmandi.common.model.CustomCustomer;
import com.spice.profitmandi.common.model.CustomOrderItem;
import com.spice.profitmandi.common.model.CustomPaymentOption;
import com.spice.profitmandi.common.model.CustomRetailer;
import com.spice.profitmandi.common.model.EWayBillPdfModel;
import com.spice.profitmandi.common.model.InvoicePdfModel;
import com.spice.profitmandi.common.model.IrnModel;

import java.util.List;

/**
 * Normalized view of a printable document, consumed by the rendering {@code Section}s.
 *
 * <p>All four document types (tax invoice V1/V2, delivery challan, debit note, credit note)
 * ultimately carry an {@link InvoicePdfModel}; debit/credit notes simply wrap one and override the
 * document number/date. This holder resolves those differences once — document number, date,
 * {@link DocumentType} and display title — and delegates everything else to the wrapped model, so
 * the sections never branch on which source type produced the document.
 */
public class DocumentData {

    public enum DocumentType {
        TAX_INVOICE("Invoice No:", "INVOICE DETAILS", "Total Invoice Value", "invoice"),
        DELIVERY_CHALLAN("Challan No:", "CHALLAN DETAILS", "Total Challan Value", "delivery challan"),
        DEBIT_NOTE("DN No:", "DEBIT NOTE DETAILS", "Total Debit Note Value", "debit note"),
        CREDIT_NOTE("CN No:", "CREDIT NOTE DETAILS", "Total Credit Note Value", "credit note");

        private final String numberLabel;
        private final String sectionLabel;
        private final String totalValueLabel;
        private final String noun;

        DocumentType(String numberLabel, String sectionLabel, String totalValueLabel, String noun) {
            this.numberLabel = numberLabel;
            this.sectionLabel = sectionLabel;
            this.totalValueLabel = totalValueLabel;
            this.noun = noun;
        }

        /** Label preceding the document number, e.g. "Invoice No:" / "DN No:". */
        public String numberLabel() { return numberLabel; }
        /** Right-aligned section heading, e.g. "INVOICE DETAILS". */
        public String sectionLabel() { return sectionLabel; }
        /** Grand-total row label, e.g. "Total Invoice Value". */
        public String totalValueLabel() { return totalValueLabel; }
        /** Lower-case noun for prose, e.g. "invoice" in "computer-generated invoice". */
        public String noun() { return noun; }
    }

    private final InvoicePdfModel model;
    private final DocumentType type;
    private final String title;
    private final String documentNumber;
    private final String documentDate;
    private final String originalInvoiceNumber;
    private final String originalInvoiceDate;

    public DocumentData(InvoicePdfModel model, DocumentType type, String title,
                        String documentNumber, String documentDate,
                        String originalInvoiceNumber, String originalInvoiceDate) {
        this.model = model;
        this.type = type;
        this.title = title;
        this.documentNumber = documentNumber;
        this.documentDate = documentDate;
        this.originalInvoiceNumber = originalInvoiceNumber;
        this.originalInvoiceDate = originalInvoiceDate;
    }

    public InvoicePdfModel model() { return model; }
    public DocumentType type() { return type; }

    /** Upper-cased display title shown in the header banner (e.g. "TAX INVOICE", "DEBIT NOTE"). */
    public String title() { return title; }

    public String documentNumber() { return documentNumber; }
    public String documentDate() { return documentDate; }

    /** Original document reference shown on a note (e.g. supplier invoice no for a warehouse debit note); null on invoices. */
    public String originalInvoiceNumber() { return originalInvoiceNumber; }
    public String originalInvoiceDate() { return originalInvoiceDate; }

    public boolean isNote() {
        return type == DocumentType.DEBIT_NOTE || type == DocumentType.CREDIT_NOTE;
    }

    public CustomCustomer customer() { return model.getCustomer(); }
    public CustomRetailer retailer() { return model.getRetailer(); }
    public List<CustomOrderItem> items() { return model.getOrderItems(); }
    public List<CustomPaymentOption> paymentOptions() { return model.getPaymentOptions(); }
    public List<String> creditTerms() { return model.getCreditTerms(); }
    public IrnModel irnModel() { return model.getIrnModel(); }
    public String irnErrorMessage() { return model.getIrnErrorMessage(); }
    public EWayBillPdfModel eWayBill() { return model.geteWayBillPdfModel(); }
    public boolean isCancelled() { return model.isCancelled(); }
    public boolean isMargin() { return model.isHasMarginSchemeItems(); }
    public String customerAddressStateCode() { return model.getCustomerAddressStateCode(); }
    public String partnerAddressStateCode() { return model.getPartnerAddressStateCode(); }

    /** Mapped purchase-order number (transaction.order only); null when unmapped — then not printed. */
    public String poNumber() { return model.getPoNumber(); }

    /** Order placed date; printed whenever present. */
    public String orderDate() { return model.getOrderDate(); }

    /** Intra-state supply iff buyer and supplier are in the same state. Mirrors the legacy rule. */
    public boolean intraState() {
        return customer().getAddress().getState().equals(retailer().getAddress().getState());
    }

    /** State code printed in the supplier block — buyer's for intra-state, partner's for inter-state. */
    public String stateCode() {
        return intraState() ? customerAddressStateCode() : partnerAddressStateCode();
    }

    /** True when any line carries an order id, which adds the "Order Id" column. */
    public boolean showOrderId() {
        if (items() == null) return false;
        for (CustomOrderItem item : items()) {
            if (item.getOrderId() != 0) return true;
        }
        return false;
    }
}