Sales Taxes and Charges - Missing field results in exception

Hello,

I have created a Custom Doctype named Sales Return which mimics the functionality of the Credit Note which one can create from the Sales Invoice, the only difference being that this Doctype does not keep the reference of the Sales Invoice which is mandatory in the standard functionality of the Sales Invoice.
For this I have reused most of the code but I discovered that there is an issue with a piece of code below:

Sales Taxes and Charges DocType is not having a field name category but it is referred in calculate_totals(self): function in calculate_taxes_and_totals class.

Here is the code snippet:

self.doc.taxes_and_charges_added = self.doc.taxes_and_charges_deducted = 0.0
for tax in self.doc.get(“taxes”):
if tax.category in [“Valuation and Total”, “Total”]:

Here is the exception:
Traceback (most recent call last):
File “/home/frappe/frappe-bench/apps/frappe/frappe/app.py”, line 55, in application
response = frappe.handler.handle()
File “/home/frappe/frappe-bench/apps/frappe/frappe/handler.py”, line 21, in handle
data = execute_cmd(cmd)
File “/home/frappe/frappe-bench/apps/frappe/frappe/handler.py”, line 52, in execute_cmd
return frappe.call(method, **frappe.form_dict)
File “/home/frappe/frappe-bench/apps/frappe/frappe/init.py”, line 907, in call
return fn(*args, **newargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/desk/form/save.py”, line 22, in savedocs
doc.save()
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 230, in save
return self._save(*args, **kwargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 253, in _save
self.insert()
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 192, in insert
self.run_before_save_methods()
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 771, in run_before_save_methods
self.run_method(“validate”)
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 666, in run_method
out = Document.hook(fn)(self, *args, **kwargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 891, in composer
return composed(self, method, *args, **kwargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 874, in runner
add_to_return_value(self, fn(self, *args, **kwargs))
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 660, in
fn = lambda self, *args, **kwargs: getattr(self, method)(*args, **kwargs)
File “/home/frappe/frappe-bench/apps/aurogroup_erpnext/aurogroup_erpnext/auro_group/doctype/sales_return/sales_return.py”, line 58, in validate
super(SalesReturn, self).validate()
File “/home/frappe/frappe-bench/apps/erpnext/erpnext/controllers/selling_controller.py”, line 33, in validate
super(SellingController, self).validate()
File “/home/frappe/frappe-bench/apps/erpnext/erpnext/controllers/stock_controller.py”, line 16, in validate
super(StockController, self).validate()
File “/home/frappe/frappe-bench/apps/erpnext/erpnext/controllers/accounts_controller.py”, line 38, in validate
self.calculate_taxes_and_totals()
File “/home/frappe/frappe-bench/apps/erpnext/erpnext/controllers/accounts_controller.py”, line 101, in calculate_taxes_and_totals
calculate_taxes_and_totals(self)
File “/home/frappe/frappe-bench/apps/erpnext/erpnext/controllers/taxes_and_totals.py”, line 15, in init
self.calculate()
File “/home/frappe/frappe-bench/apps/erpnext/erpnext/controllers/taxes_and_totals.py”, line 19, in calculate
self._calculate()
File “/home/frappe/frappe-bench/apps/erpnext/erpnext/controllers/taxes_and_totals.py”, line 35, in _calculate
self.calculate_totals()
File “/home/frappe/frappe-bench/apps/erpnext/erpnext/controllers/taxes_and_totals.py”, line 310, in calculate_totals
if tax.category in [“Valuation and Total”, “Total”]:
AttributeError: ‘SalesTaxesandCharges’ object has no attribute ‘category’

We do not want to create another custom field to fix this issue and think that it should be fixed in the Sales Invoice Doctype.

Please let me know if my understanding and approach is correct or is there another workaround?

Best way will be to add those two fields and hide them. It doesnt hurt I guess.
I am working on Sales Return as you are, and I hit the same error you faced.

They are initializing new class for tax and totals calculation at https://github.com/frappe/erpnext/blob/develop/erpnext/controllers/accounts_controller.py#L101

else we could have overridden calculate_totals method :confused:

Looks like there is one more issue in core.
After adding category field in Sales Taxes and Charges DocType this is the exception

Traceback (most recent call last):
File “/home/frappe/frappe-bench/apps/frappe/frappe/desk/form/save.py”, line 19, in savedocs
doc.submit()
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 740, in submit
self._submit()
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 729, in _submit
self.save()
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 230, in save
return self._save(*args, **kwargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 263, in _save
self.run_before_save_methods()
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 774, in run_before_save_methods
self.run_method(“validate”)
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 666, in run_method
out = Document.hook(fn)(self, *args, **kwargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 891, in composer
return composed(self, method, *args, **kwargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 874, in runner
add_to_return_value(self, fn(self, *args, **kwargs))
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 660, in
fn = lambda self, *args, **kwargs: getattr(self, method)(*args, **kwargs)
File “/home/frappe/frappe-bench/apps/aurogroup_erpnext/aurogroup_erpnext/auro_group/doctype/sales_return/sales_return.py”, line 58, in validate
super(SalesReturn, self).validate()
File “/home/frappe/frappe-bench/apps/erpnext/erpnext/controllers/selling_controller.py”, line 33, in validate
super(SellingController, self).validate()
File “/home/frappe/frappe-bench/apps/erpnext/erpnext/controllers/stock_controller.py”, line 16, in validate
super(StockController, self).validate()
File “/home/frappe/frappe-bench/apps/erpnext/erpnext/controllers/accounts_controller.py”, line 38, in validate
self.calculate_taxes_and_totals()
File “/home/frappe/frappe-bench/apps/erpnext/erpnext/controllers/accounts_controller.py”, line 101, in calculate_taxes_and_totals
calculate_taxes_and_totals(self)
File “/home/frappe/frappe-bench/apps/erpnext/erpnext/controllers/taxes_and_totals.py”, line 15, in init
self.calculate()
File “/home/frappe/frappe-bench/apps/erpnext/erpnext/controllers/taxes_and_totals.py”, line 19, in calculate
self._calculate()
File “/home/frappe/frappe-bench/apps/erpnext/erpnext/controllers/taxes_and_totals.py”, line 35, in _calculate
self.calculate_totals()
File “/home/frappe/frappe-bench/apps/erpnext/erpnext/controllers/taxes_and_totals.py”, line 316, in calculate_totals
self.doc.round_floats_in(self.doc, [“taxes_and_charges_added”, “taxes_and_charges_deducted”])
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 946, in round_floats_in
doc.set(fieldname, flt(doc.get(fieldname), self.precision(fieldname, doc.parentfield)))
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py”, line 694, in precision
if df.fieldtype in (“Currency”, “Float”, “Percent”):
AttributeError: ‘NoneType’ object has no attribute ‘fieldtype’

Actually, I did not add any fields in Taxes doctype…
I faked the fields by

for tax in self.get('taxes'):
	tax.category = "something"
	tax.add_deduct_tax = "something"

in the validate method.

We need to add taxes_and_charges_added & taxes_and_charges_deducted and their base_ (4 fields in total) to parent doctype, because these are precision checked and need to exist. Make them read only, hidden, print hidden and thats it

By the way
Are you saving the item quantities in +ve or -ve ?
I was doing -ve up until I hit this validation

Going for +ve amounts now.

Thanks for your inputs @fahimalizain.
I am storing -ve value, maybe I need to store them as +ve. Will try and see if it works.