Exemplo n.º 1
0
def conv_last_usd_val_to_home_curr(asset_guid: str) -> int:
    """ Convert last known value to USD then project as TRY """
    result = 0
    assets = imp_asset.get_assets()["assets"]

    for asset in assets:
        if asset["guid"] != asset_guid:
            continue
        if "value_history" not in asset:
            break
        values = asset["value_history"]
        last_val = values[len(values) - 1]
        last_date = parse_json_date(last_val["date"])

        historic_curr_conv = OldCurrencyConverter(last_date)
        today_curr_conv = CurrencyConverter()

        last_val_usd = \
            historic_curr_conv.convert_to_foreign_currency(
                last_val["value"],
                foreign_currency=_FOREIGN_CURR)

        result = \
            today_curr_conv.convert_to_local_currency(
                foreign_amount=last_val_usd,
                foreign_currency=_FOREIGN_CURR)

        break

    return int(result)
Exemplo n.º 2
0
def get_plan_list() -> List:
    """ Plan values """
    conv = CurrencyConverter()
    out = get_subject_list()
    fiscal = _get_latest_fiscal_file_content()
    for subject in out:
        subject["monthly_plan_amount"] = 0
        subject["annual_plan_amount"] = 0
        subject["currency"] = config.CONSTANTS["HOME_CURRENCY"]
        subject["currency_symbol"] = config.CONSTANTS["HOME_CURRENCY_SYMBOL"]

        if "plans" in fiscal:
            for plan in fiscal["plans"]:
                if subject["domain"] == plan["domain"] and subject[
                        "subject"] == plan["subject"]:
                    json_amount = conv.convert_to_local_currency(
                        plan["amount"], plan["currency"])
                    if plan["period"] == "month":
                        monthly_amount = json_amount / plan["frequency"]
                        annual_amount = json_amount * (12 / plan["frequency"])
                    elif plan["period"] == "year":
                        monthly_amount = json_amount / (12 * plan["frequency"])
                        annual_amount = json_amount / plan["frequency"]
                    else:
                        raise Exception(
                            f"Unknown budget period: {plan['period']}")
                    subject["monthly_plan_amount"] = monthly_amount
                    subject["annual_plan_amount"] = annual_amount
                    break

    return out
Exemplo n.º 3
0
def get_asset_type_resale_value_sum(only_liquid: bool = False,
                                    deduct_income_tax: bool = False,
                                    own_percentage_only: bool = False) -> List:
    """ Asset type resale value sum
    Used when calculating net worth
    """
    result = []

    assets = get_assets(deduct_income_tax=deduct_income_tax,
                        own_percentage_only=own_percentage_only)
    currency_converter = CurrencyConverter()

    for asset in assets["assets"]:
        if only_liquid and not is_liquid(asset["type"]):
            continue

        asset_unit_value = currency_converter.convert_to_local_currency(
            asset["sales_value"], asset["currency"])
        asset_value = asset_unit_value * asset["quantity"]

        found = False
        for res in result:
            if res["type"] == asset["type"]:
                res["sales_value"] = res["sales_value"] + asset_value
                found = True

        if not found:
            res = {"type": asset["type"], "sales_value": asset_value}
            result.append(res)

    return result
Exemplo n.º 4
0
def get_current_account_balance_sum() -> float:
    """ Returns money in banks in home currency """
    amount = 0
    accounts = get_bank_accounts()
    currency_converter = CurrencyConverter()

    for account in accounts["bank_accounts"]:
        amount += currency_converter.convert_to_local_currency(
            account["balance"], account["currency"])

    return amount
Exemplo n.º 5
0
    def __init__(self):
        self._tax_rates = []

        self._default_tax_rate = 0
        self._default_tax_rate_calculated = False

        self._tmp_tax_rate = 0
        self._tmp_tax_rate_calculated = False

        self._forecast_tax_rate = 0
        self._forecast_tax_rate_calculated = False

        self._converter = CurrencyConverter()
        self._read_tax_rates()
Exemplo n.º 6
0
    def open_amount(self) -> tuple:
        """ Open amount """
        if self.cleared:
            return 0, self.currency

        open_amount, open_currency = self.amount
        currency_conv = CurrencyConverter()

        for coll in self.collections:
            coll_amount, coll_curr = coll.amount
            converted_coll_amount = currency_conv.convert_to_currency(
                coll_amount, coll_curr, open_currency)
            open_amount -= converted_coll_amount

        return open_amount, open_currency
Exemplo n.º 7
0
def record_vat_payment(vat_guids: List, paid_amount: float, paid_curr: str):
    """ Records a new VAT payment """
    paid_vats = []
    all_vats = get_open_vat_payments()
    curr_conv = CurrencyConverter()
    vat_amount = 0

    for pay in all_vats:
        if pay.guid in vat_guids:
            paid_vats.append(pay)

    for pay in paid_vats:
        pay.generate_very_long_term_recurrences()
        debt_amount, debt_curr = pay.open_amount

        debt_amount_conv = curr_conv.convert_to_currency(
            from_amount=debt_amount,
            from_currency=debt_curr,
            to_currency=paid_curr)

        vat_amount += debt_amount_conv
        sch = pay.scheme
        recs = sch.recurrences
        if len(recs) != 1:
            raise Exception("Unexpected VAT scheme")
        rec = recs[0]

        coll_dict = {
            "date": datetime.datetime.now().isoformat(),
            "description": "KDV ödemesi",
            "amount": paid_amount,
            "currency": paid_curr
        }

        coll = Collection(coll_dict)
        rec.add_collection(coll)
        rec.cleared = True

        sch.recurrences = recs
        pay.scheme = sch
        pay.cleared = True

    if vat_amount > paid_amount:
        investable_amount = vat_amount - paid_amount
        record_investment_payment(investable_amount, paid_curr, "VAT surplus")

    for pay in paid_vats:
        pay.save()
