Merge branch 'develop' into early-payment-loss

This commit is contained in:
Marica 2023-03-03 13:53:57 +05:30 committed by GitHub
commit 619824855a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 124 additions and 136 deletions

View File

@ -137,7 +137,8 @@
"fieldname": "finance_book", "fieldname": "finance_book",
"fieldtype": "Link", "fieldtype": "Link",
"label": "Finance Book", "label": "Finance Book",
"options": "Finance Book" "options": "Finance Book",
"read_only": 1
}, },
{ {
"fieldname": "2_add_edit_gl_entries", "fieldname": "2_add_edit_gl_entries",
@ -538,7 +539,7 @@
"idx": 176, "idx": 176,
"is_submittable": 1, "is_submittable": 1,
"links": [], "links": [],
"modified": "2023-01-17 12:53:53.280620", "modified": "2023-03-01 14:58:59.286591",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Journal Entry", "name": "Journal Entry",

View File

@ -8,6 +8,7 @@ import frappe
from frappe import _, throw from frappe import _, throw
from frappe.model import child_table_fields, default_fields from frappe.model import child_table_fields, default_fields
from frappe.model.meta import get_field_precision from frappe.model.meta import get_field_precision
from frappe.query_builder.functions import CombineDatetime, IfNull, Sum
from frappe.utils import add_days, add_months, cint, cstr, flt, getdate from frappe.utils import add_days, add_months, cint, cstr, flt, getdate
from erpnext import get_company_currency from erpnext import get_company_currency
@ -526,12 +527,8 @@ def get_barcode_data(items_list):
itemwise_barcode = {} itemwise_barcode = {}
for item in items_list: for item in items_list:
barcodes = frappe.db.sql( barcodes = frappe.db.get_all(
""" "Item Barcode", filters={"parent": item.item_code}, fields="barcode"
select barcode from `tabItem Barcode` where parent = %s
""",
item.item_code,
as_dict=1,
) )
for barcode in barcodes: for barcode in barcodes:
@ -891,35 +888,37 @@ def get_item_price(args, item_code, ignore_party=False):
:param item_code: str, Item Doctype field item_code :param item_code: str, Item Doctype field item_code
""" """
args["item_code"] = item_code ip = frappe.qb.DocType("Item Price")
query = (
conditions = """where item_code=%(item_code)s frappe.qb.from_(ip)
and price_list=%(price_list)s .select(ip.name, ip.price_list_rate, ip.uom)
and ifnull(uom, '') in ('', %(uom)s)""" .where(
(ip.item_code == item_code)
conditions += "and ifnull(batch_no, '') in ('', %(batch_no)s)" & (ip.price_list == args.get("price_list"))
& (IfNull(ip.uom, "").isin(["", args.get("uom")]))
& (IfNull(ip.batch_no, "").isin(["", args.get("batch_no")]))
)
.orderby(ip.valid_from, order=frappe.qb.desc)
.orderby(IfNull(ip.batch_no, ""), order=frappe.qb.desc)
.orderby(ip.uom, order=frappe.qb.desc)
)
if not ignore_party: if not ignore_party:
if args.get("customer"): if args.get("customer"):
conditions += " and customer=%(customer)s" query = query.where(ip.customer == args.get("customer"))
elif args.get("supplier"): elif args.get("supplier"):
conditions += " and supplier=%(supplier)s" query = query.where(ip.supplier == args.get("supplier"))
else: else:
conditions += "and (customer is null or customer = '') and (supplier is null or supplier = '')" query = query.where((IfNull(ip.customer, "") == "") & (IfNull(ip.supplier, "") == ""))
if args.get("transaction_date"): if args.get("transaction_date"):
conditions += """ and %(transaction_date)s between query = query.where(
ifnull(valid_from, '2000-01-01') and ifnull(valid_upto, '2500-12-31')""" (IfNull(ip.valid_from, "2000-01-01") <= args["transaction_date"])
& (IfNull(ip.valid_upto, "2500-12-31") >= args["transaction_date"])
return frappe.db.sql(
""" select name, price_list_rate, uom
from `tabItem Price` {conditions}
order by valid_from desc, ifnull(batch_no, '') desc, uom desc """.format(
conditions=conditions
),
args,
) )
return query.run()
def get_price_list_rate_for(args, item_code): def get_price_list_rate_for(args, item_code):
""" """
@ -1091,91 +1090,68 @@ def get_pos_profile(company, pos_profile=None, user=None):
if not user: if not user:
user = frappe.session["user"] user = frappe.session["user"]
condition = "pfu.user = %(user)s AND pfu.default=1" pf = frappe.qb.DocType("POS Profile")
if user and company: pfu = frappe.qb.DocType("POS Profile User")
condition = "pfu.user = %(user)s AND pf.company = %(company)s AND pfu.default=1"
pos_profile = frappe.db.sql( query = (
"""SELECT pf.* frappe.qb.from_(pf)
FROM .left_join(pfu)
`tabPOS Profile` pf LEFT JOIN `tabPOS Profile User` pfu .on(pf.name == pfu.parent)
ON .select(pf.star)
pf.name = pfu.parent .where((pfu.user == user) & (pfu.default == 1))
WHERE
{cond} AND pf.disabled = 0
""".format(
cond=condition
),
{"user": user, "company": company},
as_dict=1,
) )
if company:
query = query.where(pf.company == company)
pos_profile = query.run(as_dict=True)
if not pos_profile and company: if not pos_profile and company:
pos_profile = frappe.db.sql( pos_profile = (
"""SELECT pf.* frappe.qb.from_(pf)
FROM .left_join(pfu)
`tabPOS Profile` pf LEFT JOIN `tabPOS Profile User` pfu .on(pf.name == pfu.parent)
ON .select(pf.star)
pf.name = pfu.parent .where((pf.company == company) & (pf.disabled == 0))
WHERE ).run(as_dict=True)
pf.company = %(company)s AND pf.disabled = 0
""",
{"company": company},
as_dict=1,
)
return pos_profile and pos_profile[0] or None return pos_profile and pos_profile[0] or None
def get_serial_nos_by_fifo(args, sales_order=None): def get_serial_nos_by_fifo(args, sales_order=None):
if frappe.db.get_single_value("Stock Settings", "automatically_set_serial_nos_based_on_fifo"): if frappe.db.get_single_value("Stock Settings", "automatically_set_serial_nos_based_on_fifo"):
return "\n".join( sn = frappe.qb.DocType("Serial No")
frappe.db.sql_list( query = (
"""select name from `tabSerial No` frappe.qb.from_(sn)
where item_code=%(item_code)s and warehouse=%(warehouse)s and .select(sn.name)
sales_order=IF(%(sales_order)s IS NULL, sales_order, %(sales_order)s) .where((sn.item_code == args.item_code) & (sn.warehouse == args.warehouse))
order by timestamp(purchase_date, purchase_time) .orderby(CombineDatetime(sn.purchase_date, sn.purchase_time))
asc limit %(qty)s""", .limit(abs(cint(args.stock_qty)))
{
"item_code": args.item_code,
"warehouse": args.warehouse,
"qty": abs(cint(args.stock_qty)),
"sales_order": sales_order,
},
)
) )
if sales_order:
query = query.where(sn.sales_order == sales_order)
if args.batch_no:
query = query.where(sn.batch_no == args.batch_no)
def get_serial_no_batchwise(args, sales_order=None): serial_nos = query.run(as_list=True)
if frappe.db.get_single_value("Stock Settings", "automatically_set_serial_nos_based_on_fifo"): serial_nos = [s[0] for s in serial_nos]
return "\n".join(
frappe.db.sql_list( return "\n".join(serial_nos)
"""select name from `tabSerial No`
where item_code=%(item_code)s and warehouse=%(warehouse)s and
sales_order=IF(%(sales_order)s IS NULL, sales_order, %(sales_order)s)
and batch_no=IF(%(batch_no)s IS NULL, batch_no, %(batch_no)s) order
by timestamp(purchase_date, purchase_time) asc limit %(qty)s""",
{
"item_code": args.item_code,
"warehouse": args.warehouse,
"batch_no": args.batch_no,
"qty": abs(cint(args.stock_qty)),
"sales_order": sales_order,
},
)
)
@frappe.whitelist() @frappe.whitelist()
def get_conversion_factor(item_code, uom): def get_conversion_factor(item_code, uom):
variant_of = frappe.db.get_value("Item", item_code, "variant_of", cache=True) variant_of = frappe.db.get_value("Item", item_code, "variant_of", cache=True)
filters = {"parent": item_code, "uom": uom} filters = {"parent": item_code, "uom": uom}
if variant_of: if variant_of:
filters["parent"] = ("in", (item_code, variant_of)) filters["parent"] = ("in", (item_code, variant_of))
conversion_factor = frappe.db.get_value("UOM Conversion Detail", filters, "conversion_factor") conversion_factor = frappe.db.get_value("UOM Conversion Detail", filters, "conversion_factor")
if not conversion_factor: if not conversion_factor:
stock_uom = frappe.db.get_value("Item", item_code, "stock_uom") stock_uom = frappe.db.get_value("Item", item_code, "stock_uom")
conversion_factor = get_uom_conv_factor(uom, stock_uom) conversion_factor = get_uom_conv_factor(uom, stock_uom)
return {"conversion_factor": conversion_factor or 1.0} return {"conversion_factor": conversion_factor or 1.0}
@ -1217,12 +1193,16 @@ def get_bin_details(item_code, warehouse, company=None, include_child_warehouses
def get_company_total_stock(item_code, company): def get_company_total_stock(item_code, company):
return frappe.db.sql( bin = frappe.qb.DocType("Bin")
"""SELECT sum(actual_qty) from wh = frappe.qb.DocType("Warehouse")
(`tabBin` INNER JOIN `tabWarehouse` ON `tabBin`.warehouse = `tabWarehouse`.name)
WHERE `tabWarehouse`.company = %s and `tabBin`.item_code = %s""", return (
(company, item_code), frappe.qb.from_(bin)
)[0][0] .inner_join(wh)
.on(bin.warehouse == wh.name)
.select(Sum(bin.actual_qty))
.where((wh.company == company) & (bin.item_code == item_code))
).run()[0][0]
@frappe.whitelist() @frappe.whitelist()
@ -1231,6 +1211,7 @@ def get_serial_no_details(item_code, warehouse, stock_qty, serial_no):
{"item_code": item_code, "warehouse": warehouse, "stock_qty": stock_qty, "serial_no": serial_no} {"item_code": item_code, "warehouse": warehouse, "stock_qty": stock_qty, "serial_no": serial_no}
) )
serial_no = get_serial_no(args) serial_no = get_serial_no(args)
return {"serial_no": serial_no} return {"serial_no": serial_no}
@ -1250,6 +1231,7 @@ def get_bin_details_and_serial_nos(
bin_details_and_serial_nos.update( bin_details_and_serial_nos.update(
get_serial_no_details(item_code, warehouse, stock_qty, serial_no) get_serial_no_details(item_code, warehouse, stock_qty, serial_no)
) )
return bin_details_and_serial_nos return bin_details_and_serial_nos
@ -1264,6 +1246,7 @@ def get_batch_qty_and_serial_no(batch_no, stock_qty, warehouse, item_code, has_s
) )
serial_no = get_serial_no(args) serial_no = get_serial_no(args)
batch_qty_and_serial_no.update({"serial_no": serial_no}) batch_qty_and_serial_no.update({"serial_no": serial_no})
return batch_qty_and_serial_no return batch_qty_and_serial_no
@ -1336,7 +1319,6 @@ def apply_price_list(args, as_doc=False):
def apply_price_list_on_item(args): def apply_price_list_on_item(args):
item_doc = frappe.db.get_value("Item", args.item_code, ["name", "variant_of"], as_dict=1) item_doc = frappe.db.get_value("Item", args.item_code, ["name", "variant_of"], as_dict=1)
item_details = get_price_list_rate(args, item_doc) item_details = get_price_list_rate(args, item_doc)
item_details.update(get_pricing_rule_for_item(args)) item_details.update(get_pricing_rule_for_item(args))
return item_details return item_details
@ -1420,12 +1402,12 @@ def get_valuation_rate(item_code, company, warehouse=None):
) or {"valuation_rate": 0} ) or {"valuation_rate": 0}
elif not item.get("is_stock_item"): elif not item.get("is_stock_item"):
valuation_rate = frappe.db.sql( pi_item = frappe.qb.DocType("Purchase Invoice Item")
"""select sum(base_net_amount) / sum(qty*conversion_factor) valuation_rate = (
from `tabPurchase Invoice Item` frappe.qb.from_(pi_item)
where item_code = %s and docstatus=1""", .select((Sum(pi_item.base_net_amount) / Sum(pi_item.qty * pi_item.conversion_factor)))
item_code, .where((pi_item.docstatus == 1) & (pi_item.item_code == item_code))
) ).run()
if valuation_rate: if valuation_rate:
return {"valuation_rate": valuation_rate[0][0] or 0.0} return {"valuation_rate": valuation_rate[0][0] or 0.0}
@ -1451,7 +1433,7 @@ def get_serial_no(args, serial_nos=None, sales_order=None):
if args.get("warehouse") and args.get("stock_qty") and args.get("item_code"): if args.get("warehouse") and args.get("stock_qty") and args.get("item_code"):
has_serial_no = frappe.get_value("Item", {"item_code": args.item_code}, "has_serial_no") has_serial_no = frappe.get_value("Item", {"item_code": args.item_code}, "has_serial_no")
if args.get("batch_no") and has_serial_no == 1: if args.get("batch_no") and has_serial_no == 1:
return get_serial_no_batchwise(args, sales_order) return get_serial_nos_by_fifo(args, sales_order)
elif has_serial_no == 1: elif has_serial_no == 1:
args = json.dumps( args = json.dumps(
{ {
@ -1483,31 +1465,35 @@ def get_blanket_order_details(args):
args = frappe._dict(json.loads(args)) args = frappe._dict(json.loads(args))
blanket_order_details = None blanket_order_details = None
condition = ""
if args.item_code:
if args.customer and args.doctype == "Sales Order":
condition = " and bo.customer=%(customer)s"
elif args.supplier and args.doctype == "Purchase Order":
condition = " and bo.supplier=%(supplier)s"
if args.blanket_order:
condition += " and bo.name =%(blanket_order)s"
if args.transaction_date:
condition += " and bo.to_date>=%(transaction_date)s"
blanket_order_details = frappe.db.sql( if args.item_code:
""" bo = frappe.qb.DocType("Blanket Order")
select boi.rate as blanket_order_rate, bo.name as blanket_order bo_item = frappe.qb.DocType("Blanket Order Item")
from `tabBlanket Order` bo, `tabBlanket Order Item` boi
where bo.company=%(company)s and boi.item_code=%(item_code)s query = (
and bo.docstatus=1 and bo.name = boi.parent {0} frappe.qb.from_(bo)
""".format( .from_(bo_item)
condition .select(bo_item.rate.as_("blanket_order_rate"), bo.name.as_("blanket_order"))
), .where(
args, (bo.company == args.company)
as_dict=True, & (bo_item.item_code == args.item_code)
& (bo.docstatus == 1)
& (bo.name == bo_item.parent)
)
) )
if args.customer and args.doctype == "Sales Order":
query = query.where(bo.customer == args.customer)
elif args.supplier and args.doctype == "Purchase Order":
query = query.where(bo.supplier == args.supplier)
if args.blanket_order:
query = query.where(bo.name == args.blanket_order)
if args.transaction_date:
query = query.where(bo.to_date >= args.transaction_date)
blanket_order_details = query.run(as_dict=True)
blanket_order_details = blanket_order_details[0] if blanket_order_details else "" blanket_order_details = blanket_order_details[0] if blanket_order_details else ""
return blanket_order_details return blanket_order_details
@ -1517,10 +1503,10 @@ def get_so_reservation_for_item(args):
if get_reserved_qty_for_so(args.get("against_sales_order"), args.get("item_code")): if get_reserved_qty_for_so(args.get("against_sales_order"), args.get("item_code")):
reserved_so = args.get("against_sales_order") reserved_so = args.get("against_sales_order")
elif args.get("against_sales_invoice"): elif args.get("against_sales_invoice"):
sales_order = frappe.db.sql( sales_order = frappe.db.get_all(
"""select sales_order from `tabSales Invoice Item` where "Sales Invoice Item",
parent=%s and item_code=%s""", filters={"parent": args.get("against_sales_invoice"), "item_code": args.get("item_code")},
(args.get("against_sales_invoice"), args.get("item_code")), fields="sales_order",
) )
if sales_order and sales_order[0]: if sales_order and sales_order[0]:
if get_reserved_qty_for_so(sales_order[0][0], args.get("item_code")): if get_reserved_qty_for_so(sales_order[0][0], args.get("item_code")):
@ -1532,13 +1518,14 @@ def get_so_reservation_for_item(args):
def get_reserved_qty_for_so(sales_order, item_code): def get_reserved_qty_for_so(sales_order, item_code):
reserved_qty = frappe.db.sql( reserved_qty = frappe.db.get_value(
"""select sum(qty) from `tabSales Order Item` "Sales Order Item",
where parent=%s and item_code=%s and ensure_delivery_based_on_produced_serial_no=1 filters={
""", "parent": sales_order,
(sales_order, item_code), "item_code": item_code,
"ensure_delivery_based_on_produced_serial_no": 1,
},
fieldname="sum(qty)",
) )
if reserved_qty and reserved_qty[0][0]:
return reserved_qty[0][0] return reserved_qty or 0
else:
return 0