OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

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

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 2011-2019 OpenConcerto, by ILM Informatique. All rights reserved.
 * 
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each file.
 */
 
 package org.openconcerto.erp.generationEcritures;

import org.openconcerto.erp.core.common.ui.TotalCalculator;
import org.openconcerto.erp.core.finance.accounting.element.ComptePCESQLElement;
import org.openconcerto.erp.core.finance.accounting.element.JournalSQLElement;
import org.openconcerto.erp.generationDoc.SheetXml;
import org.openconcerto.erp.core.finance.tax.model.TaxeCache;
import org.openconcerto.erp.generationEcritures.provider.AccountingRecordsProvider;
import org.openconcerto.erp.generationEcritures.provider.AccountingRecordsProviderManager;
import org.openconcerto.erp.model.PrixTTC;
import org.openconcerto.sql.model.SQLRow;
import org.openconcerto.sql.model.SQLRowAccessor;
import org.openconcerto.sql.model.SQLRowValues;
import org.openconcerto.sql.model.SQLTable;
import org.openconcerto.utils.ExceptionHandler;
import org.openconcerto.utils.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.Map;

// FIXME probleme lors de certaines generation tout reste figer

/**
 * Génération des ecritures associées à une saisie de vente avec facture. Entaine la génération du
 * reglement de la vente
 */
public class GenerationMvtSaisieVenteFacture extends GenerationEcritures implements Runnable {

    public static final String ID = "accounting.records.invoice.sales";
    private static final String source = "SAISIE_VENTE_FACTURE";
    public static final Integer journal = Integer.valueOf(JournalSQLElement.VENTES);
    private int idSaisieVenteFacture;
    private boolean useComptePCEVente;
    private static final SQLTable saisieVFTable = base.getTable("SAISIE_VENTE_FACTURE");
    private static final SQLTable mvtTable = base.getTable("MOUVEMENT");
    private static final SQLTable ecrTable = base.getTable("ECRITURE");
    private static final SQLTable tablePrefCompte = base.getTable("PREFS_COMPTE");
    private static final SQLRow rowPrefsCompte = tablePrefCompte.getRow(2);
    private final boolean genereReglement;

    /**
     * Generation de la comptabilité associée à la modification d'une saisie de vente facture
     * 
     * @param idSaisieVenteFacture
     * @param idMvt id du mouvement qui est dejà associé à la facture
     */
    public GenerationMvtSaisieVenteFacture(int idSaisieVenteFacture, int idMvt, boolean useComptePCEVente, boolean genereReglement) {
        this(idSaisieVenteFacture, idMvt, useComptePCEVente, genereReglement, false);
    }

    public GenerationMvtSaisieVenteFacture(int idSaisieVenteFacture, int idMvt, boolean useComptePCEVente, boolean genereReglement, boolean threadSafe) {
        System.err.println("********* init GeneRation");
        this.idMvt = idMvt;
        this.idSaisieVenteFacture = idSaisieVenteFacture;
        this.useComptePCEVente = useComptePCEVente;
        this.genereReglement = genereReglement;
        // Submit in sheetxml queue in order to get the good paiement in document
        if (!threadSafe)
            SheetXml.submitInQueue(GenerationMvtSaisieVenteFacture.this);
    }

    public GenerationMvtSaisieVenteFacture(int idSaisieVenteFacture, int idMvt, boolean useComptePCEVente) {
        this(idSaisieVenteFacture, idMvt, useComptePCEVente, true);
    }

    public GenerationMvtSaisieVenteFacture(int idSaisieVenteFacture, int idMvt) {
        this(idSaisieVenteFacture, idMvt, false, true);
    }

    /**
     * Generation de la comptabilité associée à la création d'une saisie de vente facture
     * 
     * @param idSaisieVenteFacture
     */
    public GenerationMvtSaisieVenteFacture(int idSaisieVenteFacture) {
        this(idSaisieVenteFacture, false);
    }

    public GenerationMvtSaisieVenteFacture(int idSaisieVenteFacture, final boolean threadSafe) {
        this(idSaisieVenteFacture, 1, false, true, threadSafe);
    }