Exemplo n.º 8
0
def record_investment_payment(investable_amount: float, paid_curr: str,
                              description_prefix: str):
    """ Records a new investment payment into the most suitable account """
    # Get investable amount
    investable_amount = CurrencyConverter().convert_to_local_currency(
        investable_amount, paid_curr)

    # Pay credit card debts
    if config.CONSTANTS["PAY_CREDIT_DEBT_BEFORE_INVESTMENT"]:
        credit_card_debts = get_credit_card_debts()
        for cc_debt in credit_card_debts.debts:
            if investable_amount < cc_debt.amount:
                payable_amount = investable_amount
                investable_amount = 0
            else:
                payable_amount = cc_debt.amount
                investable_amount -= payable_amount

            create_credit_card_transaction(cc_debt.bank_name,
                                           description_prefix,
                                           cc_debt.card_name, payable_amount)

            if investable_amount <= 0:
                return

    if investable_amount <= 0:
        return

    # Invest
    investments = InvestmentAdviser().advise(investable_amount)

    for inv in investments:
        _create_investment_transaction(inv["bank"], description_prefix,
                                       inv["account"], inv["account"],
                                       inv["amount"])
Exemplo n.º 9
0
def get_credit_card_debts() -> CreditCardDebtList:
    """ Returns all credit card debts """
    output = CreditCardDebtList(config.CONSTANTS["HOME_CURRENCY"])
    credit_cards = get_credit_cards()
    currency_converter = CurrencyConverter()

    for credit_card in credit_cards["credit_cards"]:
        debt = credit_card["credit_limit"] - credit_card["usable_limit"]
        if debt <= 0:
            continue
        local_debt = currency_converter.convert_to_local_currency(
            debt, credit_card["currency"])
        cc_debt = CreditCardDebt(credit_card["bank_name"],
                                 credit_card["card_name"], local_debt)
        output.debts.append(cc_debt)

    return output
Exemplo n.º 10
0
def get_reserved_balance() -> float:
    """ Returns the reserved bank account balance """
    output = 0
    home_curr = config.CONSTANTS["HOME_CURRENCY"]
    curr_conv = CurrencyConverter()

    for bank_account in get_bank_accounts()["bank_accounts"]:
        if not "reserved" in bank_account:
            continue
        for balance in bank_account["reserved"]:
            reserved_amt = balance["amount"] \
                            if bank_account["currency"] == home_curr \
                            else curr_conv.convert_to_local_currency( balance["amount"],
                                                                      bank_account["currency"])

            output += reserved_amt

    return output
Exemplo n.º 11
0
    def open_amount(self) -> tuple:
        """ Payment open amount """
        currency_conv = CurrencyConverter()
        scheme = self.scheme

        open_amount, open_currency = self.amount

        if scheme.repeats_forever:
            return open_amount, open_currency

        open_amount *= self.scheme.repeat

        for rec in self.scheme.recurrences:
            paid_amount, paid_currency = rec.paid_amount
            converted_paid_amount = currency_conv.convert_to_currency(
                paid_amount, paid_currency, open_currency)
            open_amount -= converted_paid_amount

        return open_amount, open_currency
Exemplo n.º 12
0
def get_liquid_assets_in_both_currencies(
        deduct_income_tax: bool = False,
        own_percentage_only: bool = False) -> List:
    """ Asset balances in original and home currencies """
    output = []

    assets = get_assets(deduct_income_tax=deduct_income_tax,
                        own_percentage_only=own_percentage_only)

    currency_converter = CurrencyConverter()

    for asset in assets["assets"]:
        if not is_liquid(asset["type"]):
            continue

        org_amount = asset["sales_value"] * asset["quantity"]

        local_amount = currency_converter.convert_to_local_currency(
            org_amount, asset["currency"])

        name = asset["bank"] + " - " + asset["type"]
        found = False

        for out in output:
            if out["name"] == name and out["original_currency"] == asset[
                    "currency"]:
                found = True
                out["home_balance"] += local_amount
                out["original_balance"] += org_amount
                break

        if not found:
            output_dict = {
                "name": asset["bank"] + " - " + asset["type"],
                "home_balance": local_amount,
                "original_balance": org_amount,
                "original_currency": asset["currency"],
                "is_investment": True
            }
            output.append(output_dict)

    return output
Exemplo n.º 13
0
    def _read_bank_accounts(self):
        currency_conv = CurrencyConverter()
        currencies = bank_account.get_currencies()

        for currency in currencies:
            accounts = bank_account.get_accounts_with_currency(currency)
            currency_sum = 0
            home_sum = 0
            bank_sum = 0
            home_perc = 0
            bank_perc = 0

            for account in accounts:
                account_balance = currency_conv.convert_to_local_currency(
                    account["balance"],
                    account["currency"])

                currency_sum += account_balance

                if account["bank_name"] == config.CONSTANTS["HOME_COMPANY"]:
                    home_sum += account_balance
                else:
                    bank_sum += account_balance

            if currency_sum != 0:
                home_perc = int((home_sum / currency_sum) * 100)
                bank_perc = 100 - home_perc

            curr_dict = {"currency": currency,
                         "currency_sum": currency_sum,
                         "bank_sum": bank_sum,
                         "home_sum": home_sum,
                         "bank_perc": bank_perc,
                         "home_perc": home_perc}

            self._out["Currencies"].append(curr_dict)
Exemplo n.º 14
0
def get_account_balances_in_both_currencies() -> List:
    """ Account balances in original and home currencies """
    output = []
    accounts = get_bank_accounts()
    currency_converter = CurrencyConverter()

    for account in accounts["bank_accounts"]:
        amount_home = currency_converter.convert_to_local_currency(
            account["balance"], account["currency"])

        reserved = 0

        if "reserved" in account:
            for res_entry in account["reserved"]:
                reserved += res_entry["amount"]

        reserved_home = currency_converter.convert_to_local_currency(
            reserved, account["currency"])

        usable = account["balance"] - reserved
        usable_home = amount_home - reserved_home

        output_dict = {
            "name": account["bank_name"] + " - " + account["account_name"],
            "home_balance": amount_home,
            "original_balance": account["balance"],
            "original_currency": account["currency"],
            "is_investment": account["is_investment"],
            "original_reserved": reserved,
            "home_reserved": reserved_home,
            "original_usable": usable,
            "home_usable": usable_home
        }
        output.append(output_dict)

    return output
