mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-25 21:05:19 +00:00
Merge branch 'develop' into fix-test
This commit is contained in:
@@ -654,7 +654,7 @@ class AccountsController(TransactionBase):
|
||||
self.base_paid_amount = 0
|
||||
|
||||
def set_missing_values(self, for_validate=False):
|
||||
if frappe.flags.in_test:
|
||||
if frappe.in_test:
|
||||
for fieldname in ["posting_date", "transaction_date"]:
|
||||
if self.meta.get_field(fieldname) and not self.get(fieldname):
|
||||
self.set(fieldname, today())
|
||||
@@ -1138,10 +1138,17 @@ class AccountsController(TransactionBase):
|
||||
return True
|
||||
|
||||
def set_taxes_and_charges(self):
|
||||
if self.get("taxes") or self.get("is_pos"):
|
||||
return
|
||||
|
||||
if frappe.get_single_value(
|
||||
"Accounts Settings", "add_taxes_from_taxes_and_charges_template"
|
||||
) and hasattr(self, "taxes_and_charges"):
|
||||
if tax_master_doctype := self.meta.get_field("taxes_and_charges").options:
|
||||
self.append_taxes_from_master(tax_master_doctype)
|
||||
|
||||
if frappe.get_single_value("Accounts Settings", "add_taxes_from_item_tax_template"):
|
||||
if hasattr(self, "taxes_and_charges") and not self.get("taxes") and not self.get("is_pos"):
|
||||
if tax_master_doctype := self.meta.get_field("taxes_and_charges").options:
|
||||
self.append_taxes_from_master(tax_master_doctype)
|
||||
self.append_taxes_from_item_tax_template()
|
||||
|
||||
def append_taxes_from_master(self, tax_master_doctype=None):
|
||||
if self.get("taxes_and_charges"):
|
||||
@@ -1174,6 +1181,8 @@ class AccountsController(TransactionBase):
|
||||
"rate": 0,
|
||||
"description": account_head,
|
||||
"set_by_item_tax_template": 1,
|
||||
"category": "Total",
|
||||
"add_deduct_tax": "Add",
|
||||
},
|
||||
)
|
||||
|
||||
@@ -2034,69 +2043,48 @@ class AccountsController(TransactionBase):
|
||||
def validate_multiple_billing(self, ref_dt, item_ref_dn, based_on):
|
||||
from erpnext.controllers.status_updater import get_allowance_for
|
||||
|
||||
item_allowance = {}
|
||||
global_qty_allowance, global_amount_allowance = None, None
|
||||
ref_wise_billed_amount = self.get_reference_wise_billed_amt(ref_dt, item_ref_dn, based_on)
|
||||
|
||||
role_allowed_to_over_bill = frappe.get_cached_value(
|
||||
"Accounts Settings", None, "role_allowed_to_over_bill"
|
||||
)
|
||||
user_roles = frappe.get_roles()
|
||||
if not ref_wise_billed_amount:
|
||||
return
|
||||
|
||||
total_overbilled_amt = 0.0
|
||||
overbilled_items = []
|
||||
precision = self.precision(based_on, "items")
|
||||
precision_allowance = 1 / (10**precision)
|
||||
|
||||
reference_names = [d.get(item_ref_dn) for d in self.get("items") if d.get(item_ref_dn)]
|
||||
reference_details = self.get_billing_reference_details(reference_names, ref_dt + " Item", based_on)
|
||||
role_allowed_to_overbill = frappe.get_single_value("Accounts Settings", "role_allowed_to_over_bill")
|
||||
is_overbilling_allowed = role_allowed_to_overbill in frappe.get_roles()
|
||||
|
||||
for item in self.get("items"):
|
||||
if not item.get(item_ref_dn):
|
||||
continue
|
||||
for row in ref_wise_billed_amount.values():
|
||||
total_billed_amt = row.billed_amt
|
||||
allowance = get_allowance_for(row.item_code, {}, None, None, "amount")[0]
|
||||
|
||||
ref_amt = flt(reference_details.get(item.get(item_ref_dn)), self.precision(based_on, item))
|
||||
based_on_amt = flt(item.get(based_on))
|
||||
|
||||
if not ref_amt:
|
||||
if based_on_amt: # Skip warning for free items
|
||||
frappe.msgprint(
|
||||
_(
|
||||
"System will not check over billing since amount for Item {0} in {1} is zero"
|
||||
).format(item.item_code, ref_dt),
|
||||
title=_("Warning"),
|
||||
indicator="orange",
|
||||
)
|
||||
continue
|
||||
|
||||
already_billed = self.get_billed_amount_for_item(item, item_ref_dn, based_on)
|
||||
|
||||
total_billed_amt = flt(flt(already_billed) + based_on_amt, self.precision(based_on, item))
|
||||
|
||||
allowance, item_allowance, global_qty_allowance, global_amount_allowance = get_allowance_for(
|
||||
item.item_code, item_allowance, global_qty_allowance, global_amount_allowance, "amount"
|
||||
)
|
||||
|
||||
max_allowed_amt = flt(ref_amt * (100 + allowance) / 100)
|
||||
max_allowed_amt = flt(row.ref_amt * (100 + allowance) / 100)
|
||||
|
||||
if total_billed_amt < 0 and max_allowed_amt < 0:
|
||||
# while making debit note against purchase return entry(purchase receipt) getting overbill error
|
||||
total_billed_amt = abs(total_billed_amt)
|
||||
max_allowed_amt = abs(max_allowed_amt)
|
||||
total_billed_amt, max_allowed_amt = abs(total_billed_amt), abs(max_allowed_amt)
|
||||
|
||||
overbill_amt = total_billed_amt - max_allowed_amt
|
||||
row["max_allowed_amt"] = max_allowed_amt
|
||||
total_overbilled_amt += overbill_amt
|
||||
|
||||
if overbill_amt > 0.01 and role_allowed_to_over_bill not in user_roles:
|
||||
if self.doctype != "Purchase Invoice":
|
||||
self.throw_overbill_exception(item, max_allowed_amt)
|
||||
elif not cint(
|
||||
if overbill_amt > precision_allowance and not is_overbilling_allowed:
|
||||
if self.doctype != "Purchase Invoice" or not cint(
|
||||
frappe.db.get_single_value(
|
||||
"Buying Settings", "bill_for_rejected_quantity_in_purchase_invoice"
|
||||
)
|
||||
):
|
||||
self.throw_overbill_exception(item, max_allowed_amt)
|
||||
overbilled_items.append(row)
|
||||
|
||||
if role_allowed_to_over_bill in user_roles and total_overbilled_amt > 0.1:
|
||||
if overbilled_items:
|
||||
self.throw_overbill_exception(overbilled_items, precision)
|
||||
|
||||
if is_overbilling_allowed and total_overbilled_amt > 0.1:
|
||||
frappe.msgprint(
|
||||
_("Overbilling of {} ignored because you have {} role.").format(
|
||||
total_overbilled_amt, role_allowed_to_over_bill
|
||||
total_overbilled_amt, role_allowed_to_overbill
|
||||
),
|
||||
indicator="orange",
|
||||
alert=True,
|
||||
@@ -2112,55 +2100,88 @@ class AccountsController(TransactionBase):
|
||||
)
|
||||
)
|
||||
|
||||
def get_billed_amount_for_item(self, item, item_ref_dn, based_on):
|
||||
def get_reference_wise_billed_amt(self, ref_dt, item_ref_dn, based_on):
|
||||
"""
|
||||
Returns Sum of Amount of
|
||||
Sales/Purchase Invoice Items
|
||||
that are linked to `item_ref_dn` (`dn_detail` / `pr_detail`)
|
||||
that are submitted OR not submitted but are under current invoice
|
||||
"""
|
||||
reference_names = [d.get(item_ref_dn) for d in self.items if d.get(item_ref_dn)]
|
||||
|
||||
from frappe.query_builder import Criterion
|
||||
from frappe.query_builder.functions import Sum
|
||||
if not reference_names:
|
||||
return
|
||||
|
||||
item_doctype = frappe.qb.DocType(item.doctype)
|
||||
ref_wise_billed_amount = {}
|
||||
precision = self.precision(based_on, "items")
|
||||
reference_details = self.get_billing_reference_details(reference_names, ref_dt + " Item", based_on)
|
||||
already_billed = self.get_already_billed_amount(reference_names, item_ref_dn, based_on)
|
||||
|
||||
for item in self.items:
|
||||
key = item.get(item_ref_dn)
|
||||
if not key:
|
||||
continue
|
||||
|
||||
ref_amt = flt(reference_details.get(key), precision)
|
||||
current_amount = flt(item.get(based_on), precision)
|
||||
|
||||
if not ref_amt:
|
||||
if current_amount: # Skip warning for free items
|
||||
frappe.msgprint(
|
||||
_(
|
||||
"System will not check over billing since amount for Item {0} in {1} is zero"
|
||||
).format(item.item_code, ref_dt),
|
||||
title=_("Warning"),
|
||||
indicator="orange",
|
||||
)
|
||||
continue
|
||||
|
||||
ref_wise_billed_amount.setdefault(
|
||||
key,
|
||||
frappe._dict(item_code=item.item_code, billed_amt=0.0, ref_amt=ref_amt, rows=[]),
|
||||
)
|
||||
|
||||
ref_wise_billed_amount[key]["rows"].append(item.idx)
|
||||
ref_wise_billed_amount[key]["ref_amt"] = ref_amt
|
||||
ref_wise_billed_amount[key]["billed_amt"] += current_amount
|
||||
if key in already_billed:
|
||||
ref_wise_billed_amount[key]["billed_amt"] += flt(already_billed.pop(key, 0), precision)
|
||||
|
||||
return ref_wise_billed_amount
|
||||
|
||||
def get_already_billed_amount(self, reference_names, item_ref_dn, based_on):
|
||||
item_doctype = frappe.qb.DocType(self.items[0].doctype)
|
||||
based_on_field = frappe.qb.Field(based_on)
|
||||
join_field = frappe.qb.Field(item_ref_dn)
|
||||
|
||||
result = (
|
||||
frappe.qb.from_(item_doctype)
|
||||
.select(Sum(based_on_field))
|
||||
.where(join_field == item.get(item_ref_dn))
|
||||
.where(
|
||||
Criterion.any(
|
||||
[ # select all items from other invoices OR current invoices
|
||||
Criterion.all(
|
||||
[ # for selecting items from other invoices
|
||||
item_doctype.docstatus == 1,
|
||||
item_doctype.parent != self.name,
|
||||
]
|
||||
),
|
||||
Criterion.all(
|
||||
[ # for selecting items from current invoice, that are linked to same reference
|
||||
item_doctype.docstatus == 0,
|
||||
item_doctype.parent == self.name,
|
||||
item_doctype.name != item.name,
|
||||
]
|
||||
),
|
||||
]
|
||||
)
|
||||
)
|
||||
).run()
|
||||
|
||||
return result[0][0] if result else 0
|
||||
|
||||
def throw_overbill_exception(self, item, max_allowed_amt):
|
||||
frappe.throw(
|
||||
_(
|
||||
"Cannot overbill for Item {0} in row {1} more than {2}. To allow over-billing, please set allowance in Accounts Settings"
|
||||
).format(item.item_code, item.idx, max_allowed_amt)
|
||||
return frappe._dict(
|
||||
(
|
||||
frappe.qb.from_(item_doctype)
|
||||
.select(join_field, Sum(based_on_field))
|
||||
.where(join_field.isin(reference_names))
|
||||
.where((item_doctype.docstatus == 1) & (item_doctype.parent != self.name))
|
||||
.groupby(join_field)
|
||||
).run()
|
||||
)
|
||||
|
||||
def throw_overbill_exception(self, overbilled_items, precision):
|
||||
message = (
|
||||
_("<p>Cannot overbill for the following Items:</p>")
|
||||
+ "<ul>"
|
||||
+ "".join(
|
||||
_("<li>Item {0} in row(s) {1} billed more than {2}</li>").format(
|
||||
frappe.bold(item.item_code),
|
||||
", ".join(str(x) for x in item.rows),
|
||||
frappe.bold(fmt_money(item.max_allowed_amt, precision=precision, currency=self.currency)),
|
||||
)
|
||||
for item in overbilled_items
|
||||
)
|
||||
+ "</ul>"
|
||||
)
|
||||
message += _("<p>To allow over-billing, please set allowance in Accounts Settings.</p>")
|
||||
|
||||
frappe.throw(_(message))
|
||||
|
||||
def get_company_default(self, fieldname, ignore_validation=False):
|
||||
from erpnext.accounts.utils import get_company_default
|
||||
|
||||
@@ -2232,6 +2253,7 @@ class AccountsController(TransactionBase):
|
||||
def set_advance_payment_status(self):
|
||||
new_status = None
|
||||
|
||||
PaymentRequest = frappe.qb.DocType("Payment Request")
|
||||
paid_amount = frappe.get_value(
|
||||
doctype="Payment Request",
|
||||
filters={
|
||||
@@ -2239,7 +2261,7 @@ class AccountsController(TransactionBase):
|
||||
"reference_name": self.name,
|
||||
"docstatus": 1,
|
||||
},
|
||||
fieldname="sum(grand_total - outstanding_amount)",
|
||||
fieldname=Sum(PaymentRequest.grand_total - PaymentRequest.outstanding_amount),
|
||||
)
|
||||
|
||||
if not paid_amount:
|
||||
|
||||
@@ -80,6 +80,21 @@ class BuyingController(SubcontractingController):
|
||||
),
|
||||
)
|
||||
|
||||
def validate_posting_date_with_po(self):
|
||||
po_list = []
|
||||
for item in self.items:
|
||||
if item.purchase_order and item.purchase_order not in po_list:
|
||||
po_list.append(item.purchase_order)
|
||||
|
||||
for po in po_list:
|
||||
po_posting_date = frappe.get_value("Purchase Order", po, "transaction_date")
|
||||
if getdate(po_posting_date) > getdate(self.posting_date):
|
||||
frappe.throw(
|
||||
_("Posting Date {0} cannot be before Purchase Order Posting Date {1}").format(
|
||||
frappe.bold(self.posting_date), frappe.bold(po_posting_date)
|
||||
)
|
||||
)
|
||||
|
||||
def create_package_for_transfer(self) -> None:
|
||||
"""Create serial and batch package for Sourece Warehouse in case of inter transfer."""
|
||||
|
||||
@@ -241,18 +256,6 @@ class BuyingController(SubcontractingController):
|
||||
|
||||
return [d.item_code for d in self.items if d.is_fixed_asset]
|
||||
|
||||
def set_landed_cost_voucher_amount(self):
|
||||
for d in self.get("items"):
|
||||
lc_voucher_data = frappe.db.sql(
|
||||
"""select sum(applicable_charges), cost_center
|
||||
from `tabLanded Cost Item`
|
||||
where docstatus = 1 and purchase_receipt_item = %s and receipt_document = %s""",
|
||||
(d.name, self.name),
|
||||
)
|
||||
d.landed_cost_voucher_amount = lc_voucher_data[0][0] if lc_voucher_data else 0.0
|
||||
if not d.cost_center and lc_voucher_data and lc_voucher_data[0][1]:
|
||||
d.db_set("cost_center", lc_voucher_data[0][1])
|
||||
|
||||
def validate_from_warehouse(self):
|
||||
for item in self.get("items"):
|
||||
if item.get("from_warehouse") and (item.get("from_warehouse") == item.get("warehouse")):
|
||||
|
||||
@@ -242,7 +242,7 @@ def enqueue_multiple_variant_creation(item, args, use_template_image=False):
|
||||
item=item,
|
||||
args=args,
|
||||
use_template_image=use_template_image,
|
||||
now=frappe.flags.in_test,
|
||||
now=frappe.in_test,
|
||||
)
|
||||
return "queued"
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import frappe
|
||||
from frappe import _
|
||||
from frappe.model.meta import get_field_precision
|
||||
from frappe.query_builder import DocType
|
||||
from frappe.query_builder.functions import Abs
|
||||
from frappe.utils import cint, flt, format_datetime, get_datetime
|
||||
|
||||
import erpnext
|
||||
@@ -661,7 +662,8 @@ def get_rate_for_return(
|
||||
if voucher_type in ("Purchase Receipt", "Purchase Invoice", "Subcontracting Receipt"):
|
||||
select_field = "incoming_rate"
|
||||
else:
|
||||
select_field = "abs(stock_value_difference / actual_qty)"
|
||||
StockLedgerEntry = frappe.qb.DocType("Stock Ledger Entry")
|
||||
select_field = Abs(StockLedgerEntry.stock_value_difference / StockLedgerEntry.actual_qty)
|
||||
|
||||
rate = flt(frappe.db.get_value("Stock Ledger Entry", filters, select_field))
|
||||
if not (rate and return_against) and voucher_type in ["Sales Invoice", "Delivery Note"]:
|
||||
@@ -683,6 +685,14 @@ def get_rate_for_return(
|
||||
raise_error_if_no_rate=False,
|
||||
)
|
||||
|
||||
if not rate and voucher_type in ["Sales Invoice", "Delivery Note"]:
|
||||
details = frappe.db.get_value(
|
||||
voucher_type + " Item", voucher_detail_no, ["rate", "allow_zero_valuation_rate"], as_dict=1
|
||||
)
|
||||
|
||||
if details and not details.allow_zero_valuation_rate:
|
||||
rate = flt(details.rate)
|
||||
|
||||
return rate
|
||||
|
||||
|
||||
|
||||
@@ -527,6 +527,15 @@ class SellingController(StockController):
|
||||
self.doctype, self.name, d.item_code, self.return_against, item_row=d
|
||||
)
|
||||
|
||||
if (
|
||||
self.get("is_return")
|
||||
and not d.incoming_rate
|
||||
and not self.get("return_against")
|
||||
and not self.is_internal_transfer()
|
||||
and not d.get("allow_zero_valuation_rate")
|
||||
):
|
||||
d.incoming_rate = d.rate
|
||||
|
||||
# For internal transfers use incoming rate as the valuation rate
|
||||
if self.is_internal_transfer():
|
||||
if self.doctype == "Delivery Note" or self.get("update_stock"):
|
||||
|
||||
@@ -164,6 +164,17 @@ status_map = {
|
||||
["Draft", None],
|
||||
["Completed", "eval:self.docstatus == 1"],
|
||||
],
|
||||
"Pick List": [
|
||||
["Draft", None],
|
||||
["Open", "eval:self.docstatus == 1"],
|
||||
["Completed", "stock_entry_exists"],
|
||||
[
|
||||
"Partly Delivered",
|
||||
"eval:self.purpose == 'Delivery' and self.delivery_status == 'Partly Delivered'",
|
||||
],
|
||||
["Completed", "eval:self.purpose == 'Delivery' and self.delivery_status == 'Fully Delivered'"],
|
||||
["Cancelled", "eval:self.docstatus == 2"],
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ from collections import defaultdict
|
||||
|
||||
import frappe
|
||||
from frappe import _, bold
|
||||
from frappe.query_builder.functions import Sum
|
||||
from frappe.utils import cint, cstr, flt, get_link_to_form, getdate
|
||||
|
||||
import erpnext
|
||||
@@ -64,6 +65,8 @@ class StockController(AccountsController):
|
||||
self.validate_internal_transfer()
|
||||
self.validate_putaway_capacity()
|
||||
self.reset_conversion_factor()
|
||||
|
||||
def on_update(self):
|
||||
self.check_zero_rate()
|
||||
|
||||
def reset_conversion_factor(self):
|
||||
@@ -229,7 +232,7 @@ class StockController(AccountsController):
|
||||
return
|
||||
|
||||
# To handle test cases
|
||||
if frappe.flags.in_test and frappe.flags.use_serial_and_batch_fields:
|
||||
if frappe.in_test and frappe.flags.use_serial_and_batch_fields:
|
||||
return
|
||||
|
||||
if not table_name:
|
||||
@@ -243,7 +246,11 @@ class StockController(AccountsController):
|
||||
parent_details = self.get_parent_details_for_packed_items()
|
||||
|
||||
for row in self.get(table_name):
|
||||
if row.serial_and_batch_bundle and (row.serial_no or row.batch_no):
|
||||
if (
|
||||
not via_landed_cost_voucher
|
||||
and row.serial_and_batch_bundle
|
||||
and (row.serial_no or row.batch_no)
|
||||
):
|
||||
self.validate_serial_nos_and_batches_with_bundle(row)
|
||||
|
||||
if not row.serial_no and not row.batch_no and not row.get("rejected_serial_no"):
|
||||
@@ -884,6 +891,91 @@ class StockController(AccountsController):
|
||||
|
||||
return sl_dict
|
||||
|
||||
def set_landed_cost_voucher_amount(self):
|
||||
for d in self.get("items"):
|
||||
lcv_item = frappe.qb.DocType("Landed Cost Item")
|
||||
query = (
|
||||
frappe.qb.from_(lcv_item)
|
||||
.select(Sum(lcv_item.applicable_charges), lcv_item.cost_center)
|
||||
.where((lcv_item.docstatus == 1) & (lcv_item.receipt_document == self.name))
|
||||
)
|
||||
|
||||
if self.doctype == "Stock Entry":
|
||||
query = query.where(lcv_item.stock_entry_item == d.name)
|
||||
else:
|
||||
query = query.where(lcv_item.purchase_receipt_item == d.name)
|
||||
|
||||
lc_voucher_data = query.run(as_list=True)
|
||||
|
||||
d.landed_cost_voucher_amount = lc_voucher_data[0][0] if lc_voucher_data else 0.0
|
||||
if not d.cost_center and lc_voucher_data and lc_voucher_data[0][1]:
|
||||
d.db_set("cost_center", lc_voucher_data[0][1])
|
||||
|
||||
def has_landed_cost_amount(self):
|
||||
for row in self.items:
|
||||
if row.get("landed_cost_voucher_amount"):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def get_item_account_wise_lcv_entries(self):
|
||||
if not self.has_landed_cost_amount():
|
||||
return
|
||||
|
||||
landed_cost_vouchers = frappe.get_all(
|
||||
"Landed Cost Purchase Receipt",
|
||||
fields=["parent"],
|
||||
filters={"receipt_document": self.name, "docstatus": 1},
|
||||
)
|
||||
|
||||
if not landed_cost_vouchers:
|
||||
return
|
||||
|
||||
item_account_wise_cost = {}
|
||||
|
||||
row_fieldname = "purchase_receipt_item"
|
||||
if self.doctype == "Stock Entry":
|
||||
row_fieldname = "stock_entry_item"
|
||||
|
||||
for lcv in landed_cost_vouchers:
|
||||
landed_cost_voucher_doc = frappe.get_doc("Landed Cost Voucher", lcv.parent)
|
||||
|
||||
based_on_field = "applicable_charges"
|
||||
# Use amount field for total item cost for manually cost distributed LCVs
|
||||
if landed_cost_voucher_doc.distribute_charges_based_on != "Distribute Manually":
|
||||
based_on_field = frappe.scrub(landed_cost_voucher_doc.distribute_charges_based_on)
|
||||
|
||||
total_item_cost = 0
|
||||
|
||||
if based_on_field:
|
||||
for item in landed_cost_voucher_doc.items:
|
||||
total_item_cost += item.get(based_on_field)
|
||||
|
||||
for item in landed_cost_voucher_doc.items:
|
||||
if item.receipt_document == self.name:
|
||||
for account in landed_cost_voucher_doc.taxes:
|
||||
exchange_rate = account.exchange_rate or 1
|
||||
item_account_wise_cost.setdefault((item.item_code, item.get(row_fieldname)), {})
|
||||
item_account_wise_cost[(item.item_code, item.get(row_fieldname))].setdefault(
|
||||
account.expense_account, {"amount": 0.0, "base_amount": 0.0}
|
||||
)
|
||||
|
||||
item_row = item_account_wise_cost[(item.item_code, item.get(row_fieldname))][
|
||||
account.expense_account
|
||||
]
|
||||
|
||||
if total_item_cost > 0:
|
||||
item_row["amount"] += account.amount * item.get(based_on_field) / total_item_cost
|
||||
|
||||
item_row["base_amount"] += (
|
||||
account.base_amount * item.get(based_on_field) / total_item_cost
|
||||
)
|
||||
else:
|
||||
item_row["amount"] += item.applicable_charges / exchange_rate
|
||||
item_row["base_amount"] += item.applicable_charges
|
||||
|
||||
return item_account_wise_cost
|
||||
|
||||
def update_inventory_dimensions(self, row, sl_dict) -> None:
|
||||
# To handle delivery note and sales invoice
|
||||
if row.get("item_row"):
|
||||
@@ -934,7 +1026,7 @@ class StockController(AccountsController):
|
||||
fieldname = f"{dimension.source_fieldname}"
|
||||
|
||||
sl_dict[dimension.target_fieldname] = row.get(fieldname)
|
||||
return
|
||||
continue
|
||||
|
||||
sl_dict[dimension.target_fieldname] = row.get(dimension.source_fieldname)
|
||||
else:
|
||||
|
||||
@@ -935,7 +935,10 @@ class TestAccountsController(IntegrationTestCase):
|
||||
self.assertEqual(exc_je_for_si, [])
|
||||
self.assertEqual(exc_je_for_pe, [])
|
||||
|
||||
@IntegrationTestCase.change_settings("Accounts Settings", {"add_taxes_from_item_tax_template": 1})
|
||||
@IntegrationTestCase.change_settings(
|
||||
"Accounts Settings",
|
||||
{"add_taxes_from_item_tax_template": 0, "add_taxes_from_taxes_and_charges_template": 1},
|
||||
)
|
||||
def test_18_fetch_taxes_based_on_taxes_and_charges_template(self):
|
||||
# Create a Sales Taxes and Charges Template
|
||||
if not frappe.db.exists("Sales Taxes and Charges Template", "_Test Tax - _TC"):
|
||||
@@ -964,6 +967,30 @@ class TestAccountsController(IntegrationTestCase):
|
||||
|
||||
self.assertEqual(sinv.total_taxes_and_charges, 4.5)
|
||||
|
||||
@IntegrationTestCase.change_settings(
|
||||
"Accounts Settings",
|
||||
{"add_taxes_from_item_tax_template": 1, "add_taxes_from_taxes_and_charges_template": 0},
|
||||
)
|
||||
def test_19_fetch_taxes_based_on_item_tax_template_template(self):
|
||||
# Create a Sales Invoice
|
||||
sinv = frappe.new_doc("Sales Invoice")
|
||||
sinv.customer = self.customer
|
||||
sinv.company = self.company
|
||||
sinv.currency = "INR"
|
||||
sinv.append(
|
||||
"items",
|
||||
{
|
||||
"item_code": "_Test Item",
|
||||
"qty": 1,
|
||||
"rate": 50,
|
||||
"item_tax_template": "_Test Account Excise Duty @ 10 - _TC",
|
||||
},
|
||||
)
|
||||
sinv.insert()
|
||||
|
||||
self.assertEqual(sinv.taxes[0].account_head, "_Test Account Excise Duty - _TC")
|
||||
self.assertEqual(sinv.total_taxes_and_charges, 5)
|
||||
|
||||
def test_20_journal_against_sales_invoice(self):
|
||||
# Invoice in Foreign Currency
|
||||
si = self.create_sales_invoice(qty=1, conversion_rate=80, rate=1)
|
||||
|
||||
@@ -5,7 +5,6 @@ import frappe
|
||||
from frappe.core.doctype.user_permission.test_user_permission import create_user
|
||||
from frappe.core.doctype.user_permission.user_permission import add_user_permissions
|
||||
from frappe.custom.doctype.property_setter.property_setter import make_property_setter
|
||||
from frappe.tests import IntegrationTestCase
|
||||
|
||||
from erpnext.controllers import queries
|
||||
from erpnext.tests.utils import ERPNextTestSuite
|
||||
@@ -120,7 +119,7 @@ class TestQueries(ERPNextTestSuite):
|
||||
}
|
||||
)
|
||||
|
||||
with IntegrationTestCase.set_user(user.name):
|
||||
with self.set_user(user.name):
|
||||
params = {
|
||||
"doctype": "Employee",
|
||||
"txt": "",
|
||||
|
||||
@@ -97,10 +97,13 @@ def get_data(filters, conditions):
|
||||
elif filters.get("group_by") == "Supplier":
|
||||
sel_col = "t1.supplier"
|
||||
|
||||
if filters.get("based_on") in ["Item", "Customer", "Supplier"]:
|
||||
if filters.get("based_on") in ["Customer", "Supplier"]:
|
||||
inc = 3
|
||||
elif filters.get("based_on") in ["Item"]:
|
||||
inc = 2
|
||||
else:
|
||||
inc = 1
|
||||
|
||||
data1 = frappe.db.sql(
|
||||
""" select {} from `tab{}` t1, `tab{} Item` t2 {}
|
||||
where t2.parent = t1.name and t1.company = {} and {} between {} and {} and
|
||||
@@ -157,7 +160,7 @@ def get_data(filters, conditions):
|
||||
|
||||
# get data for group_by filter
|
||||
row1 = frappe.db.sql(
|
||||
""" select t1.currency , {} , {} from `tab{}` t1, `tab{} Item` t2 {}
|
||||
""" select t4.default_currency AS currency , {} , {} from `tab{}` t1, `tab{} Item` t2 {}
|
||||
where t2.parent = t1.name and t1.company = {} and {} between {} and {}
|
||||
and t1.docstatus = 1 and {} = {} and {} = {} {} {}
|
||||
""".format(
|
||||
@@ -330,11 +333,20 @@ def based_wise_columns_query(based_on, trans):
|
||||
based_on_details["addl_tables"] = ""
|
||||
|
||||
elif based_on == "Customer":
|
||||
based_on_details["based_on_cols"] = [
|
||||
"Customer:Link/Customer:120",
|
||||
"Territory:Link/Territory:120",
|
||||
]
|
||||
based_on_details["based_on_select"] = "t1.customer_name, t1.territory, "
|
||||
if trans == "Quotation":
|
||||
based_on_details["based_on_cols"] = [
|
||||
"Party:Link/Customer:120",
|
||||
"Party Name:Data:120",
|
||||
"Territory:Link/Territory:120",
|
||||
]
|
||||
based_on_details["based_on_select"] = "t1.party_name, t1.customer_name, t1.territory,"
|
||||
else:
|
||||
based_on_details["based_on_cols"] = [
|
||||
"Customer:Link/Customer:120",
|
||||
"Customer Name:Data:120",
|
||||
"Territory:Link/Territory:120",
|
||||
]
|
||||
based_on_details["based_on_select"] = "t1.customer, t1.customer_name, t1.territory,"
|
||||
based_on_details["based_on_group_by"] = "t1.party_name" if trans == "Quotation" else "t1.customer"
|
||||
based_on_details["addl_tables"] = ""
|
||||
|
||||
@@ -347,9 +359,10 @@ def based_wise_columns_query(based_on, trans):
|
||||
elif based_on == "Supplier":
|
||||
based_on_details["based_on_cols"] = [
|
||||
"Supplier:Link/Supplier:120",
|
||||
"Supplier Name:Data:120",
|
||||
"Supplier Group:Link/Supplier Group:140",
|
||||
]
|
||||
based_on_details["based_on_select"] = "t1.supplier, t3.supplier_group,"
|
||||
based_on_details["based_on_select"] = "t1.supplier, t1.supplier_name, t3.supplier_group,"
|
||||
based_on_details["based_on_group_by"] = "t1.supplier"
|
||||
based_on_details["addl_tables"] = ",`tabSupplier` t3"
|
||||
based_on_details["addl_tables_relational_cond"] = " and t1.supplier = t3.name"
|
||||
@@ -381,8 +394,12 @@ def based_wise_columns_query(based_on, trans):
|
||||
else:
|
||||
frappe.throw(_("Project-wise data is not available for Quotation"))
|
||||
|
||||
based_on_details["based_on_select"] += "t1.currency,"
|
||||
based_on_details["based_on_select"] += "t4.default_currency as currency,"
|
||||
based_on_details["based_on_cols"].append("Currency:Link/Currency:120")
|
||||
based_on_details["addl_tables"] += ", `tabCompany` t4"
|
||||
based_on_details["addl_tables_relational_cond"] = (
|
||||
based_on_details.get("addl_tables_relational_cond", "") + " and t1.company = t4.name"
|
||||
)
|
||||
|
||||
return based_on_details
|
||||
|
||||
|
||||
Reference in New Issue
Block a user