Merge branch 'frappe:develop' into Custom_Abbr_On_Setup
This commit is contained in:
commit
f333d2724a
@ -6,6 +6,7 @@ from collections import defaultdict
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
|
from frappe.query_builder import Criterion
|
||||||
from frappe.utils import flt, getdate
|
from frappe.utils import flt, getdate
|
||||||
|
|
||||||
import erpnext
|
import erpnext
|
||||||
@ -359,6 +360,7 @@ def get_data(
|
|||||||
accounts_by_name,
|
accounts_by_name,
|
||||||
accounts,
|
accounts,
|
||||||
ignore_closing_entries=False,
|
ignore_closing_entries=False,
|
||||||
|
root_type=root_type,
|
||||||
)
|
)
|
||||||
|
|
||||||
calculate_values(accounts_by_name, gl_entries_by_account, companies, filters, fiscal_year)
|
calculate_values(accounts_by_name, gl_entries_by_account, companies, filters, fiscal_year)
|
||||||
@ -603,6 +605,7 @@ def set_gl_entries_by_account(
|
|||||||
accounts_by_name,
|
accounts_by_name,
|
||||||
accounts,
|
accounts,
|
||||||
ignore_closing_entries=False,
|
ignore_closing_entries=False,
|
||||||
|
root_type=None,
|
||||||
):
|
):
|
||||||
"""Returns a dict like { "account": [gl entries], ... }"""
|
"""Returns a dict like { "account": [gl entries], ... }"""
|
||||||
|
|
||||||
@ -610,7 +613,6 @@ def set_gl_entries_by_account(
|
|||||||
"Company", filters.get("company"), ["lft", "rgt"]
|
"Company", filters.get("company"), ["lft", "rgt"]
|
||||||
)
|
)
|
||||||
|
|
||||||
additional_conditions = get_additional_conditions(from_date, ignore_closing_entries, filters)
|
|
||||||
companies = frappe.db.sql(
|
companies = frappe.db.sql(
|
||||||
""" select name, default_currency from `tabCompany`
|
""" select name, default_currency from `tabCompany`
|
||||||
where lft >= %(company_lft)s and rgt <= %(company_rgt)s""",
|
where lft >= %(company_lft)s and rgt <= %(company_rgt)s""",
|
||||||
@ -626,26 +628,41 @@ def set_gl_entries_by_account(
|
|||||||
)
|
)
|
||||||
|
|
||||||
for d in companies:
|
for d in companies:
|
||||||
gl_entries = frappe.db.sql(
|
gle = frappe.qb.DocType("GL Entry")
|
||||||
"""select gl.posting_date, gl.account, gl.debit, gl.credit, gl.is_opening, gl.company,
|
account = frappe.qb.DocType("Account")
|
||||||
gl.fiscal_year, gl.debit_in_account_currency, gl.credit_in_account_currency, gl.account_currency,
|
query = (
|
||||||
acc.account_name, acc.account_number
|
frappe.qb.from_(gle)
|
||||||
from `tabGL Entry` gl, `tabAccount` acc where acc.name = gl.account and gl.company = %(company)s and gl.is_cancelled = 0
|
.inner_join(account)
|
||||||
{additional_conditions} and gl.posting_date <= %(to_date)s and acc.lft >= %(lft)s and acc.rgt <= %(rgt)s
|
.on(account.name == gle.account)
|
||||||
order by gl.account, gl.posting_date""".format(
|
.select(
|
||||||
additional_conditions=additional_conditions
|
gle.posting_date,
|
||||||
),
|
gle.account,
|
||||||
{
|
gle.debit,
|
||||||
"from_date": from_date,
|
gle.credit,
|
||||||
"to_date": to_date,
|
gle.is_opening,
|
||||||
"lft": root_lft,
|
gle.company,
|
||||||
"rgt": root_rgt,
|
gle.fiscal_year,
|
||||||
"company": d.name,
|
gle.debit_in_account_currency,
|
||||||
"finance_book": filters.get("finance_book"),
|
gle.credit_in_account_currency,
|
||||||
"company_fb": frappe.get_cached_value("Company", d.name, "default_finance_book"),
|
gle.account_currency,
|
||||||
},
|
account.account_name,
|
||||||
as_dict=True,
|
account.account_number,
|
||||||
)
|
)
|
||||||
|
.where(
|
||||||
|
(gle.company == d.name)
|
||||||
|
& (gle.is_cancelled == 0)
|
||||||
|
& (gle.posting_date <= to_date)
|
||||||
|
& (account.lft >= root_lft)
|
||||||
|
& (account.rgt <= root_rgt)
|
||||||
|
& (account.root_type <= root_type)
|
||||||
|
)
|
||||||
|
.orderby(gle.account, gle.posting_date)
|
||||||
|
)
|
||||||
|
|
||||||
|
additional_conditions = get_additional_conditions(from_date, ignore_closing_entries, filters, d)
|
||||||
|
if additional_conditions:
|
||||||
|
query = query.where(Criterion.all(additional_conditions))
|
||||||
|
gl_entries = query.run(as_dict=True)
|
||||||
|
|
||||||
if filters and filters.get("presentation_currency") != d.default_currency:
|
if filters and filters.get("presentation_currency") != d.default_currency:
|
||||||
currency_info["company"] = d.name
|
currency_info["company"] = d.name
|
||||||
@ -716,23 +733,25 @@ def validate_entries(key, entry, accounts_by_name, accounts):
|
|||||||
accounts.insert(idx + 1, args)
|
accounts.insert(idx + 1, args)
|
||||||
|
|
||||||
|
|
||||||
def get_additional_conditions(from_date, ignore_closing_entries, filters):
|
def get_additional_conditions(from_date, ignore_closing_entries, filters, d):
|
||||||
|
gle = frappe.qb.DocType("GL Entry")
|
||||||
additional_conditions = []
|
additional_conditions = []
|
||||||
|
|
||||||
if ignore_closing_entries:
|
if ignore_closing_entries:
|
||||||
additional_conditions.append("gl.voucher_type != 'Period Closing Voucher'")
|
additional_conditions.append((gle.voucher_type != "Period Closing Voucher"))
|
||||||
|
|
||||||
if from_date:
|
if from_date:
|
||||||
additional_conditions.append("gl.posting_date >= %(from_date)s")
|
additional_conditions.append(gle.posting_date >= from_date)
|
||||||
|
|
||||||
|
finance_book = filters.get("finance_book")
|
||||||
|
company_fb = frappe.get_cached_value("Company", d.name, "default_finance_book")
|
||||||
|
|
||||||
if filters.get("include_default_book_entries"):
|
if filters.get("include_default_book_entries"):
|
||||||
additional_conditions.append(
|
additional_conditions.append((gle.finance_book.isin([finance_book, company_fb, "", None])))
|
||||||
"(finance_book in (%(finance_book)s, %(company_fb)s, '') OR finance_book IS NULL)"
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
additional_conditions.append("(finance_book in (%(finance_book)s, '') OR finance_book IS NULL)")
|
additional_conditions.append((gle.finance_book.isin([finance_book, "", None])))
|
||||||
|
|
||||||
return " and {}".format(" and ".join(additional_conditions)) if additional_conditions else ""
|
return additional_conditions
|
||||||
|
|
||||||
|
|
||||||
def add_total_row(out, root_type, balance_must_be, companies, company_currency):
|
def add_total_row(out, root_type, balance_must_be, companies, company_currency):
|
||||||
|
@ -188,6 +188,7 @@ def get_data(
|
|||||||
filters,
|
filters,
|
||||||
gl_entries_by_account,
|
gl_entries_by_account,
|
||||||
ignore_closing_entries=ignore_closing_entries,
|
ignore_closing_entries=ignore_closing_entries,
|
||||||
|
root_type=root_type,
|
||||||
)
|
)
|
||||||
|
|
||||||
calculate_values(
|
calculate_values(
|
||||||
@ -417,13 +418,28 @@ def set_gl_entries_by_account(
|
|||||||
gl_entries_by_account,
|
gl_entries_by_account,
|
||||||
ignore_closing_entries=False,
|
ignore_closing_entries=False,
|
||||||
ignore_opening_entries=False,
|
ignore_opening_entries=False,
|
||||||
|
root_type=None,
|
||||||
):
|
):
|
||||||
"""Returns a dict like { "account": [gl entries], ... }"""
|
"""Returns a dict like { "account": [gl entries], ... }"""
|
||||||
gl_entries = []
|
gl_entries = []
|
||||||
|
|
||||||
|
account_filters = {
|
||||||
|
"company": company,
|
||||||
|
"is_group": 0,
|
||||||
|
"lft": (">=", root_lft),
|
||||||
|
"rgt": ("<=", root_rgt),
|
||||||
|
}
|
||||||
|
|
||||||
|
if root_type:
|
||||||
|
account_filters.update(
|
||||||
|
{
|
||||||
|
"root_type": root_type,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
accounts_list = frappe.db.get_all(
|
accounts_list = frappe.db.get_all(
|
||||||
"Account",
|
"Account",
|
||||||
filters={"company": company, "is_group": 0, "lft": (">=", root_lft), "rgt": ("<=", root_rgt)},
|
filters=account_filters,
|
||||||
pluck="name",
|
pluck="name",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ def get_data(filters):
|
|||||||
.select(
|
.select(
|
||||||
gle.voucher_type, gle.voucher_no, Sum(gle.debit).as_("debit"), Sum(gle.credit).as_("credit")
|
gle.voucher_type, gle.voucher_no, Sum(gle.debit).as_("debit"), Sum(gle.credit).as_("credit")
|
||||||
)
|
)
|
||||||
|
.where(gle.is_cancelled == 0)
|
||||||
.groupby(gle.voucher_no)
|
.groupby(gle.voucher_no)
|
||||||
)
|
)
|
||||||
query = apply_filters(query, filters, gle)
|
query = apply_filters(query, filters, gle)
|
||||||
|
@ -114,7 +114,7 @@ class Workstation(Document):
|
|||||||
|
|
||||||
if schedule_date in tuple(get_holidays(self.holiday_list)):
|
if schedule_date in tuple(get_holidays(self.holiday_list)):
|
||||||
schedule_date = add_days(schedule_date, 1)
|
schedule_date = add_days(schedule_date, 1)
|
||||||
self.validate_workstation_holiday(schedule_date, skip_holiday_list_check=True)
|
return self.validate_workstation_holiday(schedule_date, skip_holiday_list_check=True)
|
||||||
|
|
||||||
return schedule_date
|
return schedule_date
|
||||||
|
|
||||||
|
@ -62,10 +62,10 @@
|
|||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fetch_from": "process_owner.full_name",
|
"fetch_from": "procedure.process_owner_full_name",
|
||||||
"fieldname": "full_name",
|
"fieldname": "full_name",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"hidden": 1,
|
"read_only": 1,
|
||||||
"label": "Full Name"
|
"label": "Full Name"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -81,7 +81,7 @@
|
|||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-02-26 15:27:47.247814",
|
"modified": "2023-07-31 08:10:47.247814",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Quality Management",
|
"module": "Quality Management",
|
||||||
"name": "Non Conformance",
|
"name": "Non Conformance",
|
||||||
|
@ -56,6 +56,7 @@
|
|||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"default": "Open",
|
||||||
"columns": 2,
|
"columns": 2,
|
||||||
"fieldname": "status",
|
"fieldname": "status",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
@ -67,7 +68,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2020-10-27 16:28:20.908637",
|
"modified": "2023-07-31 09:20:20.908637",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Quality Management",
|
"module": "Quality Management",
|
||||||
"name": "Quality Review Objective",
|
"name": "Quality Review Objective",
|
||||||
|
@ -733,7 +733,7 @@ def make_material_request(source_name, target_doc=None):
|
|||||||
# qty is for packed items, because packed items don't have stock_qty field
|
# qty is for packed items, because packed items don't have stock_qty field
|
||||||
qty = source.get("qty")
|
qty = source.get("qty")
|
||||||
target.project = source_parent.project
|
target.project = source_parent.project
|
||||||
target.qty = qty - requested_item_qty.get(source.name, 0) - source.delivered_qty
|
target.qty = qty - requested_item_qty.get(source.name, 0) - flt(source.get("delivered_qty"))
|
||||||
target.stock_qty = flt(target.qty) * flt(target.conversion_factor)
|
target.stock_qty = flt(target.qty) * flt(target.conversion_factor)
|
||||||
|
|
||||||
args = target.as_dict().copy()
|
args = target.as_dict().copy()
|
||||||
@ -767,7 +767,7 @@ def make_material_request(source_name, target_doc=None):
|
|||||||
"doctype": "Material Request Item",
|
"doctype": "Material Request Item",
|
||||||
"field_map": {"name": "sales_order_item", "parent": "sales_order"},
|
"field_map": {"name": "sales_order_item", "parent": "sales_order"},
|
||||||
"condition": lambda doc: not frappe.db.exists("Product Bundle", doc.item_code)
|
"condition": lambda doc: not frappe.db.exists("Product Bundle", doc.item_code)
|
||||||
and (doc.stock_qty - doc.delivered_qty) > requested_item_qty.get(doc.name, 0),
|
and (doc.stock_qty - flt(doc.get("delivered_qty"))) > requested_item_qty.get(doc.name, 0),
|
||||||
"postprocess": update_item,
|
"postprocess": update_item,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -549,6 +549,26 @@ class TestSalesOrder(FrappeTestCase):
|
|||||||
workflow.is_active = 0
|
workflow.is_active = 0
|
||||||
workflow.save()
|
workflow.save()
|
||||||
|
|
||||||
|
def test_material_request_for_product_bundle(self):
|
||||||
|
# Create the Material Request from the sales order for the Packing Items
|
||||||
|
# Check whether the material request has the correct packing item or not.
|
||||||
|
if not frappe.db.exists("Item", "_Test Product Bundle Item New 1"):
|
||||||
|
bundle_item = make_item("_Test Product Bundle Item New 1", {"is_stock_item": 0})
|
||||||
|
bundle_item.append(
|
||||||
|
"item_defaults", {"company": "_Test Company", "default_warehouse": "_Test Warehouse - _TC"}
|
||||||
|
)
|
||||||
|
bundle_item.save(ignore_permissions=True)
|
||||||
|
|
||||||
|
make_item("_Packed Item New 2", {"is_stock_item": 1})
|
||||||
|
make_product_bundle("_Test Product Bundle Item New 1", ["_Packed Item New 2"], 2)
|
||||||
|
|
||||||
|
so = make_sales_order(
|
||||||
|
item_code="_Test Product Bundle Item New 1",
|
||||||
|
)
|
||||||
|
|
||||||
|
mr = make_material_request(so.name)
|
||||||
|
self.assertEqual(mr.items[0].item_code, "_Packed Item New 2")
|
||||||
|
|
||||||
def test_bin_details_of_packed_item(self):
|
def test_bin_details_of_packed_item(self):
|
||||||
# test Update Items with product bundle
|
# test Update Items with product bundle
|
||||||
if not frappe.db.exists("Item", "_Test Product Bundle Item New"):
|
if not frappe.db.exists("Item", "_Test Product Bundle Item New"):
|
||||||
|
@ -395,16 +395,16 @@ class Item(Document):
|
|||||||
|
|
||||||
def validate_warehouse_for_reorder(self):
|
def validate_warehouse_for_reorder(self):
|
||||||
"""Validate Reorder level table for duplicate and conditional mandatory"""
|
"""Validate Reorder level table for duplicate and conditional mandatory"""
|
||||||
warehouse = []
|
warehouse_material_request_type: list[tuple[str, str]] = []
|
||||||
for d in self.get("reorder_levels"):
|
for d in self.get("reorder_levels"):
|
||||||
if not d.warehouse_group:
|
if not d.warehouse_group:
|
||||||
d.warehouse_group = d.warehouse
|
d.warehouse_group = d.warehouse
|
||||||
if d.get("warehouse") and d.get("warehouse") not in warehouse:
|
if (d.get("warehouse"), d.get("material_request_type")) not in warehouse_material_request_type:
|
||||||
warehouse += [d.get("warehouse")]
|
warehouse_material_request_type += [(d.get("warehouse"), d.get("material_request_type"))]
|
||||||
else:
|
else:
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("Row {0}: An Reorder entry already exists for this warehouse {1}").format(
|
_("Row #{0}: A reorder entry already exists for warehouse {1} with reorder type {2}.").format(
|
||||||
d.idx, d.warehouse
|
d.idx, d.warehouse, d.material_request_type
|
||||||
),
|
),
|
||||||
DuplicateReorderRows,
|
DuplicateReorderRows,
|
||||||
)
|
)
|
||||||
|
@ -17,7 +17,7 @@ def execute(filters=None):
|
|||||||
if not filters:
|
if not filters:
|
||||||
filters = {}
|
filters = {}
|
||||||
|
|
||||||
sle_count = frappe.db.count("Stock Ledger Entry", {"is_cancelled": 0})
|
sle_count = frappe.db.count("Stock Ledger Entry")
|
||||||
|
|
||||||
if sle_count > SLE_COUNT_LIMIT and not filters.get("item_code") and not filters.get("warehouse"):
|
if sle_count > SLE_COUNT_LIMIT and not filters.get("item_code") and not filters.get("warehouse"):
|
||||||
frappe.throw(_("Please select either the Item or Warehouse filter to generate the report."))
|
frappe.throw(_("Please select either the Item or Warehouse filter to generate the report."))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user