Exemplo n.º 15
0
class StatementEntry():
    """ Bank statement entry """
    date: datetime = None
    text: str = ""
    amount: float = 0
    currency: str = ""

    def __post_init__(self):
        self._curr_conv = None

    @property
    def amount_in_home_currency(self) -> float:
        """ Amount in home currency """
        if self._curr_conv is None:
            self._curr_conv = CurrencyConverter()
        return self._curr_conv.convert_to_local_currency(
            self.amount, self.currency)
Exemplo n.º 16
0
class ReconciliationAPI():
    """ Reconciliation API """
    def __init__(self):
        self._out = {}
        self._company_dict = {}
        self._pay_stat_api = PaymentStatusAPI()
        self._curr = CurrencyConverter()

    def get_result(self, company_names: List[str]) -> dict:
        """ Returns payment status """
        payment.generate_high_time_recurrences()

        self._out = {"reconciliations": []}

        for company_name in company_names:
            self._company_dict = {"header": {"company": company_name,
                                             "inc_sum": 0,
                                             "out_sum": 0,
                                             "balance": 0},
                                  "incoming": [],
                                  "outgoing": []}

            self._process_open_payments(company_name)
            self._out["reconciliations"].append(self._company_dict)

        return self._out

    def _process_open_payments(self, company_name):
        open_payments = payment.get_open_payments_of_company(company_name)

        for open_payment in open_payments:
            open_payment_dict = self._pay_stat_api.get_result(open_payment.guid)
            open_amt = self._curr.convert_to_local_currency(
                open_payment_dict["summary"]["open_amount"],
                open_payment_dict["summary"]["currency"])

            if open_payment.direction == payment.DIRECTION_IN:
                self._company_dict["incoming"].append(open_payment_dict)
                self._company_dict["header"]["inc_sum"] += open_amt
                self._company_dict["header"]["balance"] += open_amt
            elif open_payment.direction == payment.DIRECTION_OUT:
                self._company_dict["outgoing"].append(open_payment_dict)
                self._company_dict["header"]["out_sum"] += open_amt
                self._company_dict["header"]["balance"] -= open_amt
Exemplo n.º 17
0
 def amount_in_local_currency(self) -> float:
     """ Payment amount in home currency """
     amount, currency = self.amount
     local_amount = CurrencyConverter().convert_to_local_currency(
         amount, currency)
     return local_amount
