Esempio n. 1
0
def parse_afm(fil, enc="WINDOWS-1253"):
    EXCLUDE = (
        " " * 109 + "Σελίδα",
        " " * 44 + "Κατηγορία ",
        "  Oνομα / Επωνυμία ",
        "  ----------------------------------------- ",
    )
    SEPON = slice(2, 44)
    COD53 = slice(54, 66)
    SCOD2 = slice(56, 68)
    SAFM = slice(87, 96)
    # Create list with lines to exclude
    epo = cod = afm = ""
    by_code = defaultdict(lambda: {"eponymia": "", "afm": "", "syn_code": ""})
    ignore_next_line = False
    with open(fil, encoding=enc) as ofil:
        for lin in ofil:
            llin = len(lin)
            if llin < 60:  # 86:
                continue
            if lin.startswith(EXCLUDE):  # Exclude lines
                continue

            if llin > 86:
                epo = lin[SEPON].strip()
                cod = lin[COD53].strip()
                afm = lin[SAFM].strip()
                if cod.startswith("53."):
                    # if afm:
                    by_code[cod] = {
                        "eponymia": epo,
                        "afm": afm,
                        "syn_code": cod
                    }
                    ignore_next_line = True
                else:
                    ignore_next_line = False
            else:
                if ignore_next_line:
                    continue
                else:
                    cod = lin[SCOD2].strip()
                    # if afm:
                    by_code[cod] = {
                        "eponymia": epo,
                        "afm": afm,
                        "syn_code": cod
                    }
    logger.info(f"AFM data parsed without errors from {fil} !!!")
    return by_code
Esempio n. 2
0
def f2_render(head, data, html_file=None):  # , template=f2_template):
    """
    Render data to html
    """
    f2data = pre_render(head, calculate_f2(data))
    # with open(template) as fil:
    #     html_template = fil.read()
    # Create and fill all form fields with ''
    html_data = {i: "" for i in F2CODES}
    # Fill fields from f2data
    for key, val in f2data.items():
        if key in html_data.keys():
            html_data[key] = val
    # Finally save the form
    if html_file:
        with open(html_file, "w") as fout:
            fout.write(F2_HTML.format(**html_data))
        logger.info(f"fpa report saved to file: {html_file}")
    else:
        print(html_data)
