Browse Source

le résultat de sqlalchemy est à l'équivalent des requetes sql brutes (avec plus de description)

Philippe Le Brouster 9 years ago
parent
commit
679703a43a
3 changed files with 384 additions and 20 deletions
  1. 1 1
      bin/himport
  2. 107 3
      himports/dolibarrAlchemy.py
  3. 276 16
      himports/dolibarrAlchemyHledger.py

+ 1 - 1
bin/himport

@@ -144,7 +144,7 @@ def do_sqlalchemy(options):
         print "WARNING: poste comptable manquant"
         for pc in pc_missing:
             sys.stdout.write("%s\n" % (pc))
-    
+ 
     # On ecrie les fichiers hledger
     Writer.write("bank", bank_journal)
     Writer.write("sells", sell_journal)

+ 107 - 3
himports/dolibarrAlchemy.py

@@ -105,6 +105,8 @@ class CotisationsSociales(Base):
     __tablename__ = "llx_chargesociales"
     id = Column("rowid", Integer, primary_key=True)
 
+    amount = Column(Float)
+
     fk_type = Column('fk_type', Integer, ForeignKey('llx_c_chargesociales.id'))
     type = relationship(
         "CCotisationsSociales", backref="cotisations_sociales",
@@ -143,9 +145,27 @@ class Societe(Base):
     id = Column("rowid", Integer, primary_key=True)
 
 
+class PaiementFacture(Base):
+    __tablename__ = "llx_paiement_facture"
+    fk_paiement = Column(Integer, ForeignKey('llx_paiement.rowid'), primary_key=True)
+    fk_facture = Column(Integer, ForeignKey('llx_facture.rowid'), primary_key=True)
+    facture = relationship(
+        "Facture",
+        lazy="subquery",
+    )
+    paiement = relationship(
+        "Paiement",
+        lazy="subquery",
+    )
+
+
 class Paiement(Base):
     __tablename__ = "llx_paiement"
     id = Column("rowid", Integer, primary_key=True)
+    factures = relationship(
+        "PaiementFacture",
+        lazy="subquery",
+    )
 
 
 class PaiementFournFactureFourn(Base):
@@ -195,16 +215,77 @@ class Product(Base):
 class FactureFourn(Base):
     __tablename__ = "llx_facture_fourn"
     id = Column("rowid", Integer, primary_key=True)
+    total_ht = Column(Float)
+    total_ttc = Column(Float)
+    total_tva = Column(Float)
+
+    fk_soc = Column(Integer, ForeignKey('llx_societe.rowid'))
+    societe = relationship(
+        'Societe',
+        backref="factures_fournisseurs",
+        lazy="subquery",
+    )
+    
+    details = relationship(
+        'FactureFournDet',
+        lazy="subquery",
+    )
+
+
+class Facture(Base):
+    __tablename__ = "llx_facture"
+    id = Column("rowid", Integer, primary_key=True)
+    total = Column(Float)
+    total_ttc = Column(Float)
+    tva = Column(Float)
+
+    fk_soc = Column(Integer, ForeignKey('llx_societe.rowid'))
+    societe = relationship(
+        'Societe',
+        backref="factures",
+        lazy="joined",
+    )
+
+    details = relationship(
+        'FactureDet',
+        lazy="subquery",
+    )
 
 
 class FactureDet(Base):
     __tablename__ = "llx_facturedet"
     id = Column("rowid", Integer, primary_key=True)
+    total_ht = Column(Float)
+    total_ttc = Column(Float)
+    total_tva = Column(Float)
+
+    fk_facture = Column(Integer, ForeignKey('llx_facture.rowid'))
+    facture = relationship(
+        'Facture',
+        lazy="subquery",
+    )
+
+    fk_product = Column(Integer, ForeignKey('llx_product.rowid'))
+    product = relationship(
+        'Product',
+        backref="facture_det",
+        lazy="subquery",
+    )
+
+    fk_code_ventilation = Column(Integer, ForeignKey('llx_accountingaccount.rowid'))
+    accounting_account = relationship(
+        'AccountingAccount',
+        backref="facture_det",
+        lazy="subquery",
+    )
 
 
 class FactureFournDet(Base):
     __tablename__ = "llx_facture_fourn_det"
     id = Column("rowid", Integer, primary_key=True)
+    total_ht = Column(Float)
+    total_ttc = Column(Float)
+    tva = Column(Float)
 
     fk_facture_fourn = Column(Integer, ForeignKey('llx_facture_fourn.rowid'))
     facture = relationship(
@@ -212,6 +293,25 @@ class FactureFournDet(Base):
         lazy="subquery",
     )
 
+    fk_product = Column(Integer, ForeignKey('llx_product.rowid'))
+    product = relationship(
+        'Product',
+        backref="facture_fourn_det",
+        lazy="subquery",
+    )
+
+    fk_code_ventilation = Column(Integer, ForeignKey('llx_accountingaccount.rowid'))
+    accounting_account = relationship(
+        'AccountingAccount',
+        backref="facture_fourn_det",
+        lazy="subquery",
+    )
+
+
+class AccountingAccount(Base):
+    __tablename__ = "llx_accountingaccount"
+    id = Column("rowid", Integer, primary_key=True)
+
 
 MYSQL_QUERIES = {
     "bank": """SELECT DISTINCT b.rowid as b_rowid,
@@ -289,9 +389,13 @@ MYSQL_QUERIES = {
                   p.ref as p_ref,
                   p.label as p_label,
                   p.accountancy_code_sell as p_accountancy_code_sell,
-                  a.account_number as a_account_number FROM llx_societe as s LEFT JOIN llx_c_pays as c on s.fk_pays = c.rowid,
-                  llx_facture as f LEFT JOIN llx_facture_extrafields as extra ON f.rowid = extra.fk_object ,
-                  llx_facturedet as fd LEFT JOIN llx_product as p on (fd.fk_product = p.rowid) LEFT JOIN llx_accountingaccount as a ON fd.fk_code_ventilation = a.rowid WHERE f.fk_soc = s.rowid AND f.rowid = fd.fk_facture AND f.entity = 1""",
+                  a.account_number as a_account_number 
+                FROM llx_societe as s 
+                LEFT JOIN llx_c_pays as c on s.fk_pays = c.rowid, llx_facture as f 
+                LEFT JOIN llx_facture_extrafields as extra ON f.rowid = extra.fk_object , llx_facturedet as fd 
+                LEFT JOIN llx_product as p on (fd.fk_product = p.rowid) 
+                LEFT JOIN llx_accountingaccount as a ON fd.fk_code_ventilation = a.rowid 
+                WHERE f.fk_soc = s.rowid AND f.rowid = fd.fk_facture AND f.entity = 1""",
 
     "suppliers": """SELECT DISTINCT s.rowid as s_rowid,
                   s.nom as s_nom,

+ 276 - 16
himports/dolibarrAlchemyHledger.py

@@ -17,9 +17,16 @@ class HledgerEntry(object):
 
     sql_class = None
 
+    # Date permettant de déterminer dans quel exercice comptable
+    # l'écriture doit se trouver
+    k_accounting_date = None
+
     def __init__(self, e):
         super(HledgerEntry, self).__init__()
         self.e = e
+        self.accounting_date = e
+        for attr in self.k_accounting_date.split('.'):
+            self.accounting_date = getattr(self.accounting_date, attr)
 
     @classmethod
     def get_entries(cls, session):
@@ -37,6 +44,8 @@ class HledgerEntry(object):
 
     def get_accounting_year(self):
         date = self.accounting_date
+        if isinstance(date, datetime.datetime):
+            date = date.date()
         for (year, dbegin, dend) in HledgerEntry.accounting_years:
             if date >= dbegin and date <= dend:
                 return year
@@ -72,11 +81,8 @@ class HledgerJournal(object):
 
 class HledgerBankEntry(HledgerEntry):
     sql_class = Bank
+    k_accounting_date = 'datev'
     
-    def __init__(self, e):
-        super(HledgerBankEntry, self).__init__(e)
-        self.accounting_date = e.datev
-
     def get_third_code(self):
         e = self.e
 
@@ -98,18 +104,41 @@ class HledgerBankEntry(HledgerEntry):
 
         return third_code
 
-    def get_ledger(self):
+    def get_description(self):
         e = self.e
-        s = ""
+        s_nom = ""
+        s_description = ""
 
         if e.url_company:
             s_nom = e.url_company.societe.nom
-        else:
-            s_nom = ""
+
+        if e.url_payment_supplier:
+            f_ids = [f.facture.ref_supplier for f in e.url_payment_supplier.payment_supplier.factures]
+            s_description = "Règlement facture fournisseur - %s - %s" % (
+                s_nom,
+                "|".join(f_ids),
+            )
+        if e.url_payment:
+            f_ids = [f.facture.facnumber for f in e.url_payment.payment.factures]
+            s_description = "Règlement facture client - %s - %s" % (
+                s_nom,
+                "|".join(f_ids),
+            )
+
+        if s_description == "":
+            s_description = s_nom + " - " + e.label
+
+        return s_description
+
+    def get_ledger(self):
+        e = self.e
+        s = ""
+
+        s_description = self.get_description()
 
         s += "%(date)s    %(description)s\n" % {
             'date': e.datev.strftime("%Y/%m/%d"),
-            'description': s_nom + " - " + e.label
+            'description': s_description
         }
 
         third_code = self.get_third_code()
@@ -129,27 +158,258 @@ class HledgerBankEntry(HledgerEntry):
             'account': settings.get_ledger_account(ba_code),
             'amount': -e.amount
         }
-        print s
         return s
 
     @classmethod
     def get_entries(cls, session):
-        return [HledgerBankEntry(b) for b in session.query(cls.sql_class).order_by(Bank.datev,Bank.num_releve).filter(Bank.num_releve != "").all() ]
+        return [cls(e) for e in session.query(cls.sql_class).order_by(Bank.datev, Bank.num_releve).filter(Bank.num_releve != "").all()]
 
 
 class HledgerSupplierEntry(HledgerEntry):
-    sql_class = FactureFournDet
-    pass
+    sql_class = FactureFourn
+    k_accounting_date = 'datef'
+
+    @classmethod
+    def get_entries(cls, session):
+        return [cls(e) for e in session.query(cls.sql_class).order_by(FactureFourn.datef).all()]
+
+    def check(self):
+        e = self.e
+
+        total_ttc = e.total_ttc
+        total_tva = e.total_tva
+        total_ht = e.total_ht
+
+        for ed in e.details:
+            total_ttc -= ed.total_ttc
+            total_tva -= ed.tva
+            total_ht -= ed.total_ht
+
+        if total_ttc > 1e-10:
+            print "Erreur dans l'écriture %s: total ttc = %s" % (e.ref_supplier, total_ttc)
+        if total_ht > 1e-10:
+            print "Erreur dans l'écriture %s: total ht = %s" % (e.ref_supplier, total_ht)
+        if total_tva > 1e-10:
+            print "Erreur dans l'écriture %s: total tva = %s" % (e.ref_supplier, total_tva)
+
+    def getMissingPC(self):
+        pc_missing = []
+        if e.societe.code_compta_fournisseur == "":
+            pc_missing.append("tiers:fournisseur: %s %s" % (e.societe.nom, s.societe.ape))
+
+        for ed in e.details:
+            if self.get_product_account_code(ed) == self.pc_default_charge:
+                pc_missing.append("achat: %s - %s" % (e.ref_supplier, ed.description.splitlines()[0]))
+
+        return pc_missing
+
+    def get_ledger(self):
+        e = self.e
+        self.check()
+
+        s = ""
+        s += "%(date)s  %(description)s\n" % {
+            'date':  e.datef.strftime("%Y/%m/%d"),
+            'description': e.ref_supplier + " - " + e.societe.nom,
+        }
+
+        s_code = self.get_supplier_code()
+        s += "    %(compte_tiers)s    %(amount_ttc)s\n" % {
+            'compte_tiers': settings.get_ledger_account(s_code),
+            'amount_ttc': e.total_ttc,
+        }
+
+        if e.total_tva != 0:
+            if s_code.startswith("2"):
+                tva_account = settings.get('PC_REFS')['tva_deductible']
+            else:
+                tva_account = settings.get('PC_REFS')['tva_deductible_immo']
+            s += "    %(compte_tva)s  %(amount_tva)s\n" % {
+                'compte_tva': settings.get_ledger_account(tva_account),
+                'amount_tva': -e.total_tva,
+            }
+
+        for ed in e.details:
+            p_code = self.get_product_account_code(ed)
+            s += "    %(compte_produit)s   %(amount_ht)s\n" % {
+                'compte_produit': settings.get_ledger_account(p_code),
+                'amount_ht': -ed.total_ht
+            }
+        return s
+
+    def get_product_account_code(self, ed):
+        p_code = ""
+        if ed.accounting_account:
+            p_code = ed.accounting_account.account_number
+        elif ed.product:
+            p_code = ed.product.accountancy_code_buy
+        else:
+            p_code = self.pc_default_charge
+        return p_code
+    
+    def get_supplier_code(self):
+        e = self.e
+        s_code = e.societe.code_compta_fournisseur
+        if s_code == "":
+            s_code = self.pc_default_supplier
+        return s_code
+
 
 
 class HledgerSellEntry(HledgerEntry):
-    sql_class = FactureDet
-    pass
+    sql_class = Facture
+    k_accounting_date = 'datef'
+
+    @classmethod
+    def get_entries(cls, session):
+        return [cls(e) for e in session.query(cls.sql_class).order_by(Facture.datef).all()]
+
+    def get_ledger(self):
+        e = self.e
+        self.check()
+        s = ""
+        s += "%(date)s  %(description)s\n" % {
+            'date':  e.datef.strftime("%Y/%m/%d"),
+            'description': e.facnumber + " - " + e.societe.nom,
+        }
+
+        s_code = self.get_client_code()
+        s += "    %(compte_tiers)s    %(amount_ttc)s\n" % {
+            'compte_tiers': settings.get_ledger_account(s_code),
+            'amount_ttc': -e.total_ttc,
+
+        }
+
+        if float(e.tva) != 0:
+            tva_account = settings.get('PC_REFS')['tva_collecte']
+            s += "    %(compte_tva_collecte)s  %(amount_tva)s\n" % {
+                'compte_tva_collecte': settings.get_ledger_account(tva_account),
+                'amount_tva': e.tva,
+            }
+
+        for ed in e.details:
+            p_code = self.get_product_account_code(ed)
+            s += "    %(compte_produit)s   %(amount_ht)s\n" % {
+                'compte_produit': settings.get_ledger_account(p_code),
+                'amount_ht': ed.total_ht
+            }
+        return s
+
+    def getMissingPC(self):
+        e = self.e
+        pc_missing = []
+        if e.societe.code_compta == "":
+            pc_missing.append("tiers: %s %s" % (e.societe.nom, s.societe.ape))
+
+        for ed in e.details:
+            if self.get_product_account_code(ed) == self.pc_default_produit:
+                if ed.description != "":
+                    description = ed.description.splitlines()[0]
+                else:
+                    description = ed.description
+                pc_missing.append("produit: %s - %s - %s" % (e.societe.nom, e.facnumber, description))
+
+        return pc_missing
+
+    def get_product_account_code(self, ed):
+        p_code = ""
+        if ed.accounting_account:
+            p_code = ed.accounting_account.account_number
+        elif ed.product:
+            p_code = ed.product.accountancy_code_sell
+        else:
+            p_code = self.pc_default_produit
+        return p_code
+
+    def get_client_code(self):
+        e = self.e
+        s_code = e.societe.code_compta
+        if s_code == "":
+            s_code = self.pc_default_client
+        return s_code
+
+    def check(self):
+        e = self.e
+        total_ttc = e.total_ttc
+        total_tva = e.tva
+        total_ht = e.total
+
+        for ed in e.details:
+            total_ttc -= ed.total_ttc
+            total_tva -= ed.total_tva
+            total_ht -= ed.total_ht
+
+        if total_ttc > 1e-10:
+            print "Erreur dans l'écriture %s: total ttc = %s" % (e.facnumber, total_ttc)
+        if total_ht > 1e-10:
+            print "Erreur dans l'écriture %s: total ht = %s" % (e.facnumber, total_ht)
+        if total_tva > 1e-10:
+            print "Erreur dans l'écriture %s: total tva = %s" % (e.facnumber, total_tva)
 
 
 class HledgerSocialEntry(HledgerEntry):
     sql_class = CotisationsSociales
-    pass
+    k_accounting_date = 'date_ech'
+    
+    @classmethod
+    def get_entries(cls, session):
+        return [cls(e) for e in session.query(cls.sql_class).order_by(CotisationsSociales.date_ech).all()]
+
+    def get_third_code(self):
+        e = self.e
+        third_code = ""
+        if e.type.code in settings.get('SOCIAL_REFS'):
+            third_code = settings.get('SOCIAL_REFS')[e.type.code]
+        if third_code == "":
+            third_code = self.pc_default_supplier
+        return third_code
+
+    def get_social_code(self):
+        e = self.e
+        s_code = ""
+        if e.type:
+            s_code = e.type.accountancy_code
+        if s_code == "":
+            s_code = self.pc_default_charge
+        return s_code
+    
+    def getMissingPC(self):
+        pc_missing = []
+        if self.get_social_code() == self.pc_default_charge:
+            pc_missing.append("charges: %s" % (e.libelle))
+
+        if self.get_third_code() == self.pc_default_supplier:
+            pc_missing.append("tiers: %s (%s)" % (e.libelle, e.type.code))
+
+        return pc_missing
+
+    def get_ledger(self):
+        e = self.e
+
+        s = ""
+
+        s += "%(date)s    %(description)s\n" % {
+            'date': e.date_ech.strftime("%Y/%m/%d"),
+            'description': e.libelle + " - " + e.type.libelle
+        }
+
+        third_code = self.get_third_code()
+        s_code = self.get_social_code()
+
+        s += "    %(account)s \t %(amount)s\n" % {
+            'account': settings.get_ledger_account(third_code),
+            'amount': e.amount
+        }
+
+        s += "    %(account)s \t %(amount)s\n" % {
+            'account': settings.get_ledger_account(s_code),
+            'amount': -e.amount
+        }
+
+        return s
+
+    def check(self):
+        e = self.e
 
 
 class HledgerDolibarrSQLAlchemy(DolibarrSQLAlchemy):