Exemplo n.º 18
0
class Invoice:
    """ Invoice class """
    @staticmethod
    def delete_invoices(invoice_guids: List):
        """ Deletes the provided invoices """
        all_invoices = get_invoices()
        new_invoices = {"invoices": []}
        for i in range(len(all_invoices["invoices"])):
            invoice_i = all_invoices["invoices"][i]
            if invoice_i["guid"] not in invoice_guids:
                new_invoices["invoices"].append(invoice_i)
        Invoice._write_invoices_to_disk(new_invoices)

    @staticmethod
    def get_due_date_suggestion(invoice_date: datetime) -> datetime:
        """ Suggests a due date based on the invoice date """
        output = date_time.get_next_month(date=invoice_date)
        output = date_time.get_first_day_of_next_month(output)
        while True:
            while output.weekday() != 2:  # Wednesday
                output = date_time.get_next_day(output)
            if date_time.is_working_day(output):
                return output
            output = date_time.get_next_day(output)

    @staticmethod
    def get_invoice_date_suggestion() -> datetime:
        """ Suggests an invoice date """
        output = datetime.datetime.now()
        if output.day > 15:
            output = date_time.get_last_day_of_month(output)
        else:
            output = date_time.get_last_day_of_prev_month(output)
        return output

    @staticmethod
    def _write_invoices_to_disk(invoices: List):
        with open(get_file_path(), "w", encoding="utf-8") as invoice_file:
            json.dump(invoices, invoice_file, indent=3)

    def __init__(self, invoice: dict):
        self._invoice = invoice
        self._amount = float(self._invoice["amount"])
        self._vat_rate = float(self._invoice["vat_rate"])
        self._income_tax_rate = float(self._invoice["income_tax_rate"])
        self._currency_converter = CurrencyConverter()

    @property
    def alms_amount(self) -> float:
        """ Amount of recommended alms """
        return (self.amount - self.income_tax_amount) * config.CONSTANTS["DEFAULT_ALMS_RATE"] / 100

    @property
    def alms_payment_date(self) -> datetime:
        """ Alms payment date """
        return self.due_date + datetime.timedelta(days=1)

    @property
    def amount(self) -> float:
        """ Invoice amount as float """
        return self._amount

    @property
    def amount_plus_vat(self) -> float:
        """ Invoice amount + vat as float """
        return self.amount + self.vat_amount

    @property
    def currency(self) -> str:
        """ Invoice currency """
        return self._invoice["currency"]

    @property
    def due_date(self) -> datetime:
        """ Invoice due date """
        return date_time.parse_json_date(self._invoice["due_date"])

    @property
    def file_path(self) -> str:
        """ File path of invoice
        This is usually the PDF file of the e-archive invoice
        """
        if "file_path" in self._invoice:
            return self._invoice["file_path"]
        return ""

    @file_path.setter
    def file_path(self, file_path: str):
        """ File path setter """
        self._invoice["file_path"] = file_path

    @property
    def guid(self) -> str:
        """ Invoice GUID
        Every invoice will have a unique immutable GUID.
        But if you really need to change it, you can edit
        JSON data files
        """
        return self._invoice["guid"]

    @property
    def income_tax_amount(self) -> float:
        """ Income tax amount """
        return self.amount * self.income_tax_rate / 100

    @property
    def income_tax_payment_date(self) -> datetime:
        """ Income tax payment date (suggestion) """
        return datetime.date(self.invoice_date.year + 1, 3, 15)

    @property
    def income_tax_rate(self) -> float:
        """ Income tax rate
        Usually ~30%
        """
        return self._income_tax_rate

    @property
    def income_tax_transfer_date(self) -> datetime:
        """ Suggested income tax transfer date """
        return self.due_date + datetime.timedelta(days=1)

    @property
    def invoice_date(self) -> datetime:
        """ Invoice date """
        return date_time.parse_json_date(self._invoice["invoice_date"])

    @property
    def payer(self) -> Company:
        """ Company which will pay the invoice """
        return Company(self._invoice["payer"])

    @property
    def serial(self) -> str:
        """ Invoice serial number
        Paper invoice: Preprinted
        E-Archive: Provided by GIB
        """
        return self._invoice["serial"]

    @property
    def vat_amount(self) -> float:
        """ Calculated VAT amount """
        return self._amount * self._vat_rate / 100

    @property
    def vat_amount_in_local_currency(self) -> float:
        """ Calculated VAT amount in local currency """
        return self._currency_converter.convert_to_local_currency(self.vat_amount, self.currency)

    @property
    def vat_payment_date(self) -> datetime:
        """ VAT payment date """
        invoice_date = self.invoice_date
        invoice_day = invoice_date.day

        if invoice_day < config.CONSTANTS["VAT_DECLARATION_LAST_DAY"]:
            output = datetime.date(
                invoice_date.year,
                invoice_date.month,
                config.CONSTANTS["VAT_DECLARATION_LAST_DAY"])
        else:
            output = datetime.date(
                invoice_date.year,
                invoice_date.month,
                config.CONSTANTS["VAT_DECLARATION_LAST_DAY"])
            output = output + datetime.timedelta(days=30)

        return output

    @property
    def vat_rate(self) -> float:
        """ VAT rate """
        return self._vat_rate

    @property
    def vat_transfer_date(self) -> datetime:
        """ VAT transfer date """
        return self.vat_payment_date - datetime.timedelta(days=15)

    @property
    def is_vat_liable(self) -> bool:
        """ Is VAT liable or not
        Usually; foreign invoices are not VAT liable """
        return not self.payer.is_foreign

    def save(self):
        """ Writes invoice data to disk """
        if "guid" not in self._invoice:
            self._invoice["guid"] = identifier.get_guid()
        elif self._invoice["guid"] == "":
            self._invoice["guid"] = identifier.get_guid()

        current_invoices = get_invoices()
        new_invoices = {"invoices": []}

        updated = False
        for inv in current_invoices["invoices"]:
            if inv["guid"] == self._invoice["guid"]:
                new_invoices["invoices"].append(self._invoice)
                updated = True
            else:
                new_invoices["invoices"].append(inv)

        if not updated:
            new_invoices["invoices"].append(self._invoice)

        Invoice._write_invoices_to_disk(new_invoices)
Exemplo n.º 19
0
 def __init__(self, invoice: dict):
     self._invoice = invoice
     self._amount = float(self._invoice["amount"])
     self._vat_rate = float(self._invoice["vat_rate"])
     self._income_tax_rate = float(self._invoice["income_tax_rate"])
     self._currency_converter = CurrencyConverter()
Exemplo n.º 20
0
def record_cash_movement(company: str,
                         direction: str,
                         amount: float,
                         currency: str,
                         description: str,
                         income_tax_only: bool = False):
    """ Records a new cash movement """
    ##############################
    # Preparation
    ##############################

    backup.execute()

    changed_payments = []
    curr_conv = CurrencyConverter()
    open_amount = amount
    open_payments = get_open_payments_of_company(company)
    date_iso = datetime.datetime.now().isoformat()

    ##############################
    # Deduct from open payments
    ##############################

    for payment in open_payments:
        if open_amount <= 0:
            break

        if payment.direction != direction:
            continue

        if income_tax_only and (not payment.is_income_tax):
            continue

        payment.generate_very_long_term_recurrences()

        scheme = payment.scheme
        recurrences = scheme.recurrences

        for recurrence in recurrences:
            if open_amount <= 0:
                break

            if not recurrence.cleared:
                rec_open_amount, rec_curr = recurrence.open_amount

                open_amount_conv = curr_conv.convert_to_currency(
                    from_amount=open_amount,
                    from_currency=currency,
                    to_currency=rec_curr)

                if open_amount_conv >= rec_open_amount:
                    coll = {
                        "date": date_iso,
                        "description": description,
                        "amount": rec_open_amount,
                        "currency": rec_curr
                    }
                    recurrence.add_collection(Collection(coll))
                    recurrence.cleared = True

                    remain_amount = open_amount_conv - rec_open_amount
                    open_amount = open_amount * (remain_amount /
                                                 open_amount_conv)
                else:
                    coll = {
                        "date": date_iso,
                        "description": description,
                        "amount": open_amount_conv,
                        "currency": rec_curr
                    }
                    recurrence.add_collection(Collection(coll))
                    open_amount = 0

        scheme.recurrences = recurrences
        payment.scheme = scheme
        if payment.open_amount[0] <= 0:
            payment.cleared = True
        changed_payments.append(payment)

    ##############################
    # Overpayment? Need to be paid back
    ##############################

    if open_amount > 0:
        if direction == DIRECTION_IN:
            pay_back_dir = DIRECTION_OUT
        else:
            pay_back_dir = DIRECTION_IN

        pay_back_dict = {
            "creation_date": date_iso,
            "company": company,
            "description": description + " - fazla ödeme iade",
            "direction": pay_back_dir,
            "amount": open_amount,
            "currency": currency,
            "cleared": False,
            "scheme": {
                "frequency": 1,
                "period": "D",
                "start": date_iso,
                "repeat": 1,
                "recurrence": []
            }
        }

        changed_payments.append(Payment(pay_back_dict))

    ##############################
    # Finish
    ##############################

    for payment in changed_payments:
        payment.save()