Esempio n. 3
0
def parse_imerologio(fil: str, encoding="WINDOWS-1253") -> tuple:
    """Parses text file"""
    # Create list with lines to exclude
    EXC = (
        " " * 150 + "Σελίδα",
        " " * 33 + "ΓΕΝΙΚΟ ΗΜΕΡΟΛΟΓΙΟ",
        "  Ημ/νία      Α/Α ΚΒΣ Στοιχεία Αρθρου",
        "  Ημ/νία     Α/Α ΚΒΣ  Στοιχεία Αρθρου",
        "                      Σχετ. Παραστατ.",
        "  -----------------------------------",
        " " * 38 + "Από μεταφορά",
        " " * 123 + "-------------- --------------",
        " " * 70 + "Σύνολα Σελίδας",
        " " * 70 + "Σε Μεταφορά",
        " " * 70 + "Σύνολα Περιόδου",
        " " * 152,
    )
    dat = par = lmo = lmp = xre = pis = pe2 = per = ""
    tno = lno = 0
    SDAT = slice(2, 12)  # Ημερομηνία
    SPAR = slice(22, 48)  # Παραστατικό
    SLMO = slice(48, 60)  # Κωδικός λογαριασμού
    SLMP = slice(77, 122)  # Ονομασία λογαριασμού
    SXRE = slice(124, 137)  # Χρέωση
    SPIS = slice(139, 152)  # Πίστωση
    SPE2 = slice(22, 48)  # Έξτρα περιγραφή
    SPER = slice(48, -1)  # Περιγραφή
    dper = {}
    dlmo = {}
    trah = {}
    trad = {}
    arthra = defaultdict(list)
    unparsed_lines = {}
    with open(fil, encoding=encoding) as ofil:
        for i, lin in enumerate(ofil):
            llin = len(lin)  # Το υπολογίζω εδώ μία φορά
            # print(lin)
            if llin < 48:  # Δεν έχουν νόημα γραμμές μικρότερες του 48
                continue
            elif lin.startswith(EXC):  # Exclude lines
                continue
            elif llin < 132:  # Πρόκειται για γραμμή περιγραφής
                pe2 = lin[SPE2].strip()
                per = lin[SPER].strip()
                dper[tno] = {"perigrafi": per, "lineperigrafi": pe2}
            elif lin[50] == "." and lin[53] == "." and lin[134] == ",":
                if lin[4] == "/" and lin[7] == "/":
                    tno += 1
                    dat = date_gr2iso(lin[SDAT])
                    par = lin[SPAR].strip()
                    trah[tno] = {"date": dat, "parastatiko": par}
                lno += 1
                lmo = lin[SLMO].strip()
                lmp = lin[SLMP].strip()
                xre = gr2dec(lin[SXRE])
                pis = gr2dec(lin[SPIS])
                if lmo in dlmo:
                    if dlmo[lmo] != lmp:
                        if dlmo[lmo] and (not lmp):
                            pass
                        elif (not dlmo[lmo]) and lmp:
                            dlmo[lmo] = lmp
                        else:
                            logger.error(
                                f"Διαφορά στο όνομα {lmo}:  {dlmo[lmo]} -> {lmp}"
                            )
                else:
                    dlmo[lmo] = lmp
                trad[lno] = {
                    "id": tno,
                    "code": lmo,
                    "debit": xre,
                    "credit": pis
                }
                arthra[tno].append(lno)
            else:
                unparsed_lines[i] = lin
    if len(unparsed_lines) > 0:
        logger.error(f"parse_imerologio unparsed lines : {unparsed_lines}")
    else:
        logger.info(f"Transactions and accounts parsed fine from {fil} !!!")
    transactions = []
    for trid, header in trah.items():
        par_type, par_no = header["parastatiko"].split("--")
        tran = {
            "id": trid,
            "date": header["date"],
            "partype": par_type,
            "parno": par_no,
            "perigrafi": dper[trid]["perigrafi"],
            "perigr2": dper[trid]["lineperigrafi"],
            "lines": [],
        }
        tdebit = tcredit = 0
        is_ee = False
        for idd in arthra[trid]:
            tdebit += trad[idd]["debit"]
            tcredit += trad[idd]["credit"]
            typ = val = 0
            if trad[idd]["debit"] == 0:
                typ = 2
                val = trad[idd]["credit"]
            elif trad[idd]["credit"] == 0:
                typ = 1
                val = trad[idd]["debit"]
            if typ == 0:
                raise ValueError(f"{trad[idd]} debit or credit")
            tran["lines"].append({
                "account": trad[idd]["code"],
                "typ": typ,
                "value": val
            })
            if trad[idd]["code"][0] in "1267":
                is_ee = True
        if tdebit != tcredit:
            raise ValueError(f"Transaction {tran} is not balanced")
        tran["total"] = tdebit
        tran["is_ee"] = is_ee
        transactions.append(tran)
    logger.debug("About to return parsed transactions and accounts!!!")
    return transactions, dlmo
