Override a function related to other functions

well I’m trying to override the function that calculates the amount with just changing how it does calculate (rate * qty * width * length) it but apparently this function is calling other functions inside it so i have tried this code but ii doesn’t work anyone got any ideas? anything is appreciated .
ps: this in my custom app
my custom file in my custom app

import frappe
from frappe import _, scrub
from frappe.utils import flt
from erpnext.controllers.taxes_and_totals import calculate_taxes_and_totals
from erpnext.accounts.doctype.pricing_rule.utils import get_applied_pricing_rules

def custom_calculate_item_values(self):
        if self.doc.get("is_consolidated"):
            return

        if not self.discount_amount_applied:
            for item in self._items:
                self.doc.round_floats_in(item)

                if item.discount_percentage == 100:
                    item.rate = 0.0
                elif item.price_list_rate:
                    if not item.rate or (
                        item.pricing_rules and item.discount_percentage > 0
                    ):
                        item.rate = flt(
                            item.price_list_rate
                            * (1.0 - (item.discount_percentage / 100.0)),
                            item.precision("rate"),
                        )

                        item.discount_amount = item.price_list_rate * (
                            item.discount_percentage / 100.0
                        )

                    elif item.discount_amount and item.pricing_rules:
                        item.rate = item.price_list_rate - item.discount_amount

                if item.doctype in [
                    "Quotation Item",
                    "Sales Order Item",
                    "Delivery Note Item",
                    "Sales Invoice Item",
                    "POS Invoice Item",
                    "Purchase Invoice Item",
                    "Purchase Order Item",
                    "Purchase Receipt Item",
                ]:
                    (
                        item.rate_with_margin,
                        item.base_rate_with_margin,
                    ) = self.calculate_margin(item)
                    if flt(item.rate_with_margin) > 0:
                        item.rate = flt(
                            item.rate_with_margin
                            * (1.0 - (item.discount_percentage / 100.0)),
                            item.precision("rate"),
                        )

                        if item.discount_amount and not item.discount_percentage:
                            item.rate = item.rate_with_margin - item.discount_amount
                        else:
                            item.discount_amount = item.rate_with_margin - item.rate

                    elif flt(item.price_list_rate) > 0:
                        item.discount_amount = item.price_list_rate - item.rate
                elif flt(item.price_list_rate) > 0 and not item.discount_amount:
                    item.discount_amount = item.price_list_rate - item.rate

                item.net_rate = item.rate

                if not item.qty and self.doc.get("is_return"):
                    item.amount = flt(-1 * item.rate, item.precision("amount"))
                elif not item.qty and self.doc.get("is_debit_note"):
                    item.amount = flt(item.rate, item.precision("amount"))
                else:
                    item.amount = flt(
                        item.rate * item.qty * item.length * item.width,
                        item.precision("amount"),
                    )

                item.net_amount = item.amount

                self._set_in_company_currency(
                    item,
                    ["price_list_rate", "rate", "net_rate", "amount", "net_amount"],
                )

                item.item_tax_amount = 0.0

def _set_in_company_currency(self, doc, fields):
        # set values in base currency
        for f in fields:
            val = flt(
                flt(
                    doc.get(f),
                    doc.precision(f) * self.doc.conversion_rate,
                    doc.precision("base_" + f),
                )
            )
            doc.set("base_" + f, val)

def calculate_margin(self, item):
        rate_with_margin = 0.0
        base_rate_with_margin = 0.0
        if item.price_list_rate:
            if item.pricing_rules and not self.doc.ignore_pricing_rule:
                has_margin = False
                for d in get_applied_pricing_rules(item.pricing_rules):
                    pricing_rule = frappe.get_cached_doc("Pricing Rule", d)
                    if pricing_rule.margin_rate_or_amount and (
                        (
                            pricing_rule.currency == self.doc.currency
                            and pricing_rule.margin_type in ["Amount", "Percentage"]
                        )
                        or pricing_rule.margin_type == "Percentage"
                    ):
                        item.margin_type = pricing_rule.margin_type
                        item.margin_rate_or_amount = pricing_rule.margin_rate_or_amount
                        has_margin = True
                if not has_margin:
                    item.margin_type = None
                    item.margin_rate_or_amount=0.0
            if not item.pricing_rules and flt(item.rate)>flt(item.price_list_rate):
                item.margin_type="Amount"
                item.margin_rate_or_amount=flt(
                    item.rate-item.price_list_rate,item.precision("margin_rate_or_amount")
                )
                item.rate_with_margin = item.rate
            elif item.margin_type and item.margin_rate_or_amount:
                margin_value = (
					item.margin_rate_or_amount
					if item.margin_type == "Amount"
					else flt(item.price_list_rate) * flt(item.margin_rate_or_amount) / 100
				)
                rate_with_margin = flt(item.price_list_rate) + flt(margin_value)
                base_rate_with_margin = flt(rate_with_margin) * flt(self.doc.conversion_rate)
        

        return rate_with_margin, base_rate_with_margin

                                
calculate_taxes_and_totals.calculate_item_values = custom_calculate_item_values

and my hook.py:

from frappe import override_doctype_class

def override_taxes_and_totals():
    from test_app.override import custom_calculate_item_values
    override_doctype_class[
        "erpnext.controllers.taxes_and_totals.calculate_taxes_and_totals"
    ] = custom_calculate_item_values

app_hooks = {
    "test_app": {
        "test_app.hooks.override_taxes_and_totals": {
            "after_install": "test_app.hooks.override_taxes_and_totals"
        }
    }
}

Check the article https://codewithkarani.com/2021/11/22/how-to-override-a-method-in-frappe-or-erpnext/

1 Like

I have already tried that solution and it didn’t work since I’m trying to override the taxes_and_totals controller class method not a doctype class method .

which doctype are you overriding?

I’m not trying to override a doctype but rather a taxes_and_totals controller class (calculate_taxes_and_totals) method (calculate_item_values) that used to calculate in quotation

Try using monkey patch override method

1 Like

example: in your custom app init file try this.
i hope this may work in your case

1 Like