Exemplo n.º 21
0
 def __init__(self) -> None:
     self._curr_conv = CurrencyConverter()
Exemplo n.º 22
0
class AssetProfitAPI():
    """ Asset profit API class """

    def __init__(self) -> None:
        self._curr_conv = CurrencyConverter()

    @property
    def result(self) -> dict:
        """ Returns result """
        out = {"Profits": [],
               "Sums": {"liquid_sales": 0,
                        "liquid_profit": 0,
                        "sales": 0,
                        "liquid_sales_home": 0,
                        "liquid_profit_home": 0,
                        "sales_home": 0}}

        assets = imp_asset.get_assets(deduct_income_tax=True, own_percentage_only=True)
        assets["assets"].sort(key=lambda x: imp_asset.is_liquid(x["type"]), reverse=True)

        for asset in assets["assets"]:
            asset_profit = self._calc_asset_profit(asset)

            history = ""
            prev_hist_val = 0
            if "value_history" in asset:
                for history_entry in asset["value_history"]:
                    hist_asset = deepcopy(asset)
                    hist_asset["sales_value"] = history_entry["value"]
                    hist_profit = self._calc_asset_profit(hist_asset)

                    if history != "":
                        if hist_profit["usd_profit"] > prev_hist_val:
                            history += " ↑ "
                        else:
                            history += " ↓ "
                    history += str(round(hist_profit["usd_profit"]))
                    prev_hist_val = hist_profit["usd_profit"]

            asset_dict = deepcopy(asset_profit)
            asset_dict["name"] = asset["name"]
            asset_dict["purchase_date"] = date_time.get_formatted_date(asset_profit["purchase_date"]) # pylint: disable=C0301
            asset_dict["quantity"] = asset["quantity"]
            asset_dict["history"] = history

            out["Profits"].append(asset_dict)

            if imp_asset.is_liquid(asset["type"]):
                out["Sums"]["liquid_sales"] += int(asset_dict["actual_usd_total"])
                out["Sums"]["liquid_profit"] += int(asset_dict["usd_profit"])
            out["Sums"]["sales"] += int(asset_dict["actual_usd_total"])

        out["Sums"]["liquid_sales_home"] = int(self._curr_conv.convert_to_local_currency(
            out["Sums"]["liquid_sales"],
            "USD"))

        out["Sums"]["liquid_profit_home"] = int(self._curr_conv.convert_to_local_currency(
            out["Sums"]["liquid_profit"],
            "USD"))

        out["Sums"]["sales_home"] = int(self._curr_conv.convert_to_local_currency(
            out["Sums"]["sales"],
            "USD"))

        return out

    def _calc_asset_profit(self, asset: dict) -> dict:
        purchase_date = date_time.parse_json_date(asset["purchase_date"])
        old_currency_converter = OldCurrencyConverter(purchase_date)

        purchase_value = self._curr_conv.convert_to_local_currency(asset["purchase_value"],
                                                                   asset["currency"])

        purchase_total = asset["quantity"] * purchase_value

        purchase_usd_total = old_currency_converter.convert_to_foreign_currency(purchase_total,
                                                                                "USD")

        sales_value = self._curr_conv.convert_to_local_currency(asset["sales_value"],
                                                                asset["currency"])

        sales_total = asset["quantity"] * sales_value

        actual_usd_price = self._curr_conv.convert_to_foreign_currency(sales_value,
                                                                       "USD")

        actual_usd_total = asset["quantity"] * actual_usd_price

        usd_profit = actual_usd_total - purchase_usd_total
        if purchase_usd_total == 0:
            perc_profit = 0
        else:
            perc_profit = (usd_profit / purchase_usd_total) * 100

        result = {
            "purchase_date": purchase_date,
            "purchase_value": purchase_value,
            "purchase_total": purchase_total,
            "purchase_usd_total": purchase_usd_total,
            "sales_value": sales_value,
            "sales_total": sales_total,
            "actual_usd_price": actual_usd_price,
            "actual_usd_total": actual_usd_total,
            "usd_profit": usd_profit,
            "perc_profit": perc_profit
        }

        return result
Exemplo n.º 23
0
 def amount_in_home_currency(self) -> float:
     """ Amount in home currency """
     if self._curr_conv is None:
         self._curr_conv = CurrencyConverter()
     return self._curr_conv.convert_to_local_currency(
         self.amount, self.currency)