Esempio n. 4
0
def parse_esex(fil, enc="WINDOWS-1253"):
    # Create list with lines to exclude
    logger.debug(f"Starting to parse {fil} file")
    EXC = (
        " " * 164 + "Σελίδα",
        "   Κινήσεις ανά Ημέρα",
        "     A/A Τύπος Εγγραφής",
        "-------- ------------------------- ",
        "   Σύνολα ημέρας",
        " " * 92 + "-------------------- -------------------- ",
        " " * 53 + "Σύνολα Εξόδων",
        " " * 53 + "Σύνολα Εξόδων",
        "  Γενικά Σύνολα",
        " " * 53 + "Εξόδων",
    )
    SDAT = slice(32, 42)  # Ημερομηνία
    SAA = slice(0, 8)  # Αριθμός άρθρου
    STYP = slice(9, 34)  # Τύπος
    SPAR = slice(35, 66)  # Παραστατικό
    SAFM = slice(67, 76)  # ΑΦΜ
    SLMO = slice(67, 91)  # όλο το πεδίο άν δεν υπάρχει ΑΦΜ
    SLMP = slice(77, 91)  # μόνο μετά το ΑΦΜ
    SVAL = slice(93, 112)  # Καθαρή αξία
    SFPA = slice(114, 133)  # ΦΠΑ
    STOT = slice(156, 175)  # Σύνολο
    dat = typ = par = per = afm = ""
    aar = val = fpa = tot = 0
    lines = []
    lines3 = defaultdict(lambda: defaultdict(lambda: {"afm": ""}))
    types = set()
    with open(fil, encoding=enc) as ofil:
        for lin in ofil:
            llin = len(lin)
            if llin < 40:
                continue
            elif lin.startswith(EXC):  # Exclude lines
                continue
            elif lin.startswith("  Κινήσεις της "):
                # print(lin)
                dat = date_gr2iso(lin[SDAT])
            elif lin[109] == "," and lin[130] == "," and lin[151]:
                aar = int(lin[SAA].strip())
                typ = lin[STYP].strip()
                ee = ESEJ[typ]
                par = lin[SPAR].strip()
                # afm = lin[SAFM].strip()
                # if is_afm(afm):
                #     per = lin[SLMP].strip()
                csy = ""

                afm, *per = lin[SLMO].strip().split()
                per = " ".join(per)
                # afm = '000000000'
                val = gr2dec(lin[SVAL])
                fpa = gr2dec(lin[SFPA])
                tot = gr2dec(lin[STOT])
                partyp, parno = par.split()
                lines.append({
                    "id": aar,
                    "date": dat,
                    "type": typ,
                    "ee": ee,
                    "partyp": partyp,
                    "parno": parno,
                    "perigrafi": per,
                    "afm": afm,
                    "syn_code": csy,
                    "value": val,
                    "fpa": fpa,
                    "total": tot,
                })
                lines3[dat][parno] = {"afm": afm, "value": val, "fpa": fpa}
                types.add(typ)
    logger.info(f"ee lines and types parsed without errors from {fil} !!!")
    return lines3, types
