mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-01 03:09:09 +00:00
refactor(treewide): formatting and ruff fixes, + manually enabled F401
Signed-off-by: Akhil Narang <me@akhilnarang.dev>
This commit is contained in:
@@ -18,7 +18,7 @@ from frappe.utils import cint, cstr, flt, get_formatted_email, today
|
||||
from frappe.utils.deprecations import deprecated
|
||||
from frappe.utils.user import get_users_with_role
|
||||
|
||||
from erpnext.accounts.party import get_dashboard_info, validate_party_accounts # noqa
|
||||
from erpnext.accounts.party import get_dashboard_info, validate_party_accounts
|
||||
from erpnext.controllers.website_list_for_contact import add_role_for_portal_user
|
||||
from erpnext.utilities.transaction_base import TransactionBase
|
||||
|
||||
@@ -107,17 +107,16 @@ class Customer(TransactionBase):
|
||||
self.name = set_name_from_naming_options(frappe.get_meta(self.doctype).autoname, self)
|
||||
|
||||
def get_customer_name(self):
|
||||
|
||||
if frappe.db.get_value("Customer", self.customer_name) and not frappe.flags.in_import:
|
||||
count = frappe.db.sql(
|
||||
"""select ifnull(MAX(CAST(SUBSTRING_INDEX(name, ' ', -1) AS UNSIGNED)), 0) from tabCustomer
|
||||
where name like %s""",
|
||||
"%{0} - %".format(self.customer_name),
|
||||
f"%{self.customer_name} - %",
|
||||
as_list=1,
|
||||
)[0][0]
|
||||
count = cint(count) + 1
|
||||
|
||||
new_customer_name = "{0} - {1}".format(self.customer_name, cstr(count))
|
||||
new_customer_name = f"{self.customer_name} - {cstr(count)}"
|
||||
|
||||
msgprint(
|
||||
_("Changed customer name to '{}' as '{}' already exists.").format(
|
||||
@@ -322,9 +321,7 @@ class Customer(TransactionBase):
|
||||
)
|
||||
]
|
||||
|
||||
current_credit_limits = [
|
||||
d.credit_limit for d in sorted(self.credit_limits, key=lambda k: k.company)
|
||||
]
|
||||
current_credit_limits = [d.credit_limit for d in sorted(self.credit_limits, key=lambda k: k.company)]
|
||||
|
||||
if past_credit_limits == current_credit_limits:
|
||||
return
|
||||
@@ -506,9 +503,7 @@ def get_loyalty_programs(doc):
|
||||
) and (
|
||||
not loyalty_program.customer_territory
|
||||
or doc.territory
|
||||
in get_nested_links(
|
||||
"Territory", loyalty_program.customer_territory, doc.flags.ignore_permissions
|
||||
)
|
||||
in get_nested_links("Territory", loyalty_program.customer_territory, doc.flags.ignore_permissions)
|
||||
):
|
||||
lp_details.append(loyalty_program.name)
|
||||
|
||||
@@ -554,12 +549,12 @@ def check_credit_limit(customer, company, ignore_outstanding_sales_order=False,
|
||||
]
|
||||
if not credit_controller_users_formatted:
|
||||
frappe.throw(
|
||||
_("Please contact your administrator to extend the credit limits for {0}.").format(customer)
|
||||
_("Please contact your administrator to extend the credit limits for {0}.").format(
|
||||
customer
|
||||
)
|
||||
)
|
||||
|
||||
user_list = "<br><br><ul><li>{0}</li></ul>".format(
|
||||
"<li>".join(credit_controller_users_formatted)
|
||||
)
|
||||
user_list = "<br><br><ul><li>{}</li></ul>".format("<li>".join(credit_controller_users_formatted))
|
||||
|
||||
message += _(
|
||||
"Please contact any of the following users to extend the credit limits for {0}: {1}"
|
||||
@@ -592,32 +587,24 @@ def send_emails(args):
|
||||
message = _("Credit limit has been crossed for customer {0} ({1}/{2})").format(
|
||||
args.get("customer"), args.get("customer_outstanding"), args.get("credit_limit")
|
||||
)
|
||||
frappe.sendmail(
|
||||
recipients=args.get("credit_controller_users_list"), subject=subject, message=message
|
||||
)
|
||||
frappe.sendmail(recipients=args.get("credit_controller_users_list"), subject=subject, message=message)
|
||||
|
||||
|
||||
def get_customer_outstanding(
|
||||
customer, company, ignore_outstanding_sales_order=False, cost_center=None
|
||||
):
|
||||
def get_customer_outstanding(customer, company, ignore_outstanding_sales_order=False, cost_center=None):
|
||||
# Outstanding based on GL Entries
|
||||
cond = ""
|
||||
if cost_center:
|
||||
lft, rgt = frappe.get_cached_value("Cost Center", cost_center, ["lft", "rgt"])
|
||||
|
||||
cond = """ and cost_center in (select name from `tabCost Center` where
|
||||
lft >= {0} and rgt <= {1})""".format(
|
||||
lft, rgt
|
||||
)
|
||||
cond = f""" and cost_center in (select name from `tabCost Center` where
|
||||
lft >= {lft} and rgt <= {rgt})"""
|
||||
|
||||
outstanding_based_on_gle = frappe.db.sql(
|
||||
"""
|
||||
f"""
|
||||
select sum(debit) - sum(credit)
|
||||
from `tabGL Entry` where party_type = 'Customer'
|
||||
and is_cancelled = 0 and party = %s
|
||||
and company=%s {0}""".format(
|
||||
cond
|
||||
),
|
||||
and company=%s {cond}""",
|
||||
(customer, company),
|
||||
)
|
||||
|
||||
@@ -765,7 +752,7 @@ def make_address(args, is_primary_address=1, is_shipping_address=1):
|
||||
if reqd_fields:
|
||||
msg = _("Following fields are mandatory to create address:")
|
||||
frappe.throw(
|
||||
"{0} <br><br> <ul>{1}</ul>".format(msg, "\n".join(reqd_fields)),
|
||||
"{} <br><br> <ul>{}</ul>".format(msg, "\n".join(reqd_fields)),
|
||||
title=_("Missing Values Required"),
|
||||
)
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
|
||||
import frappe
|
||||
from frappe.custom.doctype.property_setter.property_setter import make_property_setter
|
||||
from frappe.test_runner import make_test_records
|
||||
from frappe.tests.utils import FrappeTestCase
|
||||
from frappe.utils import flt
|
||||
@@ -268,7 +267,6 @@ class TestCustomer(FrappeTestCase):
|
||||
|
||||
def test_customer_credit_limit(self):
|
||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||
from erpnext.selling.doctype.sales_order.sales_order import make_sales_invoice
|
||||
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
|
||||
from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
|
||||
|
||||
@@ -412,17 +410,13 @@ def set_credit_limit(customer, company, credit_limit):
|
||||
customer.credit_limits[-1].db_insert()
|
||||
|
||||
|
||||
def create_internal_customer(
|
||||
customer_name=None, represents_company=None, allowed_to_interact_with=None
|
||||
):
|
||||
def create_internal_customer(customer_name=None, represents_company=None, allowed_to_interact_with=None):
|
||||
if not customer_name:
|
||||
customer_name = represents_company
|
||||
if not allowed_to_interact_with:
|
||||
allowed_to_interact_with = represents_company
|
||||
|
||||
exisiting_representative = frappe.db.get_value(
|
||||
"Customer", {"represents_company": represents_company}
|
||||
)
|
||||
exisiting_representative = frappe.db.get_value("Customer", {"represents_company": represents_company})
|
||||
if exisiting_representative:
|
||||
return exisiting_representative
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ class InstallationNote(TransactionBase):
|
||||
# end: auto-generated types
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(InstallationNote, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.status_updater = [
|
||||
{
|
||||
"source_dt": "Installation Note Item",
|
||||
|
||||
@@ -65,7 +65,7 @@ class ProductBundle(Document):
|
||||
|
||||
if len(invoice_links):
|
||||
frappe.throw(
|
||||
"This Product Bundle is linked with {0}. You will have to cancel these documents in order to delete this Product Bundle".format(
|
||||
"This Product Bundle is linked with {}. You will have to cancel these documents in order to delete this Product Bundle".format(
|
||||
", ".join(invoice_links)
|
||||
),
|
||||
title=_("Not Allowed"),
|
||||
@@ -97,9 +97,7 @@ def get_new_item_code(doctype, txt, searchfield, start, page_len, filters):
|
||||
query = (
|
||||
frappe.qb.from_(item)
|
||||
.select(item.item_code, item.item_name)
|
||||
.where(
|
||||
(item.is_stock_item == 0) & (item.is_fixed_asset == 0) & (item[searchfield].like(f"%{txt}%"))
|
||||
)
|
||||
.where((item.is_stock_item == 0) & (item.is_fixed_asset == 0) & (item[searchfield].like(f"%{txt}%")))
|
||||
.limit(page_len)
|
||||
.offset(start)
|
||||
)
|
||||
|
||||
@@ -125,7 +125,7 @@ class Quotation(SellingController):
|
||||
self.indicator_title = "Expired"
|
||||
|
||||
def validate(self):
|
||||
super(Quotation, self).validate()
|
||||
super().validate()
|
||||
self.set_status()
|
||||
self.validate_uom_is_integer("stock_uom", "stock_qty")
|
||||
self.validate_uom_is_integer("uom", "qty")
|
||||
@@ -188,7 +188,8 @@ class Quotation(SellingController):
|
||||
def is_in_sales_order(row):
|
||||
in_sales_order = bool(
|
||||
frappe.db.exists(
|
||||
"Sales Order Item", {"quotation_item": row.name, "item_code": row.item_code, "docstatus": 1}
|
||||
"Sales Order Item",
|
||||
{"quotation_item": row.name, "item_code": row.item_code, "docstatus": 1},
|
||||
)
|
||||
)
|
||||
return in_sales_order
|
||||
@@ -278,7 +279,7 @@ class Quotation(SellingController):
|
||||
def on_cancel(self):
|
||||
if self.lost_reasons:
|
||||
self.lost_reasons = []
|
||||
super(Quotation, self).on_cancel()
|
||||
super().on_cancel()
|
||||
|
||||
# update enquiry status
|
||||
self.set_status(update=True)
|
||||
@@ -453,12 +454,8 @@ def set_expired_status():
|
||||
# if not exists any SO, set status as Expired
|
||||
frappe.db.multisql(
|
||||
{
|
||||
"mariadb": """UPDATE `tabQuotation` SET `tabQuotation`.status = 'Expired' WHERE {cond} and not exists({so_against_quo})""".format(
|
||||
cond=cond, so_against_quo=so_against_quo
|
||||
),
|
||||
"postgres": """UPDATE `tabQuotation` SET status = 'Expired' FROM `tabSales Order`, `tabSales Order Item` WHERE {cond} and not exists({so_against_quo})""".format(
|
||||
cond=cond, so_against_quo=so_against_quo
|
||||
),
|
||||
"mariadb": f"""UPDATE `tabQuotation` SET `tabQuotation`.status = 'Expired' WHERE {cond} and not exists({so_against_quo})""",
|
||||
"postgres": f"""UPDATE `tabQuotation` SET status = 'Expired' FROM `tabSales Order`, `tabSales Order Item` WHERE {cond} and not exists({so_against_quo})""",
|
||||
},
|
||||
(nowdate()),
|
||||
)
|
||||
@@ -543,7 +540,8 @@ def _make_customer(source_name, ignore_permissions=False, customer_group=None):
|
||||
frappe.local.message_log = []
|
||||
lead_link = frappe.utils.get_link_to_form("Lead", lead_name)
|
||||
message = (
|
||||
_("Could not auto create Customer due to the following missing mandatory field(s):") + "<br>"
|
||||
_("Could not auto create Customer due to the following missing mandatory field(s):")
|
||||
+ "<br>"
|
||||
)
|
||||
message += "<br><ul><li>" + "</li><li>".join(mandatory_fields) + "</li></ul>"
|
||||
message += _("Please create Customer from Lead {0}.").format(lead_link)
|
||||
|
||||
@@ -140,9 +140,7 @@ class TestQuotation(FrappeTestCase):
|
||||
self.assertEqual(quotation.payment_schedule[0].payment_amount, 8906.00)
|
||||
self.assertEqual(quotation.payment_schedule[0].due_date, quotation.transaction_date)
|
||||
self.assertEqual(quotation.payment_schedule[1].payment_amount, 8906.00)
|
||||
self.assertEqual(
|
||||
quotation.payment_schedule[1].due_date, add_days(quotation.transaction_date, 30)
|
||||
)
|
||||
self.assertEqual(quotation.payment_schedule[1].due_date, add_days(quotation.transaction_date, 30))
|
||||
|
||||
sales_order = make_sales_order(quotation.name)
|
||||
|
||||
@@ -175,9 +173,7 @@ class TestQuotation(FrappeTestCase):
|
||||
def test_so_from_expired_quotation(self):
|
||||
from erpnext.selling.doctype.quotation.quotation import make_sales_order
|
||||
|
||||
frappe.db.set_single_value(
|
||||
"Selling Settings", "allow_sales_order_creation_for_expired_quotation", 0
|
||||
)
|
||||
frappe.db.set_single_value("Selling Settings", "allow_sales_order_creation_for_expired_quotation", 0)
|
||||
|
||||
quotation = frappe.copy_doc(test_records[0])
|
||||
quotation.valid_till = add_days(nowdate(), -1)
|
||||
@@ -186,9 +182,7 @@ class TestQuotation(FrappeTestCase):
|
||||
|
||||
self.assertRaises(frappe.ValidationError, make_sales_order, quotation.name)
|
||||
|
||||
frappe.db.set_single_value(
|
||||
"Selling Settings", "allow_sales_order_creation_for_expired_quotation", 1
|
||||
)
|
||||
frappe.db.set_single_value("Selling Settings", "allow_sales_order_creation_for_expired_quotation", 1)
|
||||
|
||||
make_sales_order(quotation.name)
|
||||
|
||||
@@ -646,7 +640,7 @@ class TestQuotation(FrappeTestCase):
|
||||
).insert()
|
||||
|
||||
if not frappe.db.exists("Item Tax Template", "Vat Template - _TC"):
|
||||
doc = frappe.get_doc(
|
||||
frappe.get_doc(
|
||||
{
|
||||
"doctype": "Item Tax Template",
|
||||
"name": "Vat Template",
|
||||
@@ -668,9 +662,7 @@ class TestQuotation(FrappeTestCase):
|
||||
item_doc.append("taxes", {"item_tax_template": "Vat Template - _TC"})
|
||||
item_doc.save()
|
||||
|
||||
quotation = make_quotation(
|
||||
item_code="_Test Item Tax Template QTN", qty=1, rate=100, do_not_submit=1
|
||||
)
|
||||
quotation = make_quotation(item_code="_Test Item Tax Template QTN", qty=1, rate=100, do_not_submit=1)
|
||||
self.assertFalse(quotation.taxes)
|
||||
|
||||
quotation.append_taxes_from_item_tax_template()
|
||||
|
||||
@@ -182,7 +182,7 @@ class SalesOrder(SellingController):
|
||||
# end: auto-generated types
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SalesOrder, self).__init__(*args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def onload(self) -> None:
|
||||
if frappe.db.get_single_value("Stock Settings", "enable_stock_reservation"):
|
||||
@@ -193,7 +193,7 @@ class SalesOrder(SellingController):
|
||||
self.set_onload("has_reserved_stock", True)
|
||||
|
||||
def validate(self):
|
||||
super(SalesOrder, self).validate()
|
||||
super().validate()
|
||||
self.validate_delivery_date()
|
||||
self.validate_proj_cust()
|
||||
self.validate_po()
|
||||
@@ -234,7 +234,9 @@ class SalesOrder(SellingController):
|
||||
for d in self.get("items"):
|
||||
if d.delivery_date and getdate(self.po_date) > getdate(d.delivery_date):
|
||||
frappe.throw(
|
||||
_("Row #{0}: Expected Delivery Date cannot be before Purchase Order Date").format(d.idx)
|
||||
_("Row #{0}: Expected Delivery Date cannot be before Purchase Order Date").format(
|
||||
d.idx
|
||||
)
|
||||
)
|
||||
|
||||
if self.po_no and self.customer and not self.skip_delivery_note:
|
||||
@@ -249,9 +251,9 @@ class SalesOrder(SellingController):
|
||||
frappe.db.get_single_value("Selling Settings", "allow_against_multiple_purchase_orders")
|
||||
):
|
||||
frappe.msgprint(
|
||||
_("Warning: Sales Order {0} already exists against Customer's Purchase Order {1}").format(
|
||||
frappe.bold(so[0][0]), frappe.bold(self.po_no)
|
||||
),
|
||||
_(
|
||||
"Warning: Sales Order {0} already exists against Customer's Purchase Order {1}"
|
||||
).format(frappe.bold(so[0][0]), frappe.bold(self.po_no)),
|
||||
alert=True,
|
||||
)
|
||||
else:
|
||||
@@ -261,14 +263,15 @@ class SalesOrder(SellingController):
|
||||
).format(
|
||||
frappe.bold(so[0][0]),
|
||||
frappe.bold(self.po_no),
|
||||
frappe.bold(_("'Allow Multiple Sales Orders Against a Customer's Purchase Order'")),
|
||||
frappe.bold(
|
||||
_("'Allow Multiple Sales Orders Against a Customer's Purchase Order'")
|
||||
),
|
||||
get_link_to_form("Selling Settings", "Selling Settings"),
|
||||
)
|
||||
)
|
||||
|
||||
def validate_for_items(self):
|
||||
for d in self.get("items"):
|
||||
|
||||
# used for production plan
|
||||
d.transaction_date = self.transaction_date
|
||||
|
||||
@@ -298,7 +301,9 @@ class SalesOrder(SellingController):
|
||||
(d.prevdoc_docname, self.order_type),
|
||||
)
|
||||
if not res:
|
||||
frappe.msgprint(_("Quotation {0} not of type {1}").format(d.prevdoc_docname, self.order_type))
|
||||
frappe.msgprint(
|
||||
_("Quotation {0} not of type {1}").format(d.prevdoc_docname, self.order_type)
|
||||
)
|
||||
|
||||
def validate_delivery_date(self):
|
||||
if self.order_type == "Sales" and not self.skip_delivery_note:
|
||||
@@ -337,13 +342,16 @@ class SalesOrder(SellingController):
|
||||
)
|
||||
|
||||
def validate_warehouse(self):
|
||||
super(SalesOrder, self).validate_warehouse()
|
||||
super().validate_warehouse()
|
||||
|
||||
for d in self.get("items"):
|
||||
if (
|
||||
(
|
||||
frappe.get_cached_value("Item", d.item_code, "is_stock_item") == 1
|
||||
or (self.has_product_bundle(d.item_code) and self.product_bundle_has_stock_item(d.item_code))
|
||||
or (
|
||||
self.has_product_bundle(d.item_code)
|
||||
and self.product_bundle_has_stock_item(d.item_code)
|
||||
)
|
||||
)
|
||||
and not d.warehouse
|
||||
and not cint(d.delivered_by_supplier)
|
||||
@@ -353,7 +361,7 @@ class SalesOrder(SellingController):
|
||||
)
|
||||
|
||||
def validate_with_previous_doc(self):
|
||||
super(SalesOrder, self).validate_with_previous_doc(
|
||||
super().validate_with_previous_doc(
|
||||
{
|
||||
"Quotation": {"ref_dn_field": "prevdoc_docname", "compare_fields": [["company", "="]]},
|
||||
"Quotation Item": {
|
||||
@@ -414,7 +422,7 @@ class SalesOrder(SellingController):
|
||||
|
||||
def on_cancel(self):
|
||||
self.ignore_linked_doctypes = ("GL Entry", "Stock Ledger Entry", "Payment Ledger Entry")
|
||||
super(SalesOrder, self).on_cancel()
|
||||
super().on_cancel()
|
||||
|
||||
# Cannot cancel closed SO
|
||||
if self.status == "Closed":
|
||||
@@ -437,9 +445,7 @@ class SalesOrder(SellingController):
|
||||
update_coupon_code_count(self.coupon_code, "cancelled")
|
||||
|
||||
def update_project(self):
|
||||
if (
|
||||
frappe.db.get_single_value("Selling Settings", "sales_update_frequency") != "Each Transaction"
|
||||
):
|
||||
if frappe.db.get_single_value("Selling Settings", "sales_update_frequency") != "Each Transaction":
|
||||
return
|
||||
|
||||
if self.project:
|
||||
@@ -477,7 +483,7 @@ class SalesOrder(SellingController):
|
||||
|
||||
def check_modified_date(self):
|
||||
mod_db = frappe.db.get_value("Sales Order", self.name, "modified")
|
||||
date_diff = frappe.db.sql("select TIMEDIFF('%s', '%s')" % (mod_db, cstr(self.modified)))
|
||||
date_diff = frappe.db.sql(f"select TIMEDIFF('{mod_db}', '{cstr(self.modified)}')")
|
||||
if date_diff and date_diff[0][0]:
|
||||
frappe.throw(_("{0} {1} has been modified. Please refresh.").format(self.doctype, self.name))
|
||||
|
||||
@@ -654,9 +660,9 @@ class SalesOrder(SellingController):
|
||||
)
|
||||
if not frappe.db.exists("BOM", {"item": item.item_code, "is_active": 1}):
|
||||
frappe.throw(
|
||||
_("No active BOM found for item {0}. Delivery by Serial No cannot be ensured").format(
|
||||
item.item_code
|
||||
)
|
||||
_(
|
||||
"No active BOM found for item {0}. Delivery by Serial No cannot be ensured"
|
||||
).format(item.item_code)
|
||||
)
|
||||
reserved_items.append(item.item_code)
|
||||
else:
|
||||
@@ -672,9 +678,7 @@ class SalesOrder(SellingController):
|
||||
def validate_reserved_stock(self):
|
||||
"""Clean reserved stock flag for non-stock Item"""
|
||||
|
||||
enable_stock_reservation = frappe.db.get_single_value(
|
||||
"Stock Settings", "enable_stock_reservation"
|
||||
)
|
||||
enable_stock_reservation = frappe.db.get_single_value("Stock Settings", "enable_stock_reservation")
|
||||
|
||||
for item in self.items:
|
||||
if item.reserve_stock and (not enable_stock_reservation or not cint(item.is_stock_item)):
|
||||
@@ -698,7 +702,7 @@ class SalesOrder(SellingController):
|
||||
@frappe.whitelist()
|
||||
def create_stock_reservation_entries(
|
||||
self,
|
||||
items_details: list[dict] = None,
|
||||
items_details: list[dict] | None = None,
|
||||
from_voucher_type: Literal["Pick List", "Purchase Receipt"] = None,
|
||||
notify=True,
|
||||
) -> None:
|
||||
@@ -732,11 +736,7 @@ def get_unreserved_qty(item: object, reserved_qty_details: dict) -> float:
|
||||
"""Returns the unreserved quantity for the Sales Order Item."""
|
||||
|
||||
existing_reserved_qty = reserved_qty_details.get(item.name, 0)
|
||||
return (
|
||||
item.stock_qty
|
||||
- flt(item.delivered_qty) * item.get("conversion_factor", 1)
|
||||
- existing_reserved_qty
|
||||
)
|
||||
return item.stock_qty - flt(item.delivered_qty) * item.get("conversion_factor", 1) - existing_reserved_qty
|
||||
|
||||
|
||||
def get_list_context(context=None):
|
||||
@@ -1175,7 +1175,7 @@ def get_events(start, end, filters=None):
|
||||
conditions = get_event_conditions("Sales Order", filters)
|
||||
|
||||
data = frappe.db.sql(
|
||||
"""
|
||||
f"""
|
||||
select
|
||||
distinct `tabSales Order`.name, `tabSales Order`.customer_name, `tabSales Order`.status,
|
||||
`tabSales Order`.delivery_status, `tabSales Order`.billing_status,
|
||||
@@ -1188,9 +1188,7 @@ def get_events(start, end, filters=None):
|
||||
and (`tabSales Order Item`.delivery_date between %(start)s and %(end)s)
|
||||
and `tabSales Order`.docstatus < 2
|
||||
{conditions}
|
||||
""".format(
|
||||
conditions=conditions
|
||||
),
|
||||
""",
|
||||
{"start": start, "end": end},
|
||||
as_dict=True,
|
||||
update={"allDay": 0},
|
||||
@@ -1264,9 +1262,7 @@ def make_purchase_order_for_default_supplier(source_name, selected_items=None, t
|
||||
items_to_map = list(set(items_to_map))
|
||||
|
||||
if not suppliers:
|
||||
frappe.throw(
|
||||
_("Please set a Supplier against the Items to be considered in the Purchase Order.")
|
||||
)
|
||||
frappe.throw(_("Please set a Supplier against the Items to be considered in the Purchase Order."))
|
||||
|
||||
purchase_orders = []
|
||||
for supplier in suppliers:
|
||||
@@ -1332,9 +1328,7 @@ def make_purchase_order(source_name, selected_items=None, target_doc=None):
|
||||
selected_items = json.loads(selected_items)
|
||||
|
||||
items_to_map = [
|
||||
item.get("item_code")
|
||||
for item in selected_items
|
||||
if item.get("item_code") and item.get("item_code")
|
||||
item.get("item_code") for item in selected_items if item.get("item_code") and item.get("item_code")
|
||||
]
|
||||
items_to_map = list(set(items_to_map))
|
||||
|
||||
@@ -1517,17 +1511,13 @@ def make_raw_material_request(items, company, sales_order, project=None):
|
||||
for item in items.get("items"):
|
||||
item["include_exploded_items"] = items.get("include_exploded_items")
|
||||
item["ignore_existing_ordered_qty"] = items.get("ignore_existing_ordered_qty")
|
||||
item["include_raw_materials_from_sales_order"] = items.get(
|
||||
"include_raw_materials_from_sales_order"
|
||||
)
|
||||
item["include_raw_materials_from_sales_order"] = items.get("include_raw_materials_from_sales_order")
|
||||
|
||||
items.update({"company": company, "sales_order": sales_order})
|
||||
|
||||
raw_materials = get_items_for_material_requests(items)
|
||||
if not raw_materials:
|
||||
frappe.msgprint(
|
||||
_("Material Request not created, as quantity for Raw Materials already available.")
|
||||
)
|
||||
frappe.msgprint(_("Material Request not created, as quantity for Raw Materials already available."))
|
||||
return
|
||||
|
||||
material_request = frappe.new_doc("Material Request")
|
||||
|
||||
@@ -306,9 +306,7 @@ class TestSalesOrder(FrappeTestCase):
|
||||
|
||||
def test_reserved_qty_for_partial_delivery_with_packing_list(self):
|
||||
make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100)
|
||||
make_stock_entry(
|
||||
item="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=10, rate=100
|
||||
)
|
||||
make_stock_entry(item="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=10, rate=100)
|
||||
|
||||
existing_reserved_qty_item1 = get_reserved_qty("_Test Item")
|
||||
existing_reserved_qty_item2 = get_reserved_qty("_Test Item Home Desktop 100")
|
||||
@@ -316,16 +314,12 @@ class TestSalesOrder(FrappeTestCase):
|
||||
so = make_sales_order(item_code="_Test Product Bundle Item")
|
||||
|
||||
self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50)
|
||||
self.assertEqual(
|
||||
get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 20
|
||||
)
|
||||
self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 20)
|
||||
|
||||
dn = create_dn_against_so(so.name)
|
||||
|
||||
self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 25)
|
||||
self.assertEqual(
|
||||
get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 10
|
||||
)
|
||||
self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 10)
|
||||
|
||||
# close so
|
||||
so.load_from_db()
|
||||
@@ -339,15 +333,11 @@ class TestSalesOrder(FrappeTestCase):
|
||||
so.update_status("Draft")
|
||||
|
||||
self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 25)
|
||||
self.assertEqual(
|
||||
get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 10
|
||||
)
|
||||
self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 10)
|
||||
|
||||
dn.cancel()
|
||||
self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50)
|
||||
self.assertEqual(
|
||||
get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 20
|
||||
)
|
||||
self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 20)
|
||||
|
||||
so.load_from_db()
|
||||
so.cancel()
|
||||
@@ -363,9 +353,7 @@ class TestSalesOrder(FrappeTestCase):
|
||||
|
||||
def test_reserved_qty_for_over_delivery_with_packing_list(self):
|
||||
make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100)
|
||||
make_stock_entry(
|
||||
item="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=10, rate=100
|
||||
)
|
||||
make_stock_entry(item="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=10, rate=100)
|
||||
|
||||
# set over-delivery allowance
|
||||
frappe.db.set_value("Item", "_Test Product Bundle Item", "over_delivery_receipt_allowance", 50)
|
||||
@@ -376,9 +364,7 @@ class TestSalesOrder(FrappeTestCase):
|
||||
so = make_sales_order(item_code="_Test Product Bundle Item")
|
||||
|
||||
self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50)
|
||||
self.assertEqual(
|
||||
get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 20
|
||||
)
|
||||
self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 20)
|
||||
|
||||
dn = create_dn_against_so(so.name, 15)
|
||||
|
||||
@@ -387,9 +373,7 @@ class TestSalesOrder(FrappeTestCase):
|
||||
|
||||
dn.cancel()
|
||||
self.assertEqual(get_reserved_qty("_Test Item"), existing_reserved_qty_item1 + 50)
|
||||
self.assertEqual(
|
||||
get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 20
|
||||
)
|
||||
self.assertEqual(get_reserved_qty("_Test Item Home Desktop 100"), existing_reserved_qty_item2 + 20)
|
||||
|
||||
def test_update_child_adding_new_item(self):
|
||||
so = make_sales_order(item_code="_Test Item", qty=4)
|
||||
@@ -459,9 +443,7 @@ class TestSalesOrder(FrappeTestCase):
|
||||
trans_item = json.dumps(
|
||||
[{"item_code": "_Test Item 2", "qty": 2, "rate": 500, "docname": so.get("items")[1].name}]
|
||||
)
|
||||
self.assertRaises(
|
||||
frappe.ValidationError, update_child_qty_rate, "Sales Order", trans_item, so.name
|
||||
)
|
||||
self.assertRaises(frappe.ValidationError, update_child_qty_rate, "Sales Order", trans_item, so.name)
|
||||
|
||||
# remove last added item
|
||||
trans_item = json.dumps(
|
||||
@@ -500,9 +482,7 @@ class TestSalesOrder(FrappeTestCase):
|
||||
trans_item = json.dumps(
|
||||
[{"item_code": "_Test Item", "rate": 200, "qty": 2, "docname": so.items[0].name}]
|
||||
)
|
||||
self.assertRaises(
|
||||
frappe.ValidationError, update_child_qty_rate, "Sales Order", trans_item, so.name
|
||||
)
|
||||
self.assertRaises(frappe.ValidationError, update_child_qty_rate, "Sales Order", trans_item, so.name)
|
||||
|
||||
def test_update_child_with_precision(self):
|
||||
from frappe.custom.doctype.property_setter.property_setter import make_property_setter
|
||||
@@ -532,15 +512,11 @@ class TestSalesOrder(FrappeTestCase):
|
||||
trans_item = json.dumps(
|
||||
[{"item_code": "_Test Item", "rate": 200, "qty": 7, "docname": so.items[0].name}]
|
||||
)
|
||||
self.assertRaises(
|
||||
frappe.ValidationError, update_child_qty_rate, "Sales Order", trans_item, so.name
|
||||
)
|
||||
self.assertRaises(frappe.ValidationError, update_child_qty_rate, "Sales Order", trans_item, so.name)
|
||||
|
||||
# add new item
|
||||
trans_item = json.dumps([{"item_code": "_Test Item", "rate": 100, "qty": 2}])
|
||||
self.assertRaises(
|
||||
frappe.ValidationError, update_child_qty_rate, "Sales Order", trans_item, so.name
|
||||
)
|
||||
self.assertRaises(frappe.ValidationError, update_child_qty_rate, "Sales Order", trans_item, so.name)
|
||||
|
||||
def test_update_child_qty_rate_with_workflow(self):
|
||||
from frappe.model.workflow import apply_workflow
|
||||
@@ -558,9 +534,7 @@ class TestSalesOrder(FrappeTestCase):
|
||||
trans_item = json.dumps(
|
||||
[{"item_code": "_Test Item", "rate": 150, "qty": 2, "docname": so.items[0].name}]
|
||||
)
|
||||
self.assertRaises(
|
||||
frappe.ValidationError, update_child_qty_rate, "Sales Order", trans_item, so.name
|
||||
)
|
||||
self.assertRaises(frappe.ValidationError, update_child_qty_rate, "Sales Order", trans_item, so.name)
|
||||
|
||||
frappe.set_user("Administrator")
|
||||
user2 = "test2@example.com"
|
||||
@@ -818,9 +792,7 @@ class TestSalesOrder(FrappeTestCase):
|
||||
|
||||
frappe.set_user("Administrator")
|
||||
frappe.permissions.remove_user_permission("Warehouse", "_Test Warehouse 1 - _TC", test_user.name)
|
||||
frappe.permissions.remove_user_permission(
|
||||
"Warehouse", "_Test Warehouse 2 - _TC1", test_user_2.name
|
||||
)
|
||||
frappe.permissions.remove_user_permission("Warehouse", "_Test Warehouse 2 - _TC1", test_user_2.name)
|
||||
frappe.permissions.remove_user_permission("Company", "_Test Company 1", test_user_2.name)
|
||||
|
||||
def test_block_delivery_note_against_cancelled_sales_order(self):
|
||||
@@ -939,9 +911,7 @@ class TestSalesOrder(FrappeTestCase):
|
||||
from erpnext.selling.doctype.sales_order.sales_order import update_status as so_update_status
|
||||
|
||||
# make items
|
||||
po_item = make_item(
|
||||
"_Test Item for Drop Shipping", {"is_stock_item": 1, "delivered_by_supplier": 1}
|
||||
)
|
||||
po_item = make_item("_Test Item for Drop Shipping", {"is_stock_item": 1, "delivered_by_supplier": 1})
|
||||
dn_item = make_item("_Test Regular Item", {"is_stock_item": 1})
|
||||
|
||||
so_items = [
|
||||
@@ -1224,17 +1194,13 @@ class TestSalesOrder(FrappeTestCase):
|
||||
new_so = frappe.copy_doc(so)
|
||||
new_so.save(ignore_permissions=True)
|
||||
|
||||
self.assertEqual(
|
||||
new_so.get("items")[0].rate, flt((price_list_rate * 25) / 100 + price_list_rate)
|
||||
)
|
||||
self.assertEqual(new_so.get("items")[0].rate, flt((price_list_rate * 25) / 100 + price_list_rate))
|
||||
new_so.items[0].margin_rate_or_amount = 25
|
||||
new_so.payment_schedule = []
|
||||
new_so.save()
|
||||
new_so.submit()
|
||||
|
||||
self.assertEqual(
|
||||
new_so.get("items")[0].rate, flt((price_list_rate * 25) / 100 + price_list_rate)
|
||||
)
|
||||
self.assertEqual(new_so.get("items")[0].rate, flt((price_list_rate * 25) / 100 + price_list_rate))
|
||||
|
||||
def test_terms_auto_added(self):
|
||||
so = make_sales_order(do_not_save=1)
|
||||
@@ -1304,9 +1270,7 @@ class TestSalesOrder(FrappeTestCase):
|
||||
def test_advance_payment_entry_unlink_against_sales_order(self):
|
||||
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
|
||||
|
||||
frappe.db.set_single_value(
|
||||
"Accounts Settings", "unlink_advance_payment_on_cancelation_of_order", 0
|
||||
)
|
||||
frappe.db.set_single_value("Accounts Settings", "unlink_advance_payment_on_cancelation_of_order", 0)
|
||||
|
||||
so = make_sales_order()
|
||||
|
||||
@@ -1359,9 +1323,7 @@ class TestSalesOrder(FrappeTestCase):
|
||||
so = make_sales_order()
|
||||
|
||||
# disable unlinking of payment entry
|
||||
frappe.db.set_single_value(
|
||||
"Accounts Settings", "unlink_advance_payment_on_cancelation_of_order", 0
|
||||
)
|
||||
frappe.db.set_single_value("Accounts Settings", "unlink_advance_payment_on_cancelation_of_order", 0)
|
||||
|
||||
# create a payment entry against sales order
|
||||
pe = get_payment_entry("Sales Order", so.name, bank_account="_Test Bank - _TC")
|
||||
@@ -1492,7 +1454,7 @@ class TestSalesOrder(FrappeTestCase):
|
||||
Second Sales Order should not add on to Blanket Orders Ordered Quantity.
|
||||
"""
|
||||
|
||||
bo = make_blanket_order(blanket_order_type="Selling", quantity=10, rate=10)
|
||||
make_blanket_order(blanket_order_type="Selling", quantity=10, rate=10)
|
||||
|
||||
so = make_sales_order(item_code="_Test Item", qty=5, against_blanket_order=1)
|
||||
so_doc = frappe.get_doc("Sales Order", so.get("name"))
|
||||
@@ -1713,7 +1675,10 @@ class TestSalesOrder(FrappeTestCase):
|
||||
|
||||
wo.submit()
|
||||
make_stock_entry(
|
||||
item_code="_Test Item", target="Work In Progress - _TC", qty=4, basic_rate=100 # Stock RM
|
||||
item_code="_Test Item",
|
||||
target="Work In Progress - _TC",
|
||||
qty=4,
|
||||
basic_rate=100, # Stock RM
|
||||
)
|
||||
make_stock_entry(
|
||||
item_code="_Test Item Home Desktop 100", # Stock RM
|
||||
@@ -1821,10 +1786,6 @@ class TestSalesOrder(FrappeTestCase):
|
||||
|
||||
def test_delivered_item_material_request(self):
|
||||
"SO -> MR (Manufacture) -> WO. Test if WO Qty is updated in SO."
|
||||
from erpnext.manufacturing.doctype.work_order.work_order import (
|
||||
make_stock_entry as make_se_from_wo,
|
||||
)
|
||||
from erpnext.stock.doctype.material_request.material_request import raise_work_orders
|
||||
|
||||
so = make_sales_order(
|
||||
item_list=[
|
||||
@@ -1832,9 +1793,7 @@ class TestSalesOrder(FrappeTestCase):
|
||||
]
|
||||
)
|
||||
|
||||
make_stock_entry(
|
||||
item_code="_Test FG Item", target="Work In Progress - _TC", qty=4, basic_rate=100
|
||||
)
|
||||
make_stock_entry(item_code="_Test FG Item", target="Work In Progress - _TC", qty=4, basic_rate=100)
|
||||
|
||||
dn = make_delivery_note(so.name)
|
||||
dn.items[0].qty = 4
|
||||
@@ -1859,7 +1818,8 @@ class TestSalesOrder(FrappeTestCase):
|
||||
if not frappe.db.exists("Item", product_bundle):
|
||||
bundle_item = make_item(product_bundle, {"is_stock_item": 0})
|
||||
bundle_item.append(
|
||||
"item_defaults", {"company": "_Test Company", "default_warehouse": "_Test Warehouse - _TC"}
|
||||
"item_defaults",
|
||||
{"company": "_Test Company", "default_warehouse": "_Test Warehouse - _TC"},
|
||||
)
|
||||
bundle_item.save(ignore_permissions=True)
|
||||
|
||||
@@ -1929,7 +1889,8 @@ class TestSalesOrder(FrappeTestCase):
|
||||
if not frappe.db.exists("Item", product_bundle):
|
||||
bundle_item = make_item(product_bundle, {"is_stock_item": 0})
|
||||
bundle_item.append(
|
||||
"item_defaults", {"company": "_Test Company", "default_warehouse": "_Test Warehouse - _TC"}
|
||||
"item_defaults",
|
||||
{"company": "_Test Company", "default_warehouse": "_Test Warehouse - _TC"},
|
||||
)
|
||||
bundle_item.save(ignore_permissions=True)
|
||||
|
||||
@@ -2202,9 +2163,7 @@ def create_dn_against_so(so, delivered_qty=0, do_not_submit=False):
|
||||
|
||||
|
||||
def get_reserved_qty(item_code="_Test Item", warehouse="_Test Warehouse - _TC"):
|
||||
return flt(
|
||||
frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, "reserved_qty")
|
||||
)
|
||||
return flt(frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse}, "reserved_qty"))
|
||||
|
||||
|
||||
test_dependencies = ["Currency Exchange"]
|
||||
@@ -2217,9 +2176,7 @@ def make_sales_order_workflow():
|
||||
doc.save()
|
||||
return doc
|
||||
|
||||
frappe.get_doc(dict(doctype="Role", role_name="Test Junior Approver")).insert(
|
||||
ignore_if_duplicate=True
|
||||
)
|
||||
frappe.get_doc(dict(doctype="Role", role_name="Test Junior Approver")).insert(ignore_if_duplicate=True)
|
||||
frappe.get_doc(dict(doctype="Role", role_name="Test Approver")).insert(ignore_if_duplicate=True)
|
||||
frappe.cache().hdel("roles", frappe.session.user)
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
|
||||
import json
|
||||
from typing import Dict, Optional
|
||||
|
||||
import frappe
|
||||
from frappe.utils import cint
|
||||
@@ -198,16 +197,14 @@ def get_items(start, page_length, price_list, item_group, pos_profile, search_te
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def search_for_serial_or_batch_or_barcode_number(search_value: str) -> Dict[str, Optional[str]]:
|
||||
def search_for_serial_or_batch_or_barcode_number(search_value: str) -> dict[str, str | None]:
|
||||
return scan_barcode(search_value)
|
||||
|
||||
|
||||
def get_conditions(search_term):
|
||||
condition = "("
|
||||
condition += """item.name like {search_term}
|
||||
or item.item_name like {search_term}""".format(
|
||||
search_term=frappe.db.escape("%" + search_term + "%")
|
||||
)
|
||||
or item.item_name like {search_term}""".format(search_term=frappe.db.escape("%" + search_term + "%"))
|
||||
condition += add_search_fields_condition(search_term)
|
||||
condition += ")"
|
||||
|
||||
@@ -219,7 +216,7 @@ def add_search_fields_condition(search_term):
|
||||
search_fields = frappe.get_all("POS Search Fields", fields=["fieldname"])
|
||||
if search_fields:
|
||||
for field in search_fields:
|
||||
condition += " or item.`{0}` like {1}".format(
|
||||
condition += " or item.`{}` like {}".format(
|
||||
field["fieldname"], frappe.db.escape("%" + search_term + "%")
|
||||
)
|
||||
return condition
|
||||
@@ -249,10 +246,8 @@ def item_group_query(doctype, txt, searchfield, start, page_len, filters):
|
||||
cond = cond % tuple(item_groups)
|
||||
|
||||
return frappe.db.sql(
|
||||
""" select distinct name from `tabItem Group`
|
||||
where {condition} and (name like %(txt)s) limit {page_len} offset {start}""".format(
|
||||
condition=cond, start=start, page_len=page_len
|
||||
),
|
||||
f""" select distinct name from `tabItem Group`
|
||||
where {cond} and (name like %(txt)s) limit {page_len} offset {start}""",
|
||||
{"txt": "%%%s%%" % txt},
|
||||
)
|
||||
|
||||
@@ -297,13 +292,13 @@ def get_past_order_list(search_term, status, limit=20):
|
||||
if search_term and status:
|
||||
invoices_by_customer = frappe.db.get_all(
|
||||
"POS Invoice",
|
||||
filters={"customer": ["like", "%{}%".format(search_term)], "status": status},
|
||||
filters={"customer": ["like", f"%{search_term}%"], "status": status},
|
||||
fields=fields,
|
||||
page_length=limit,
|
||||
)
|
||||
invoices_by_name = frappe.db.get_all(
|
||||
"POS Invoice",
|
||||
filters={"name": ["like", "%{}%".format(search_term)], "status": status},
|
||||
filters={"name": ["like", f"%{search_term}%"], "status": status},
|
||||
fields=fields,
|
||||
page_length=limit,
|
||||
)
|
||||
|
||||
@@ -85,7 +85,7 @@ def get_opp_by_lead_source(from_date, to_date, company):
|
||||
* x["probability"]
|
||||
/ 100
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
for x in opportunities
|
||||
]
|
||||
@@ -137,7 +137,7 @@ def get_pipeline_data(from_date, to_date, company):
|
||||
* x["probability"]
|
||||
/ 100
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
for x in opportunities
|
||||
]
|
||||
|
||||
@@ -27,8 +27,8 @@ def get_columns(filters):
|
||||
party_type = filters.get("party_type")
|
||||
party_type_value = get_party_group(party_type)
|
||||
return [
|
||||
"{party_type}:Link/{party_type}".format(party_type=party_type),
|
||||
"{party_value_type}::150".format(party_value_type=frappe.unscrub(str(party_type_value))),
|
||||
f"{party_type}:Link/{party_type}",
|
||||
f"{frappe.unscrub(str(party_type_value))}::150",
|
||||
"Address Line 1",
|
||||
"Address Line 2",
|
||||
"City",
|
||||
@@ -109,7 +109,7 @@ def get_party_details(party_type, party_list, doctype, party_details):
|
||||
["Dynamic Link", "link_doctype", "=", party_type],
|
||||
["Dynamic Link", "link_name", "in", party_list],
|
||||
]
|
||||
fields = ["`tabDynamic Link`.link_name"] + field_map.get(doctype, [])
|
||||
fields = ["`tabDynamic Link`.link_name", *field_map.get(doctype, [])]
|
||||
|
||||
records = frappe.get_list(doctype, filters=filters, fields=fields, as_list=True)
|
||||
for d in records:
|
||||
|
||||
@@ -77,10 +77,8 @@ def get_data_by_time(filters, common_columns):
|
||||
|
||||
out = []
|
||||
for year in range(from_year, to_year + 1):
|
||||
for month in range(
|
||||
from_month if year == from_year else 1, (to_month + 1) if year == to_year else 13
|
||||
):
|
||||
key = "{year}-{month:02d}".format(year=year, month=month)
|
||||
for month in range(from_month if year == from_year else 1, (to_month + 1) if year == to_year else 13):
|
||||
key = f"{year}-{month:02d}"
|
||||
data = customers_in.get(key)
|
||||
new = data["new"] if data else [0, 0.0]
|
||||
repeat = data["repeat"] if data else [0, 0.0]
|
||||
@@ -147,7 +145,7 @@ def get_data_by_territory(filters, common_columns):
|
||||
|
||||
for ld in loop_data:
|
||||
if ld["parent_territory"]:
|
||||
parent_data = [x for x in data if x["territory"] == ld["parent_territory"]][0]
|
||||
parent_data = next(x for x in data if x["territory"] == ld["parent_territory"])
|
||||
for key in parent_data.keys():
|
||||
if key not in ["indent", "territory", "parent_territory", "bold"]:
|
||||
parent_data[key] += ld[key]
|
||||
@@ -165,15 +163,12 @@ def get_customer_stats(filters, tree_view=False):
|
||||
customers_in = {}
|
||||
|
||||
for si in frappe.db.sql(
|
||||
"""select territory, posting_date, customer, base_grand_total from `tabSales Invoice`
|
||||
f"""select territory, posting_date, customer, base_grand_total from `tabSales Invoice`
|
||||
where docstatus=1 and posting_date <= %(to_date)s
|
||||
{company_condition} order by posting_date""".format(
|
||||
company_condition=company_condition
|
||||
),
|
||||
{company_condition} order by posting_date""",
|
||||
filters,
|
||||
as_dict=1,
|
||||
):
|
||||
|
||||
key = si.territory if tree_view else si.posting_date.strftime("%Y-%m")
|
||||
new_or_repeat = "new" if si.customer not in customers else "repeat"
|
||||
customers_in.setdefault(key, {"new": [0, 0.0], "repeat": [0, 0.0]})
|
||||
|
||||
@@ -77,7 +77,6 @@ def get_columns(customer_naming_type):
|
||||
|
||||
|
||||
def get_details(filters):
|
||||
|
||||
sql_query = """SELECT
|
||||
c.name, c.customer_name,
|
||||
ccl.bypass_credit_limit_check,
|
||||
|
||||
@@ -51,7 +51,10 @@ def get_columns(filters=None):
|
||||
|
||||
|
||||
def fetch_item_prices(
|
||||
customer: str = None, price_list: str = None, selling_price_list: str = None, items: list = None
|
||||
customer: str | None = None,
|
||||
price_list: str | None = None,
|
||||
selling_price_list: str | None = None,
|
||||
items: list | None = None,
|
||||
):
|
||||
price_list_map = frappe._dict()
|
||||
ip = qb.DocType("Item Price")
|
||||
@@ -59,10 +62,10 @@ def fetch_item_prices(
|
||||
or_conditions = []
|
||||
if items:
|
||||
and_conditions.append(ip.item_code.isin([x.item_code for x in items]))
|
||||
and_conditions.append(ip.selling == True)
|
||||
and_conditions.append(ip.selling is True)
|
||||
|
||||
or_conditions.append(ip.customer == None)
|
||||
or_conditions.append(ip.price_list == None)
|
||||
or_conditions.append(ip.customer is None)
|
||||
or_conditions.append(ip.price_list is None)
|
||||
|
||||
if customer:
|
||||
or_conditions.append(ip.customer == customer)
|
||||
|
||||
@@ -40,19 +40,17 @@ def get_sales_details(doctype):
|
||||
DATEDIFF(CURRENT_DATE, max(so.transaction_date)) as 'days_since_last_order'"""
|
||||
|
||||
return frappe.db.sql(
|
||||
"""select
|
||||
f"""select
|
||||
cust.name,
|
||||
cust.customer_name,
|
||||
cust.territory,
|
||||
cust.customer_group,
|
||||
count(distinct(so.name)) as 'num_of_order',
|
||||
sum(base_net_total) as 'total_order_value', {0}
|
||||
from `tabCustomer` cust, `tab{1}` so
|
||||
sum(base_net_total) as 'total_order_value', {cond}
|
||||
from `tabCustomer` cust, `tab{doctype}` so
|
||||
where cust.name = so.customer and so.docstatus = 1
|
||||
group by cust.name
|
||||
order by 'days_since_last_order' desc """.format(
|
||||
cond, doctype
|
||||
),
|
||||
order by 'days_since_last_order' desc """,
|
||||
as_list=1,
|
||||
)
|
||||
|
||||
@@ -62,11 +60,9 @@ def get_last_sales_amt(customer, doctype):
|
||||
if doctype == "Sales Order":
|
||||
cond = "transaction_date"
|
||||
res = frappe.db.sql(
|
||||
"""select base_net_total from `tab{0}`
|
||||
where customer = %s and docstatus = 1 order by {1} desc
|
||||
limit 1""".format(
|
||||
doctype, cond
|
||||
),
|
||||
f"""select base_net_total from `tab{doctype}`
|
||||
where customer = %s and docstatus = 1 order by {cond} desc
|
||||
limit 1""",
|
||||
customer,
|
||||
)
|
||||
|
||||
|
||||
@@ -128,7 +128,6 @@ def get_columns(filters):
|
||||
|
||||
|
||||
def get_data(filters):
|
||||
|
||||
data = []
|
||||
|
||||
company_list = get_descendants_of("Company", filters.get("company"))
|
||||
@@ -181,9 +180,7 @@ def get_item_details():
|
||||
details = frappe.db.get_all("Item", fields=["name", "item_name", "item_group"])
|
||||
item_details = {}
|
||||
for d in details:
|
||||
item_details.setdefault(
|
||||
d.name, frappe._dict({"item_name": d.item_name, "item_group": d.item_group})
|
||||
)
|
||||
item_details.setdefault(d.name, frappe._dict({"item_name": d.item_name, "item_group": d.item_group}))
|
||||
return item_details
|
||||
|
||||
|
||||
@@ -240,14 +237,13 @@ def get_chart_data(data):
|
||||
for row in data:
|
||||
item_key = row.get("item_code")
|
||||
|
||||
if not item_key in item_wise_sales_map:
|
||||
if item_key not in item_wise_sales_map:
|
||||
item_wise_sales_map[item_key] = 0
|
||||
|
||||
item_wise_sales_map[item_key] = flt(item_wise_sales_map[item_key]) + flt(row.get("amount"))
|
||||
|
||||
item_wise_sales_map = {
|
||||
item: value
|
||||
for item, value in (sorted(item_wise_sales_map.items(), key=lambda i: i[1], reverse=True))
|
||||
item: value for item, value in (sorted(item_wise_sales_map.items(), key=lambda i: i[1], reverse=True))
|
||||
}
|
||||
|
||||
for key in item_wise_sales_map:
|
||||
|
||||
@@ -53,9 +53,7 @@ def get_columns(group_by: Literal["Lost Reason", "Competitor"]):
|
||||
]
|
||||
|
||||
|
||||
def get_data(
|
||||
company: str, from_date: str, to_date: str, group_by: Literal["Lost Reason", "Competitor"]
|
||||
):
|
||||
def get_data(company: str, from_date: str, to_date: str, group_by: Literal["Lost Reason", "Competitor"]):
|
||||
"""Return quotation value grouped by lost reason or competitor"""
|
||||
if group_by == "Lost Reason":
|
||||
fieldname = "lost_reason"
|
||||
|
||||
@@ -82,9 +82,7 @@ def get_descendants_of(doctype, group_name):
|
||||
).run()[0]
|
||||
|
||||
# get all children of group node
|
||||
query = (
|
||||
qb.from_(group_doc).select(group_doc.name).where((group_doc.lft >= lft) & (group_doc.rgt <= rgt))
|
||||
)
|
||||
query = qb.from_(group_doc).select(group_doc.name).where((group_doc.lft >= lft) & (group_doc.rgt <= rgt))
|
||||
|
||||
child_nodes = []
|
||||
for x in query.run():
|
||||
@@ -108,7 +106,9 @@ def get_customers_or_items(doctype, txt, searchfield, start, page_len, filters):
|
||||
)
|
||||
elif item[0] == "Item Group":
|
||||
if item[3] != "":
|
||||
filter_list.append([doctype, "item_group", "in", get_descendants_of("Item Group", item[3])])
|
||||
filter_list.append(
|
||||
[doctype, "item_group", "in", get_descendants_of("Item Group", item[3])]
|
||||
)
|
||||
|
||||
if searchfield and txt:
|
||||
filter_list.append([doctype, searchfield, "like", "%%%s%%" % txt])
|
||||
@@ -132,9 +132,7 @@ def get_conditions(filters):
|
||||
|
||||
conditions.company = filters.company or frappe.defaults.get_user_default("company")
|
||||
conditions.end_date = filters.period_end_date or frappe.utils.today()
|
||||
conditions.start_date = filters.period_start_date or frappe.utils.add_months(
|
||||
conditions.end_date, -1
|
||||
)
|
||||
conditions.start_date = filters.period_start_date or frappe.utils.add_months(conditions.end_date, -1)
|
||||
|
||||
return conditions
|
||||
|
||||
|
||||
@@ -81,9 +81,7 @@ def get_data():
|
||||
|
||||
bundled_item_map = get_packed_items(sales_orders)
|
||||
|
||||
item_with_product_bundle = get_items_with_product_bundle(
|
||||
[row.item_code for row in sales_order_entry]
|
||||
)
|
||||
item_with_product_bundle = get_items_with_product_bundle([row.item_code for row in sales_order_entry])
|
||||
|
||||
materials_request_dict = {}
|
||||
|
||||
@@ -129,7 +127,9 @@ def get_data():
|
||||
"description": item.description,
|
||||
"sales_order_no": so.name,
|
||||
"date": so.transaction_date,
|
||||
"material_request": ",".join(material_requests_against_so.get("material_requests", [])),
|
||||
"material_request": ",".join(
|
||||
material_requests_against_so.get("material_requests", [])
|
||||
),
|
||||
"customer": so.customer,
|
||||
"territory": so.territory,
|
||||
"so_qty": item.qty,
|
||||
|
||||
@@ -48,9 +48,7 @@ def get_chart_data(data, conditions, filters):
|
||||
return {
|
||||
"data": {
|
||||
"labels": labels,
|
||||
"datasets": [
|
||||
{"name": _(filters.get("period")) + " " + _("Quoted Amount"), "values": datapoints}
|
||||
],
|
||||
"datasets": [{"name": _(filters.get("period")) + " " + _("Quoted Amount"), "values": datapoints}],
|
||||
},
|
||||
"type": "line",
|
||||
"lineOptions": {"regionFill": 1},
|
||||
|
||||
@@ -13,7 +13,7 @@ def execute(filters=None):
|
||||
return Analytics(filters).run()
|
||||
|
||||
|
||||
class Analytics(object):
|
||||
class Analytics:
|
||||
def __init__(self, filters=None):
|
||||
self.filters = frappe._dict(filters or {})
|
||||
self.date_field = (
|
||||
@@ -87,9 +87,7 @@ class Analytics(object):
|
||||
{"label": _(period), "fieldname": scrub(period), "fieldtype": "Float", "width": 120}
|
||||
)
|
||||
|
||||
self.columns.append(
|
||||
{"label": _("Total"), "fieldname": "total", "fieldtype": "Float", "width": 120}
|
||||
)
|
||||
self.columns.append({"label": _("Total"), "fieldname": "total", "fieldtype": "Float", "width": 120})
|
||||
|
||||
def get_data(self):
|
||||
if self.filters.tree_type in ["Customer", "Supplier"]:
|
||||
@@ -129,9 +127,7 @@ class Analytics(object):
|
||||
""" select s.order_type as entity, s.{value_field} as value_field, s.{date_field}
|
||||
from `tab{doctype}` s where s.docstatus = 1 and s.company = %s and s.{date_field} between %s and %s
|
||||
and ifnull(s.order_type, '') != '' order by s.order_type
|
||||
""".format(
|
||||
date_field=self.date_field, value_field=value_field, doctype=self.filters.doc_type
|
||||
),
|
||||
""".format(date_field=self.date_field, value_field=value_field, doctype=self.filters.doc_type),
|
||||
(self.filters.company, self.filters.from_date, self.filters.to_date),
|
||||
as_dict=1,
|
||||
)
|
||||
@@ -166,7 +162,6 @@ class Analytics(object):
|
||||
self.entity_names.setdefault(d.entity, d.entity_name)
|
||||
|
||||
def get_sales_transactions_based_on_items(self):
|
||||
|
||||
if self.filters["value_quantity"] == "Value":
|
||||
value_field = "base_net_amount"
|
||||
else:
|
||||
@@ -178,9 +173,7 @@ class Analytics(object):
|
||||
from `tab{doctype} Item` i , `tab{doctype}` s
|
||||
where s.name = i.parent and i.docstatus = 1 and s.company = %s
|
||||
and s.{date_field} between %s and %s
|
||||
""".format(
|
||||
date_field=self.date_field, value_field=value_field, doctype=self.filters.doc_type
|
||||
),
|
||||
""".format(date_field=self.date_field, value_field=value_field, doctype=self.filters.doc_type),
|
||||
(self.filters.company, self.filters.from_date, self.filters.to_date),
|
||||
as_dict=1,
|
||||
)
|
||||
@@ -221,14 +214,12 @@ class Analytics(object):
|
||||
value_field = "qty"
|
||||
|
||||
self.entries = frappe.db.sql(
|
||||
"""
|
||||
select i.item_group as entity, i.{value_field} as value_field, s.{date_field}
|
||||
from `tab{doctype} Item` i , `tab{doctype}` s
|
||||
f"""
|
||||
select i.item_group as entity, i.{value_field} as value_field, s.{self.date_field}
|
||||
from `tab{self.filters.doc_type} Item` i , `tab{self.filters.doc_type}` s
|
||||
where s.name = i.parent and i.docstatus = 1 and s.company = %s
|
||||
and s.{date_field} between %s and %s
|
||||
""".format(
|
||||
date_field=self.date_field, value_field=value_field, doctype=self.filters.doc_type
|
||||
),
|
||||
and s.{self.date_field} between %s and %s
|
||||
""",
|
||||
(self.filters.company, self.filters.from_date, self.filters.to_date),
|
||||
as_dict=1,
|
||||
)
|
||||
@@ -294,7 +285,7 @@ class Analytics(object):
|
||||
total += amount
|
||||
|
||||
row["total"] = total
|
||||
out = [row] + out
|
||||
out = [row, *out]
|
||||
|
||||
self.data = out
|
||||
|
||||
@@ -330,9 +321,7 @@ class Analytics(object):
|
||||
|
||||
from_date, to_date = getdate(self.filters.from_date), getdate(self.filters.to_date)
|
||||
|
||||
increment = {"Monthly": 1, "Quarterly": 3, "Half-Yearly": 6, "Yearly": 12}.get(
|
||||
self.filters.range, 1
|
||||
)
|
||||
increment = {"Monthly": 1, "Quarterly": 3, "Half-Yearly": 6, "Yearly": 12}.get(self.filters.range, 1)
|
||||
|
||||
if self.filters.range in ["Monthly", "Quarterly"]:
|
||||
from_date = from_date.replace(day=1)
|
||||
@@ -342,7 +331,7 @@ class Analytics(object):
|
||||
from_date = from_date + relativedelta(from_date, weekday=MO(-1))
|
||||
|
||||
self.periodic_daterange = []
|
||||
for dummy in range(1, 53):
|
||||
for _dummy in range(1, 53):
|
||||
if self.filters.range == "Weekly":
|
||||
period_end_date = add_days(from_date, 6)
|
||||
else:
|
||||
@@ -370,10 +359,8 @@ class Analytics(object):
|
||||
self.depth_map = frappe._dict()
|
||||
|
||||
self.group_entries = frappe.db.sql(
|
||||
"""select name, lft, rgt , {parent} as parent
|
||||
from `tab{tree}` order by lft""".format(
|
||||
tree=self.filters.tree_type, parent=parent
|
||||
),
|
||||
f"""select name, lft, rgt , {parent} as parent
|
||||
from `tab{self.filters.tree_type}` order by lft""",
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
@@ -387,12 +374,10 @@ class Analytics(object):
|
||||
self.depth_map = frappe._dict()
|
||||
|
||||
self.group_entries = frappe.db.sql(
|
||||
""" select * from (select "Order Types" as name, 0 as lft,
|
||||
f""" select * from (select "Order Types" as name, 0 as lft,
|
||||
2 as rgt, '' as parent union select distinct order_type as name, 1 as lft, 1 as rgt, "Order Types" as parent
|
||||
from `tab{doctype}` where ifnull(order_type, '') != '') as b order by lft, name
|
||||
""".format(
|
||||
doctype=self.filters.doc_type
|
||||
),
|
||||
from `tab{self.filters.doc_type}` where ifnull(order_type, '') != '') as b order by lft, name
|
||||
""",
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ def get_conditions(filters):
|
||||
|
||||
def get_data(conditions, filters):
|
||||
data = frappe.db.sql(
|
||||
"""
|
||||
f"""
|
||||
SELECT
|
||||
so.transaction_date as date,
|
||||
soi.delivery_date as delivery_date,
|
||||
@@ -91,9 +91,7 @@ def get_data(conditions, filters):
|
||||
{conditions}
|
||||
GROUP BY soi.name
|
||||
ORDER BY so.transaction_date ASC, soi.item_code ASC
|
||||
""".format(
|
||||
conditions=conditions
|
||||
),
|
||||
""",
|
||||
filters,
|
||||
as_dict=1,
|
||||
)
|
||||
@@ -167,7 +165,7 @@ def prepare_data(data, so_elapsed_time, filters):
|
||||
if filters.get("group_by_so"):
|
||||
so_name = row["sales_order"]
|
||||
|
||||
if not so_name in sales_order_map:
|
||||
if so_name not in sales_order_map:
|
||||
# create an entry
|
||||
row_copy = copy.deepcopy(row)
|
||||
sales_order_map[so_name] = row_copy
|
||||
@@ -176,7 +174,9 @@ def prepare_data(data, so_elapsed_time, filters):
|
||||
so_row = sales_order_map[so_name]
|
||||
so_row["required_date"] = max(getdate(so_row["delivery_date"]), getdate(row["delivery_date"]))
|
||||
so_row["delay"] = (
|
||||
min(so_row["delay"], row["delay"]) if row["delay"] and so_row["delay"] else so_row["delay"]
|
||||
min(so_row["delay"], row["delay"])
|
||||
if row["delay"] and so_row["delay"]
|
||||
else so_row["delay"]
|
||||
)
|
||||
|
||||
# sum numeric columns
|
||||
|
||||
@@ -75,16 +75,14 @@ def get_entries(filters):
|
||||
entries = frappe.db.sql(
|
||||
"""
|
||||
SELECT
|
||||
name, customer, territory, {0} as posting_date, base_net_total as amount,
|
||||
name, customer, territory, {} as posting_date, base_net_total as amount,
|
||||
sales_partner, commission_rate, total_commission
|
||||
FROM
|
||||
`tab{1}`
|
||||
`tab{}`
|
||||
WHERE
|
||||
{2} and docstatus = 1 and sales_partner is not null
|
||||
{} and docstatus = 1 and sales_partner is not null
|
||||
and sales_partner != '' order by name desc, sales_partner
|
||||
""".format(
|
||||
date_field, filters.get("doctype"), conditions
|
||||
),
|
||||
""".format(date_field, filters.get("doctype"), conditions),
|
||||
filters,
|
||||
as_dict=1,
|
||||
)
|
||||
@@ -97,15 +95,15 @@ def get_conditions(filters, date_field):
|
||||
|
||||
for field in ["company", "customer", "territory"]:
|
||||
if filters.get(field):
|
||||
conditions += " and {0} = %({1})s".format(field, field)
|
||||
conditions += f" and {field} = %({field})s"
|
||||
|
||||
if filters.get("sales_partner"):
|
||||
conditions += " and sales_partner = %(sales_partner)s"
|
||||
|
||||
if filters.get("from_date"):
|
||||
conditions += " and {0} >= %(from_date)s".format(date_field)
|
||||
conditions += f" and {date_field} >= %(from_date)s"
|
||||
|
||||
if filters.get("to_date"):
|
||||
conditions += " and {0} <= %(to_date)s".format(date_field)
|
||||
conditions += f" and {date_field} <= %(to_date)s"
|
||||
|
||||
return conditions
|
||||
|
||||
@@ -94,8 +94,8 @@ def get_columns(filters, period_list, partner_doctype):
|
||||
]
|
||||
|
||||
for period in period_list:
|
||||
target_key = "target_{}".format(period.key)
|
||||
variance_key = "variance_{}".format(period.key)
|
||||
target_key = f"target_{period.key}"
|
||||
variance_key = f"variance_{period.key}"
|
||||
|
||||
columns.extend(
|
||||
[
|
||||
@@ -169,9 +169,7 @@ def prepare_data(
|
||||
|
||||
for d in sales_users_data:
|
||||
key = (d.parent, d.item_group)
|
||||
dist_data = get_periodwise_distribution_data(
|
||||
d.distribution_id, period_list, filters.get("period")
|
||||
)
|
||||
dist_data = get_periodwise_distribution_data(d.distribution_id, period_list, filters.get("period"))
|
||||
|
||||
if key not in rows:
|
||||
rows.setdefault(key, {"total_target": 0, "total_achieved": 0, "total_variance": 0})
|
||||
@@ -182,8 +180,8 @@ def prepare_data(
|
||||
if p_key not in details:
|
||||
details[p_key] = 0
|
||||
|
||||
target_key = "target_{}".format(p_key)
|
||||
variance_key = "variance_{}".format(p_key)
|
||||
target_key = f"target_{p_key}"
|
||||
variance_key = f"variance_{p_key}"
|
||||
details[target_key] = (d.get(target_qty_amt_field) * dist_data.get(p_key)) / 100
|
||||
details[variance_key] = 0
|
||||
details["total_target"] += details[target_key]
|
||||
|
||||
@@ -8,6 +8,4 @@ from erpnext.selling.report.sales_partner_target_variance_based_on_item_group.it
|
||||
|
||||
|
||||
def execute(filters=None):
|
||||
data = []
|
||||
|
||||
return get_data_column(filters, "Sales Partner")
|
||||
|
||||
@@ -110,9 +110,7 @@ def get_entries(filters):
|
||||
{cond} and dt.name = dt_item.parent and dt.docstatus = 1
|
||||
and dt.sales_partner is not null and dt.sales_partner != ''
|
||||
order by dt.name desc, dt.sales_partner
|
||||
""".format(
|
||||
date_field=date_field, doctype=filters.get("doctype"), cond=conditions
|
||||
),
|
||||
""".format(date_field=date_field, doctype=filters.get("doctype"), cond=conditions),
|
||||
filters,
|
||||
as_dict=1,
|
||||
)
|
||||
@@ -125,13 +123,13 @@ def get_conditions(filters, date_field):
|
||||
|
||||
for field in ["company", "customer", "territory", "sales_partner"]:
|
||||
if filters.get(field):
|
||||
conditions += " and dt.{0} = %({1})s".format(field, field)
|
||||
conditions += f" and dt.{field} = %({field})s"
|
||||
|
||||
if filters.get("from_date"):
|
||||
conditions += " and dt.{0} >= %(from_date)s".format(date_field)
|
||||
conditions += f" and dt.{date_field} >= %(from_date)s"
|
||||
|
||||
if filters.get("to_date"):
|
||||
conditions += " and dt.{0} <= %(to_date)s".format(date_field)
|
||||
conditions += f" and dt.{date_field} <= %(to_date)s"
|
||||
|
||||
if not filters.get("show_return_entries"):
|
||||
conditions += " and dt_item.qty > 0.0"
|
||||
@@ -142,10 +140,7 @@ def get_conditions(filters, date_field):
|
||||
if filters.get("item_group"):
|
||||
lft, rgt = frappe.get_cached_value("Item Group", filters.get("item_group"), ["lft", "rgt"])
|
||||
|
||||
conditions += """ and dt_item.item_group in (select name from
|
||||
`tabItem Group` where lft >= %s and rgt <= %s)""" % (
|
||||
lft,
|
||||
rgt,
|
||||
)
|
||||
conditions += f""" and dt_item.item_group in (select name from
|
||||
`tabItem Group` where lft >= {lft} and rgt <= {rgt})"""
|
||||
|
||||
return conditions
|
||||
|
||||
@@ -103,16 +103,15 @@ def get_entries(filters):
|
||||
entries = frappe.db.sql(
|
||||
"""
|
||||
select
|
||||
dt.name, dt.customer, dt.territory, dt.%s as posting_date,dt.base_net_total as base_net_amount,
|
||||
dt.name, dt.customer, dt.territory, dt.{} as posting_date,dt.base_net_total as base_net_amount,
|
||||
st.commission_rate,st.sales_person, st.allocated_percentage, st.allocated_amount, st.incentives
|
||||
from
|
||||
`tab%s` dt, `tabSales Team` st
|
||||
`tab{}` dt, `tabSales Team` st
|
||||
where
|
||||
st.parent = dt.name and st.parenttype = %s
|
||||
and dt.docstatus = 1 %s order by dt.name desc,st.sales_person
|
||||
"""
|
||||
% (date_field, filters["doc_type"], "%s", conditions),
|
||||
tuple([filters["doc_type"]] + values),
|
||||
st.parent = dt.name and st.parenttype = {}
|
||||
and dt.docstatus = 1 {} order by dt.name desc,st.sales_person
|
||||
""".format(date_field, filters["doc_type"], "%s", conditions),
|
||||
tuple([filters["doc_type"], *values]),
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
@@ -125,18 +124,18 @@ def get_conditions(filters, date_field):
|
||||
|
||||
for field in ["company", "customer", "territory"]:
|
||||
if filters.get(field):
|
||||
conditions.append("dt.{0}=%s".format(field))
|
||||
conditions.append(f"dt.{field}=%s")
|
||||
values.append(filters[field])
|
||||
|
||||
if filters.get("sales_person"):
|
||||
conditions.append("st.sales_person = '{0}'".format(filters.get("sales_person")))
|
||||
conditions.append("st.sales_person = '{}'".format(filters.get("sales_person")))
|
||||
|
||||
if filters.get("from_date"):
|
||||
conditions.append("dt.{0}>=%s".format(date_field))
|
||||
conditions.append(f"dt.{date_field}>=%s")
|
||||
values.append(filters["from_date"])
|
||||
|
||||
if filters.get("to_date"):
|
||||
conditions.append("dt.{0}<=%s".format(date_field))
|
||||
conditions.append(f"dt.{date_field}<=%s")
|
||||
values.append(filters["to_date"])
|
||||
|
||||
return " and ".join(conditions), values
|
||||
|
||||
@@ -156,27 +156,26 @@ def get_entries(filters):
|
||||
entries = frappe.db.sql(
|
||||
"""
|
||||
SELECT
|
||||
dt.name, dt.customer, dt.territory, dt.%s as posting_date, dt_item.item_code,
|
||||
dt.name, dt.customer, dt.territory, dt.{} as posting_date, dt_item.item_code,
|
||||
st.sales_person, st.allocated_percentage, dt_item.warehouse,
|
||||
CASE
|
||||
WHEN dt.status = "Closed" THEN dt_item.%s * dt_item.conversion_factor
|
||||
WHEN dt.status = "Closed" THEN dt_item.{} * dt_item.conversion_factor
|
||||
ELSE dt_item.stock_qty
|
||||
END as stock_qty,
|
||||
CASE
|
||||
WHEN dt.status = "Closed" THEN (dt_item.base_net_rate * dt_item.%s * dt_item.conversion_factor)
|
||||
WHEN dt.status = "Closed" THEN (dt_item.base_net_rate * dt_item.{} * dt_item.conversion_factor)
|
||||
ELSE dt_item.base_net_amount
|
||||
END as base_net_amount,
|
||||
CASE
|
||||
WHEN dt.status = "Closed" THEN ((dt_item.base_net_rate * dt_item.%s * dt_item.conversion_factor) * st.allocated_percentage/100)
|
||||
WHEN dt.status = "Closed" THEN ((dt_item.base_net_rate * dt_item.{} * dt_item.conversion_factor) * st.allocated_percentage/100)
|
||||
ELSE dt_item.base_net_amount * st.allocated_percentage/100
|
||||
END as contribution_amt
|
||||
FROM
|
||||
`tab%s` dt, `tab%s Item` dt_item, `tabSales Team` st
|
||||
`tab{}` dt, `tab{} Item` dt_item, `tabSales Team` st
|
||||
WHERE
|
||||
st.parent = dt.name and dt.name = dt_item.parent and st.parenttype = %s
|
||||
and dt.docstatus = 1 %s order by st.sales_person, dt.name desc
|
||||
"""
|
||||
% (
|
||||
st.parent = dt.name and dt.name = dt_item.parent and st.parenttype = {}
|
||||
and dt.docstatus = 1 {} order by st.sales_person, dt.name desc
|
||||
""".format(
|
||||
date_field,
|
||||
qty_field,
|
||||
qty_field,
|
||||
@@ -186,7 +185,7 @@ def get_entries(filters):
|
||||
"%s",
|
||||
conditions,
|
||||
),
|
||||
tuple([filters["doc_type"]] + values),
|
||||
tuple([filters["doc_type"], *values]),
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
@@ -199,23 +198,21 @@ def get_conditions(filters, date_field):
|
||||
|
||||
for field in ["company", "customer", "territory"]:
|
||||
if filters.get(field):
|
||||
conditions.append("dt.{0}=%s".format(field))
|
||||
conditions.append(f"dt.{field}=%s")
|
||||
values.append(filters[field])
|
||||
|
||||
if filters.get("sales_person"):
|
||||
lft, rgt = frappe.get_value("Sales Person", filters.get("sales_person"), ["lft", "rgt"])
|
||||
conditions.append(
|
||||
"exists(select name from `tabSales Person` where lft >= {0} and rgt <= {1} and name=st.sales_person)".format(
|
||||
lft, rgt
|
||||
)
|
||||
f"exists(select name from `tabSales Person` where lft >= {lft} and rgt <= {rgt} and name=st.sales_person)"
|
||||
)
|
||||
|
||||
if filters.get("from_date"):
|
||||
conditions.append("dt.{0}>=%s".format(date_field))
|
||||
conditions.append(f"dt.{date_field}>=%s")
|
||||
values.append(filters["from_date"])
|
||||
|
||||
if filters.get("to_date"):
|
||||
conditions.append("dt.{0}<=%s".format(date_field))
|
||||
conditions.append(f"dt.{date_field}<=%s")
|
||||
values.append(filters["to_date"])
|
||||
|
||||
items = get_items(filters)
|
||||
|
||||
@@ -8,6 +8,4 @@ from erpnext.selling.report.sales_partner_target_variance_based_on_item_group.it
|
||||
|
||||
|
||||
def execute(filters=None):
|
||||
data = []
|
||||
|
||||
return get_data_column(filters, "Territory")
|
||||
|
||||
@@ -107,7 +107,7 @@ def get_opportunities(filters):
|
||||
conditions = ""
|
||||
|
||||
if filters.get("transaction_date"):
|
||||
conditions = " WHERE transaction_date between {0} and {1}".format(
|
||||
conditions = " WHERE transaction_date between {} and {}".format(
|
||||
frappe.db.escape(filters["transaction_date"][0]),
|
||||
frappe.db.escape(filters["transaction_date"][1]),
|
||||
)
|
||||
@@ -120,12 +120,10 @@ def get_opportunities(filters):
|
||||
conditions += " company = %(company)s"
|
||||
|
||||
return frappe.db.sql(
|
||||
"""
|
||||
f"""
|
||||
SELECT name, territory, opportunity_amount
|
||||
FROM `tabOpportunity` {0}
|
||||
""".format(
|
||||
conditions
|
||||
),
|
||||
FROM `tabOpportunity` {conditions}
|
||||
""",
|
||||
filters,
|
||||
as_dict=1,
|
||||
) # nosec
|
||||
@@ -141,10 +139,8 @@ def get_quotations(opportunities):
|
||||
"""
|
||||
SELECT `name`,`base_grand_total`, `opportunity`
|
||||
FROM `tabQuotation`
|
||||
WHERE docstatus=1 AND opportunity in ({0})
|
||||
""".format(
|
||||
", ".join(["%s"] * len(opportunity_names))
|
||||
),
|
||||
WHERE docstatus=1 AND opportunity in ({})
|
||||
""".format(", ".join(["%s"] * len(opportunity_names))),
|
||||
tuple(opportunity_names),
|
||||
as_dict=1,
|
||||
) # nosec
|
||||
@@ -160,10 +156,8 @@ def get_sales_orders(quotations):
|
||||
"""
|
||||
SELECT so.`name`, so.`base_grand_total`, soi.prevdoc_docname as quotation
|
||||
FROM `tabSales Order` so, `tabSales Order Item` soi
|
||||
WHERE so.docstatus=1 AND so.name = soi.parent AND soi.prevdoc_docname in ({0})
|
||||
""".format(
|
||||
", ".join(["%s"] * len(quotation_names))
|
||||
),
|
||||
WHERE so.docstatus=1 AND so.name = soi.parent AND soi.prevdoc_docname in ({})
|
||||
""".format(", ".join(["%s"] * len(quotation_names))),
|
||||
tuple(quotation_names),
|
||||
as_dict=1,
|
||||
) # nosec
|
||||
@@ -179,10 +173,8 @@ def get_sales_invoice(sales_orders):
|
||||
"""
|
||||
SELECT si.name, si.base_grand_total, sii.sales_order
|
||||
FROM `tabSales Invoice` si, `tabSales Invoice Item` sii
|
||||
WHERE si.docstatus=1 AND si.name = sii.parent AND sii.sales_order in ({0})
|
||||
""".format(
|
||||
", ".join(["%s"] * len(so_names))
|
||||
),
|
||||
WHERE si.docstatus=1 AND si.name = sii.parent AND sii.sales_order in ({})
|
||||
""".format(", ".join(["%s"] * len(so_names))),
|
||||
tuple(so_names),
|
||||
as_dict=1,
|
||||
) # nosec
|
||||
|
||||
Reference in New Issue
Block a user