Exemplo n.º 24
0
class IncomeTaxCalculator():
    """ Income tax calculator class """
    def __init__(self):
        self._tax_rates = []

        self._default_tax_rate = 0
        self._default_tax_rate_calculated = False

        self._tmp_tax_rate = 0
        self._tmp_tax_rate_calculated = False

        self._forecast_tax_rate = 0
        self._forecast_tax_rate_calculated = False

        self._converter = CurrencyConverter()
        self._read_tax_rates()

    @property
    def default_tax_rate(self) -> float:
        """ Returns average tax rate from historic invoices """
        if not self._default_tax_rate_calculated:
            today = date.today()
            invoices = get_invoices_of_last_year()
            invoice_sum = 0
            for invoice in invoices:
                home_amount = self._converter.convert_to_local_currency(
                    invoice["amount"], invoice["currency"])
                inv_date = parse_json_date(invoice["invoice_date"])
                if inv_date.year < today.year:
                    home_amount *= 1 + (config.CONSTANTS["TUFE_RATE"] / 100)
                invoice_sum += home_amount
            annual_tax = self._calc_annual_tax(invoice_sum)
            self._default_tax_rate = (annual_tax / invoice_sum) * 100
            self._default_tax_rate_calculated = True
        return self._default_tax_rate

    @property
    def temp_tax_rate(self) -> float:
        """ Returns temporay tax rate """
        if not self._tmp_tax_rate_calculated:
            self._tmp_tax_rate = self.default_tax_rate / 2
            self._tmp_tax_rate_calculated = True
        return self._tmp_tax_rate

    @property
    def safety_tax_rate(self) -> float:
        """ Returns safety tax rate """
        return self.temp_tax_rate

    @property
    def forecast_tax_rate(self) -> float:
        """ Returns forecast tax rate """
        if not self._forecast_tax_rate_calculated:
            # Last year (with inflation)
            last_year = date.today().year - 1
            last_year_invoices = get_invoices_of_fiscal_year(last_year)
            invoice_sum = 0
            for invoice in last_year_invoices:
                home_amount = self._converter.convert_to_local_currency(
                    invoice["amount"], invoice["currency"])
                home_amount *= 1 + (config.CONSTANTS["TUFE_RATE"] / 100)
                invoice_sum += home_amount

            if invoice_sum == 0:
                last_year_rate = 0
            else:
                last_year_annual_tax = self._calc_annual_tax(invoice_sum)
                last_year_rate = last_year_annual_tax / invoice_sum

            # This year (projection)
            this_year_invoices = get_invoices_of_fiscal_year(date.today().year)
            invoice_sum = 0
            for invoice in this_year_invoices:
                home_amount = self._converter.convert_to_local_currency(
                    invoice["amount"], invoice["currency"])
                home_amount *= 1 + (config.CONSTANTS["TUFE_RATE"] / 100)
                invoice_sum += home_amount

            invoice_sum += Activity.get_total_activity_earnings()
            invoice_sum = invoice_sum * (12 - (date.today().month) + 1)

            if invoice_sum == 0:
                this_year_rate = 0
            else:
                this_year_annual_tax = self._calc_annual_tax(invoice_sum)
                this_year_rate = this_year_annual_tax / invoice_sum

            # Average
            if this_year_rate == 0:
                self._forecast_tax_rate = last_year_rate
            elif last_year_rate == 0:
                self._forecast_tax_rate = this_year_rate
            else:
                if this_year_rate > last_year_rate:
                    self._forecast_tax_rate = this_year_rate
                else:
                    self._forecast_tax_rate = (this_year_rate +
                                               last_year_rate) / 2

            self._forecast_tax_rate *= 100
            self._forecast_tax_rate_calculated = True
        return self._forecast_tax_rate

    def calc_invoice_tax_rate(self, year: int, amount: float) -> float:
        """ Calculate tax rate for given invoice """
        fiscal_invoices = get_invoices_of_fiscal_year(year)
        invoice_sum = 0
        for invoice in fiscal_invoices:
            home_amount = self._converter.convert_to_local_currency(
                invoice["amount"], invoice["currency"])
            invoice_sum += home_amount
        invoice_sum += amount

        for tax_rate in self._tax_rates:
            if tax_rate["amount"] >= invoice_sum:
                return tax_rate["rate"]

        raise Exception("Couldn't calculate invoice tax rate")

    def calc_invoice_tax_amount(self, year: int, amount: float) -> float:
        """ Calculate tax for given invoice """
        tax_rate = self.calc_invoice_tax_rate(year, amount)
        return amount * tax_rate / 100

    def _read_tax_rates(self):
        with open(self._income_tax_file_path, encoding="utf-8") as tax_file:
            json_data = json.load(tax_file)
        self._tax_rates = json_data["rates"]

    def _calc_annual_tax(self, amount: float) -> float:
        out = 0
        remain = amount

        for tax_rate in self._tax_rates:
            if remain > tax_rate["amount"]:
                tax_amount = tax_rate["amount"] * tax_rate["rate"] / 100
                out += tax_amount
                remain -= tax_rate["amount"]
            else:
                tax_amount = remain * tax_rate["rate"] / 100
                out += tax_amount
                remain = 0
                break
        return out

    @property
    def _income_tax_file_path(self) -> str:
        return path.join(config.CONSTANTS["DATA_DIR_PATH"] + _INCOME_TAX_FILE)
Exemplo n.º 25
0
 def __init__(self):
     self._out = {}
     self._company_dict = {}
     self._pay_stat_api = PaymentStatusAPI()
     self._curr = CurrencyConverter()
Exemplo n.º 26
0
def get_plan_vs_actual_list() -> List:
    """ Plan vs actual """
    conv = CurrencyConverter()
    out = get_plan_list()
    fiscal = _get_latest_fiscal_file_content()

    for subject in out:
        subject["actuals"] = [{
            "month": 1,
            "amount": 0,
            "status_icon": _GREEN_ICON
        }, {
            "month": 2,
            "amount": 0,
            "status_icon": _GREEN_ICON
        }, {
            "month": 3,
            "amount": 0,
            "status_icon": _GREEN_ICON
        }, {
            "month": 4,
            "amount": 0,
            "status_icon": _GREEN_ICON
        }, {
            "month": 5,
            "amount": 0,
            "status_icon": _GREEN_ICON
        }, {
            "month": 6,
            "amount": 0,
            "status_icon": _GREEN_ICON
        }, {
            "month": 7,
            "amount": 0,
            "status_icon": _GREEN_ICON
        }, {
            "month": 8,
            "amount": 0,
            "status_icon": _GREEN_ICON
        }, {
            "month": 9,
            "amount": 0,
            "status_icon": _GREEN_ICON
        }, {
            "month": 10,
            "amount": 0,
            "status_icon": _GREEN_ICON
        }, {
            "month": 11,
            "amount": 0,
            "status_icon": _GREEN_ICON
        }, {
            "month": 12,
            "amount": 0,
            "status_icon": _GREEN_ICON
        }]

        for actual_months in fiscal["actuals"]:
            for actual in actual_months["values"]:
                if actual["domain"] != subject["domain"]:
                    continue
                if actual["subject"] != subject["subject"]:
                    continue
                if actual["direction"] != subject["direction"]:
                    continue

                local_amount = conv.convert_to_local_currency(
                    actual["amount"], actual["currency"])

                for out_actual in subject["actuals"]:
                    if out_actual["month"] == actual_months["month"]:
                        out_actual["amount"] += local_amount
                        out_actual["status_icon"] = _get_status_icon(
                            subject["monthly_plan_amount"],
                            out_actual["amount"])
                        break

    return out