Esempio n. 5
0
    def myf_xml(self,
                exclude=None,
                only=None,
                koybas=(),
                rfpa=(),
                action="replace"):
        """
        Συγκεντρωτικές τιμολογίων πελατών/προμηθευτών σε xml
        """
        data = {
            "action": action,
            "co": {
                "afm": self.afm,
                "month": "12",
                "year": self.year,
                "branch": self.branch,
            },
            "gcash": [],
            "oexpenses": {},
        }
        dat = "2020-12-31"
        di1 = {}
        di2 = {}
        di6 = {}
        di7 = {}
        cre = "credit"
        nor = "normal"
        tam = {"tamNo": "", "amount": 0, "tax": 0, "date": dat}
        reversed_afm = set()
        for trn in self.ee_book():
            # first we filter records
            if only:
                if not startswith_any(trn["accounts"], only):
                    continue
            if exclude:
                if startswith_any(tuple(trn["accounts"]), exclude):
                    continue

            afm = trn["afm"]

            if trn["typos"] == "1":
                pass

            elif trn["typos"] in "26":
                # Εάν έχουμε λογαριασμούς χωρίς έκπτωση φπα, επειδή οι
                # εγγραφές είναι συνολικές θα πρέπει πρωτού προχωρήσουμε
                # να αποφορολογήσουμε
                if any(i in rfpa for i in trn["accounts"]):
                    if trn["fpa"] == 0:
                        val = dec(trn["value"] / dec(1.24))
                        trn["fpa"] = trn["value"] - val
                        trn["value"] = val
                        reversed_afm.add(afm)

                # Προμηθευτές σε κουβά (πχ ΔΕΗ)
                if afm in koybas:
                    data["oexpenses"]["amount"] = data["oexpenses"].get(
                        "amount", 0)
                    data["oexpenses"]["amount"] += trn["value"]
                    data["oexpenses"]["tax"] = data["oexpenses"].get("tax", 0)
                    data["oexpenses"]["tax"] += trn["fpa"]
                    data["oexpenses"]["date"] = data["oexpenses"].get(
                        "date", dat)
                    continue
                if len(afm) < 9:
                    raise ValueError(f"There is an error in {trn}")
                # Διαφορετικά κανονικά ανά ΑΦΜ/normal-credit
                di6[afm] = di6.get(afm, {})
                if trn["value"] >= 0:
                    di6[afm][nor] = di6[afm].get(
                        nor,
                        {
                            "afm": afm,
                            "amount": 0,
                            "tax": 0,
                            "note": nor,
                            "invoices": 0,
                            "date": dat,
                            "nonObl": 0,
                        },
                    )
                    di6[afm][nor]["amount"] += trn["value"]
                    di6[afm][nor]["tax"] += trn["fpa"]
                    di6[afm][nor]["invoices"] += 1
                else:
                    di6[afm][cre] = di6[afm].get(
                        cre,
                        {
                            "afm": afm,
                            "amount": 0,
                            "tax": 0,
                            "note": cre,
                            "invoices": 0,
                            "date": dat,
                            "nonObl": 0,
                        },
                    )
                    di6[afm][cre]["amount"] -= trn["value"]
                    di6[afm][cre]["tax"] -= trn["fpa"]
                    di6[afm][cre]["invoices"] += 1

            elif trn["typos"] == "7":
                if afm == "":
                    tam["amount"] += trn["value"]
                    tam["tax"] += trn["fpa"]
                else:
                    di7[afm] = di7.get(afm, {})
                    if trn["value"] >= 0:
                        di7[afm][nor] = di7[afm].get(
                            nor,
                            {
                                "afm": afm,
                                "amount": 0,
                                "tax": 0,
                                "note": nor,
                                "invoices": 0,
                                "date": dat,
                            },
                        )
                        di7[afm][nor]["amount"] += trn["value"]
                        di7[afm][nor]["tax"] += trn["fpa"]
                        di7[afm][nor]["invoices"] += 1
                    else:
                        di7[afm][cre] = di7[afm].get(
                            cre,
                            {
                                "afm": afm,
                                "amount": 0,
                                "tax": 0,
                                "note": cre,
                                "invoices": 0,
                                "date": dat,
                            },
                        )
                        di7[afm][cre]["amount"] -= trn["value"]
                        di7[afm][cre]["tax"] -= trn["fpa"]
                        di7[afm][cre]["invoices"] += 1

            else:
                raise ValueError("Αδύνατη περίπτωση !!!")
        logger.info(f"Λογαριασμοί που εξαιρούνται σπό τη ΜΥΦ: {exclude}")
        logger.info(f"ΜΥΦ μόνο για λογαριασμούς: {only}")
        logger.info(f"ΑΦΜ για κουβά εξόδων: {koybas}")
        logger.info(f"Λογαριασμοί για αντιστροφή ΦΠΑ: {rfpa}")
        logger.info(f"ΑΦΜ που έγινε αντιστροφή ΦΠΑ: {reversed_afm}")
        # Έχουμε πλέον τα σύνολα ανα ομάδα
        gexpenses = []
        for afm, decre in sorted(di2.items()):
            for _, val in decre.items():
                val["amount"] = dec2grp(val["amount"])
                val["tax"] = dec2grp(val["tax"])
                gexpenses.append(val)
        # ΕΛΛΗΝΙΚΟ format ΑΡΙΘΜΩΝ
        # Εγγραφές χωρίς έκπτωση του ΦΠΑ επαναφορά
        for afm, decre in sorted(di6.items()):
            for _, val in decre.items():
                val["amount"] = dec2grp(val["amount"])
                val["tax"] = dec2grp(val["tax"])
                gexpenses.append(val)
        data["gexpenses"] = gexpenses

        grevenues = []
        for afm, decre in sorted(di7.items()):
            for _, val in decre.items():
                val["amount"] = dec2grp(val["amount"])
                val["tax"] = dec2grp(val["tax"])
                grevenues.append(val)
        data["grevenues"] = grevenues
        # Mόνο όταν υπάρχουν τιμές στο gcash
        if tam["amount"] != 0:
            tam["amount"] = dec2grp(tam["amount"])
            tam["tax"] = dec2grp(tam["tax"])
            data["gcash"].append(tam)
        # Μόνο όταν υπάρχουν τιμές στο oexpenses
        if data["oexpenses"]:
            data["oexpenses"]["amount"] = dec2grp(data["oexpenses"]["amount"])
            data["oexpenses"]["tax"] = dec2grp(data["oexpenses"]["tax"])
        return data