    public final void genereMouvement() throws Exception {

        SQLRow saisieRow = GenerationMvtSaisieVenteFacture.saisieVFTable.getRow(this.idSaisieVenteFacture);
        setRowAnalytiqueSource(saisieRow);
        SQLRow clientRow = saisieRow.getForeignRow("ID_CLIENT");

        // Calcul des montants
        PrixTTC prixTTC = new PrixTTC(((Long) saisieRow.getObject("T_TTC")).longValue());
        // Total des acomptes déjà versés sur la facture
        long montantAcompteTTC = 0;

        int idCompteClient = clientRow.getInt("ID_COMPTE_PCE");

        Boolean acompte = saisieRow.getBoolean("ACOMPTE");
        if (acompte != null && acompte) {
            this.nom = "Fact. acompte client" + saisieRow.getObject("NUMERO").toString();
        } else {
            this.nom = "Fact. vente " + saisieRow.getObject("NUMERO").toString();
        }
        this.nom += " " + StringUtils.limitLength(clientRow.getString("NOM"), 20);
        this.putValue("NOM", this.nom);

        // iniatilisation des valeurs de la map
        this.date = (Date) saisieRow.getObject("DATE");
        AccountingRecordsProvider provider = AccountingRecordsProviderManager.get(ID);
        provider.putLabel(saisieRow, this.mEcritures);

        this.putValue("DATE", this.date);
        this.putValue("ID_JOURNAL", GenerationMvtSaisieVenteFacture.journal);
        this.putValue("ID_MOUVEMENT", Integer.valueOf(1));

        // on calcule le nouveau numero de mouvement
        if (this.idMvt == 1) {
            SQLRowValues rowValsPiece = new SQLRowValues(pieceTable);
            provider.putPieceLabel(saisieRow, rowValsPiece);
            getNewMouvement(GenerationMvtSaisieVenteFacture.source, this.idSaisieVenteFacture, 1, rowValsPiece);
        } else {
            this.putValue("ID_MOUVEMENT", Integer.valueOf(this.idMvt));
            SQLRowValues rowValsPiece = mvtTable.getRow(idMvt).getForeign("ID_PIECE").asRowValues();
            provider.putPieceLabel(saisieRow, rowValsPiece);
            rowValsPiece.update();
        }

        SQLTable tableEchantillon = null;
        BigDecimal portHT = BigDecimal.valueOf(saisieRow.getLong("PORT_HT")).movePointLeft(2);
        BigDecimal fraisDocHT = BigDecimal.valueOf(saisieRow.getLong("FRAIS_DOCUMENT_HT")).movePointLeft(2);
        SQLRow taxeDoc = saisieRow.getNonEmptyForeign("ID_TAXE_FRAIS_DOCUMENT") == null ? TaxeCache.getCache().getFirstTaxe()
                : TaxeCache.getCache().getRowFromId(saisieRow.getForeignID("ID_TAXE_FRAIS_DOCUMENT")).asRow();

        TotalCalculator calc;
        SQLRow taxePort = saisieRow.getNonEmptyForeign("ID_TAXE_PORT") == null ? TaxeCache.getCache().getFirstTaxe()
                : TaxeCache.getCache().getRowFromId(saisieRow.getForeignID("ID_TAXE_PORT")).asRow();

        if (clientRow.getTable().contains("ID_COMPTE_PCE_PRODUIT") && !clientRow.isForeignEmpty("ID_COMPTE_PCE_PRODUIT")) {

            calc = getValuesFromElement(false, false, "T_PV_HT", saisieRow, saisieVFTable.getTable("SAISIE_VENTE_FACTURE_ELEMENT"), portHT, taxePort, fraisDocHT, taxeDoc, tableEchantillon,
                    clientRow.getForeign("ID_COMPTE_PCE_PRODUIT"));
        } else {

            calc = getValuesFromElement(saisieRow, saisieVFTable.getTable("SAISIE_VENTE_FACTURE_ELEMENT"), portHT, taxePort, fraisDocHT, taxeDoc, tableEchantillon);
        }

        // On génére les ecritures si la facture n'est pas un acompte
        long ttcLongValue = calc.getTotalTTC().movePointRight(2).longValue();
        if (acompte == null || !acompte) {

            Map<SQLRowAccessor, Map<SQLRowAccessor, BigDecimal>> taxeCompl = calc.getMapHtTaxeCompl();
            for (SQLRowAccessor row : calc.getMapHt().keySet()) {
                long b = calc.getMapHt().get(row).setScale(2, RoundingMode.HALF_UP).movePointRight(2).longValue();
                if (b != 0) {
                    final Integer idComptePCE;
                    long taxe = 0;

                    if (taxeCompl.containsKey(row)) {
                        Map<SQLRowAccessor, BigDecimal> compl = taxeCompl.get(row);
                        for (SQLRowAccessor rowCompl : compl.keySet()) {
                            if (compl.get(rowCompl) != null) {
                                long taxeC = compl.get(rowCompl).multiply(rowCompl.getBigDecimal("POURCENT").movePointLeft(2)).setScale(2, RoundingMode.HALF_UP).movePointRight(2).longValue();
                                this.putValue("ID_COMPTE_PCE", rowCompl.getForeignID("ID_COMPTE_PCE"));
                                this.putValue("DEBIT", Long.valueOf(0));
                                this.putValue("CREDIT", Long.valueOf(taxeC));
                                ajoutEcriture();
                                taxe += taxeC;
                                // this.putValue("ID_COMPTE_PCE",
                                // rowCompl.getForeignID("ID_COMPTE_PCE_PRODUITS"));
                                // this.putValue("DEBIT", Long.valueOf(taxeC));
                                // this.putValue("CREDIT", Long.valueOf(0));
                                // ajoutEcriture();
                            }
                        }
                    }
                    // TODO check if taxe compl > b
                    if (this.useComptePCEVente) {
                        // Utilise le compte de la facture
                        idComptePCE = saisieRow.getInt("ID_COMPTE_PCE_VENTE");
                    } else {
                        idComptePCE = Integer.valueOf(row.getID());
                    }

                    this.putValue("ID_COMPTE_PCE", idComptePCE);
                    this.putValue("DEBIT", Long.valueOf(0));
                    this.putValue("CREDIT", Long.valueOf(b - taxe));
                    ajoutEcriture();
                }
            }

            Map<SQLRowAccessor, BigDecimal> tvaMap = calc.getMapHtTVA();
            for (SQLRowAccessor rowAc : tvaMap.keySet()) {
                long longValue = tvaMap.get(rowAc).setScale(2, RoundingMode.HALF_UP).movePointRight(2).longValue();
                if (longValue != 0) {
                    this.putValue("ID_COMPTE_PCE", rowAc.getID());
                    this.putValue("DEBIT", Long.valueOf(0));
                    this.putValue("CREDIT", longValue);
                    ajoutEcriture();
                }
            }

            // compte Clients

            if (idCompteClient <= 1) {
                idCompteClient = rowPrefsCompte.getInt("ID_COMPTE_PCE_CLIENT");
                if (idCompteClient <= 1) {
                    idCompteClient = ComptePCESQLElement.getIdComptePceDefault("Clients");
                }
            }
            this.putValue("ID_COMPTE_PCE", Integer.valueOf(idCompteClient));
            if (ecrTable.contains("CODE_CLIENT")) {
                this.putValue("CODE_CLIENT", clientRow.getString("CODE"));
            }
            this.putValue("DEBIT", ttcLongValue);
            this.putValue("CREDIT", Long.valueOf(0));
            ajoutEcriture();

            // TODO Gestion des factures d'acomptes
            // Solde des acomptes
            // List<SQLRow> rowsAcompte =
            // saisieRow.getReferentRows(saisieVFTable.getField("ID_SAISIE_VENTE_FACTURE_ACOMPTE"));
            // if (rowsAcompte != null && rowsAcompte.size() > 0) {
            // // Compte acompte
            // int idCompteAcompteClient = ComptePCESQLElement.getId("4191",
            // "Clients - Avances et acomptes reçus sur commandes");
            // int idTVAAcompte = ComptePCESQLElement.getId("44587",
            // "Taxes sur le chiffre d'affaire à régulariser ou en attente");
            // for (SQLRow sqlRow : rowsAcompte) {
            // long acompteTTC = sqlRow.getLong("T_TTC");
            // long acompteHT = sqlRow.getLong("T_HT");
            // this.putValue("ID_COMPTE_PCE", Integer.valueOf(idCompteAcompteClient));
            // this.putValue("DEBIT", acompteTTC);
            // this.putValue("CREDIT", Long.valueOf(0));
            // ajoutEcriture();
            // this.putValue("ID_COMPTE_PCE", Integer.valueOf(idCompteClient));
            // this.putValue("DEBIT", Long.valueOf(0));
            // this.putValue("CREDIT", acompteTTC);
            // ajoutEcriture();
            //
            // montantAcompteTTC += acompteTTC;
            //
            // long tva = acompteTTC - acompteHT;
            // if (tva > 0) {
            //
            //
            // this.putValue("ID_COMPTE_PCE", Integer.valueOf(idTVAAcompte));
            // this.putValue("DEBIT", Long.valueOf(0));
            // this.putValue("CREDIT", Long.valueOf(tva));
            // ajoutEcriture();
            //
            // Map<Integer, Long> m = getMultiTVAFromRow(saisieRow,
            // saisieVFTable.getTable("SAISIE_VENTE_FACTURE_ELEMENT"), true);
            // long allTaxe = 0;
            // for (Integer i : m.keySet()) {
            // Long l = m.get(i);
            // if (l != null && l > 0) {
            // // FIXME
            // int idCpt = i;
            // if (idCpt <= 1) {
            // idCpt = idCompteTVA;
            // }
            // this.putValue("ID_COMPTE_PCE", Integer.valueOf(idCpt));
            // this.putValue("DEBIT", Long.valueOf(0));
            // this.putValue("CREDIT", Long.valueOf(l));
            // ajoutEcriture();
            // allTaxe += l;
            // }
            // }
            // if (allTaxe < prixTVA.getLongValue()) {
            // this.putValue("ID_COMPTE_PCE", Integer.valueOf(idCompteTVA));
            // this.putValue("DEBIT", Long.valueOf(0));
            // this.putValue("CREDIT", Long.valueOf(prixTVA.getLongValue() - allTaxe));
            // ajoutEcriture();
            // }
            //
            // this.putValue("ID_COMPTE_PCE", Integer.valueOf(compteDebitTvaAcompte));
            // this.putValue("DEBIT", Long.valueOf(tva));
            // this.putValue("CREDIT", Long.valueOf(0));
            // ajoutEcriture();
            // }
            // }
            // }
        }

        {
            SQLRowValues valSasieVF = new SQLRowValues(GenerationMvtSaisieVenteFacture.saisieVFTable);
            valSasieVF.put("DATE_REGLEMENT", null);
            valSasieVF.update(this.idSaisieVenteFacture);
        }

            if (genereReglement) {
                // Génération du reglement
                SQLRow modeRegl = saisieRow.getForeignRow("ID_MODE_REGLEMENT");
                final SQLRow typeRegRow = modeRegl.getForeignRow("ID_TYPE_REGLEMENT");
                String label = this.nom + " (" + typeRegRow.getString("NOM") + ") " + StringUtils.limitLength(clientRow.getString("NOM"), 20);
                int idAvoir = saisieRow.getInt("ID_AVOIR_CLIENT");
                if (idAvoir > 1) {
                    // SQLRow avoirRow = base.getTable("AVOIR_CLIENT").getRow(idAvoir);
                    long l = ((Number) saisieRow.getObject("T_AVOIR_TTC")).longValue();
                    prixTTC = new PrixTTC(((Long) saisieRow.getObject("T_TTC")).longValue() - l);
                }
                prixTTC = new PrixTTC(saisieRow.getLong("NET_A_PAYER"));
                if (prixTTC.getLongValue() > 0) {
                    new GenerationReglementVenteNG(label.trim(), clientRow, prixTTC, this.date, modeRegl, saisieRow, mvtTable.getRow(idMvt));
                }
            }
        // Mise à jour de mouvement associé à la facture

        SQLRowValues valSasieVF = new SQLRowValues(GenerationMvtSaisieVenteFacture.saisieVFTable);
        valSasieVF.put("ID_MOUVEMENT", Integer.valueOf(this.idMvt));

        if (valSasieVF.getInvalid() == null) {
            valSasieVF.update(this.idSaisieVenteFacture);
            displayMvtNumber();
        }

    }

    public void run() {
        try {
            genereMouvement();
        } catch (Exception e) {
            ExceptionHandler.handle("Erreur pendant la générations des écritures comptables", e);

        }
    }
}