Exemplo n.º 27
0
 def open_amount_in_local_currency(self) -> float:
     """ Payment open amount in local currency """
     open_amount, curr = self.open_amount
     local_amount = CurrencyConverter().convert_to_local_currency(
         open_amount, curr)
     return local_amount
Exemplo n.º 28
0
def get_payment_objects_from_invoice(invoice: Invoice) -> list:
    """ Extracts new payment objects out of an invoice """
    # Preparation
    output = []

    currency_converter = CurrencyConverter()
    inc_tax_calc = IncomeTaxCalculatorFactory.get_instance()

    invoice_currency = invoice.currency
    invoice_date = invoice.invoice_date
    invoice_payer = invoice.payer
    invoice_serial = invoice.serial
    payment_amount = invoice.amount_plus_vat

    description_prefix = invoice_payer.name + " - " + date_time.get_formatted_date(
        invoice_date) + "(" + invoice_serial + ")"

    # Incoming payment

    incoming_payment_json = {
        "guid": identifier.get_guid(),
        "creation_date": datetime.datetime.now().isoformat(),
        "company": invoice_payer.name,
        "description": description_prefix + " - Incoming payment",
        "invoice_guid": invoice.guid,
        "direction": DIRECTION_IN,
        "amount": payment_amount,
        "currency": invoice_currency,
        "cleared": False
    }

    incoming_scheme_json = {
        "frequency":
        1,
        "period":
        PERIOD_DAILY,
        "start":
        invoice.due_date.isoformat(),
        "repeat":
        1,
        "recurrence": [{
            "recurrence_date": invoice.due_date.isoformat(),
            "expected_payment_date": invoice.due_date.isoformat(),
            "amount": payment_amount,
            "currency": invoice_currency,
            "cleared": False,
            "collections": []
        }]
    }

    incoming_scheme_obj = Scheme(incoming_scheme_json)

    incoming_payment_obj = Payment(incoming_payment_json)
    incoming_payment_obj.scheme = incoming_scheme_obj

    output.append(incoming_payment_obj)

    # VAT transfer

    if invoice.is_vat_liable:
        vat_amount = invoice.vat_amount_in_local_currency

        vat_transfer_json = {
            "guid": identifier.get_guid(),
            "creation_date": datetime.datetime.now().isoformat(),
            "company": config.CONSTANTS["DEFAULT_BANK"],
            "description": description_prefix + " - VAT transfer",
            "invoice_guid": "",
            "direction": DIRECTION_TRANSFER,
            "amount": vat_amount,
            "currency": config.CONSTANTS["HOME_CURRENCY"],
            "cleared": False
        }

        vat_transfer_date = invoice.vat_transfer_date

        vat_transfer_scheme_json = {
            "frequency":
            1,
            "period":
            PERIOD_DAILY,
            "start":
            vat_transfer_date.isoformat(),
            "repeat":
            1,
            "recurrence": [{
                "recurrence_date":
                vat_transfer_date.isoformat(),
                "expected_payment_date":
                vat_transfer_date.isoformat(),
                "amount":
                vat_amount,
                "currency":
                config.CONSTANTS["HOME_CURRENCY"],
                "cleared":
                False,
                "collections": []
            }]
        }

        vat_transfer_scheme_obj = Scheme(vat_transfer_scheme_json)

        vat_transfer_payment_obj = Payment(vat_transfer_json)
        vat_transfer_payment_obj.scheme = vat_transfer_scheme_obj

        output.append(vat_transfer_payment_obj)

    # VAT payment

    if invoice.is_vat_liable:
        vat_amount = invoice.vat_amount_in_local_currency

        vat_payment_json = {
            "guid": identifier.get_guid(),
            "creation_date": datetime.datetime.now().isoformat(),
            "company": config.CONSTANTS["HOME_GOVERNMENT"],
            "description": description_prefix + " - VAT payment",
            "invoice_guid": "",
            "direction": DIRECTION_OUT,
            "amount": vat_amount,
            "currency": config.CONSTANTS["HOME_CURRENCY"],
            "cleared": False,
            "is_vat": True
        }

        vat_payment_date = invoice.vat_payment_date

        vat_payment_scheme_json = {
            "frequency":
            1,
            "period":
            PERIOD_DAILY,
            "start":
            vat_payment_date.isoformat(),
            "repeat":
            1,
            "recurrence": [{
                "recurrence_date":
                vat_payment_date.isoformat(),
                "expected_payment_date":
                vat_payment_date.isoformat(),
                "amount":
                vat_amount,
                "currency":
                config.CONSTANTS["HOME_CURRENCY"],
                "cleared":
                False,
                "collections": []
            }]
        }

        vat_payment_scheme_obj = Scheme(vat_payment_scheme_json)

        vat_payment_payment_obj = Payment(vat_payment_json)
        vat_payment_payment_obj.scheme = vat_payment_scheme_obj

        output.append(vat_payment_payment_obj)

    # Income tax investment & transfer

    itax_amount = currency_converter.convert_to_local_currency(
        invoice.income_tax_amount, invoice_currency)

    itax_investment_rate = 100
    itax_investment_rate -= inc_tax_calc.safety_tax_rate
    itax_investment_rate -= inc_tax_calc.temp_tax_rate
    itax_investment_amount = itax_amount * itax_investment_rate / 100
    itax_amount -= itax_investment_amount

    itax_transfer_json = {
        "guid": identifier.get_guid(),
        "creation_date": datetime.datetime.now().isoformat(),
        "company": config.CONSTANTS["DEFAULT_BANK"],
        "description": description_prefix + " - income tax investment",
        "invoice_guid": "",
        "direction": DIRECTION_TRANSFER,
        "amount": itax_investment_amount,
        "currency": config.CONSTANTS["HOME_CURRENCY"],
        "cleared": False
    }

    itax_transfer_date = invoice.income_tax_transfer_date

    itax_transfer_scheme_json = {
        "frequency":
        1,
        "period":
        PERIOD_DAILY,
        "start":
        itax_transfer_date.isoformat(),
        "repeat":
        1,
        "recurrence": [{
            "recurrence_date": itax_transfer_date.isoformat(),
            "expected_payment_date": itax_transfer_date.isoformat(),
            "amount": itax_amount,
            "currency": config.CONSTANTS["HOME_CURRENCY"],
            "cleared": False,
            "collections": []
        }]
    }

    itax_transfer_scheme_obj = Scheme(itax_transfer_scheme_json)
    itax_transfer_payment_obj = Payment(itax_transfer_json)
    itax_transfer_payment_obj.scheme = itax_transfer_scheme_obj
    output.append(itax_transfer_payment_obj)

    itax_transfer_json = {
        "guid": identifier.get_guid(),
        "creation_date": datetime.datetime.now().isoformat(),
        "company": config.CONSTANTS["DEFAULT_BANK"],
        "description": description_prefix + " - income tax transfer",
        "invoice_guid": "",
        "direction": DIRECTION_TRANSFER,
        "amount": itax_amount,
        "currency": config.CONSTANTS["HOME_CURRENCY"],
        "cleared": False
    }

    itax_transfer_date = invoice.income_tax_transfer_date

    itax_transfer_scheme_json = {
        "frequency":
        1,
        "period":
        PERIOD_DAILY,
        "start":
        itax_transfer_date.isoformat(),
        "repeat":
        1,
        "recurrence": [{
            "recurrence_date": itax_transfer_date.isoformat(),
            "expected_payment_date": itax_transfer_date.isoformat(),
            "amount": itax_amount,
            "currency": config.CONSTANTS["HOME_CURRENCY"],
            "cleared": False,
            "collections": []
        }]
    }

    itax_transfer_scheme_obj = Scheme(itax_transfer_scheme_json)
    itax_transfer_payment_obj = Payment(itax_transfer_json)
    itax_transfer_payment_obj.scheme = itax_transfer_scheme_obj
    output.append(itax_transfer_payment_obj)

    # Income tax payment

    itax_amount = currency_converter.convert_to_local_currency(
        invoice.income_tax_amount, invoice_currency)

    itax_payment_json = {
        "guid": identifier.get_guid(),
        "creation_date": datetime.datetime.now().isoformat(),
        "company": config.CONSTANTS["HOME_GOVERNMENT"],
        "description": description_prefix + " - income tax payment",
        "invoice_guid": "",
        "direction": DIRECTION_OUT,
        "amount": itax_amount,
        "currency": config.CONSTANTS["HOME_CURRENCY"],
        "cleared": False,
        "is_income_tax": True
    }

    itax_payment_date = invoice.income_tax_payment_date

    itax_payment_scheme_json = {
        "frequency":
        1,
        "period":
        PERIOD_DAILY,
        "start":
        itax_payment_date.isoformat(),
        "repeat":
        1,
        "recurrence": [{
            "recurrence_date": itax_payment_date.isoformat(),
            "expected_payment_date": itax_payment_date.isoformat(),
            "amount": itax_amount,
            "currency": config.CONSTANTS["HOME_CURRENCY"],
            "cleared": False,
            "collections": []
        }]
    }

    itax_payment_scheme_obj = Scheme(itax_payment_scheme_json)

    itax_payment_payment_obj = Payment(itax_payment_json)
    itax_payment_payment_obj.scheme = itax_payment_scheme_obj

    output.append(itax_payment_payment_obj)

    # Alms

    alms_amount = currency_converter.convert_to_local_currency(
        invoice.alms_amount, invoice_currency)

    alms_payment_json = {
        "guid": identifier.get_guid(),
        "creation_date": datetime.datetime.now().isoformat(),
        "company": config.CONSTANTS["COMPANY_NAME_UNKNOWN"],
        "description": description_prefix + " - alms",
        "invoice_guid": "",
        "direction": DIRECTION_OUT,
        "amount": alms_amount,
        "currency": config.CONSTANTS["HOME_CURRENCY"],
        "cleared": False
    }

    alms_payment_date = invoice.alms_payment_date

    alms_payment_scheme_json = {
        "frequency":
        1,
        "period":
        PERIOD_DAILY,
        "start":
        alms_payment_date.isoformat(),
        "repeat":
        1,
        "recurrence": [{
            "recurrence_date": alms_payment_date.isoformat(),
            "expected_payment_date": alms_payment_date.isoformat(),
            "amount": alms_amount,
            "currency": config.CONSTANTS["HOME_CURRENCY"],
            "cleared": False,
            "collections": []
        }]
    }

    alms_payment_scheme_obj = Scheme(alms_payment_scheme_json)

    alms_payment_payment_obj = Payment(alms_payment_json)
    alms_payment_payment_obj.scheme = alms_payment_scheme_obj

    output.append(alms_payment_payment_obj)

    # Flush
    return output
Exemplo n.º 29
0
 def earned_amount_in_local_currency(self) -> float:
     """ Activity generated amount in local currency """
     foreign_amount, foreign_currency = self.earned_amount
     return CurrencyConverter().convert_to_local_currency(
         foreign_amount, foreign_currency)