mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-01 19:29:10 +00:00
style: format code with black
This commit is contained in:
@@ -7,9 +7,12 @@ from erpnext.utilities.activation import get_level
|
||||
|
||||
|
||||
def update_doctypes():
|
||||
for d in frappe.db.sql("""select df.parent, df.fieldname
|
||||
for d in frappe.db.sql(
|
||||
"""select df.parent, df.fieldname
|
||||
from tabDocField df, tabDocType dt where df.fieldname
|
||||
like "%description%" and df.parent = dt.name and dt.istable = 1""", as_dict=1):
|
||||
like "%description%" and df.parent = dt.name and dt.istable = 1""",
|
||||
as_dict=1,
|
||||
):
|
||||
dt = frappe.get_doc("DocType", d.parent)
|
||||
|
||||
for f in dt.fields:
|
||||
@@ -18,20 +21,17 @@ def update_doctypes():
|
||||
dt.save()
|
||||
break
|
||||
|
||||
|
||||
def get_site_info(site_info):
|
||||
# called via hook
|
||||
company = frappe.db.get_single_value('Global Defaults', 'default_company')
|
||||
company = frappe.db.get_single_value("Global Defaults", "default_company")
|
||||
domain = None
|
||||
|
||||
if not company:
|
||||
company = frappe.db.sql('select name from `tabCompany` order by creation asc')
|
||||
company = frappe.db.sql("select name from `tabCompany` order by creation asc")
|
||||
company = company[0][0] if company else None
|
||||
|
||||
if company:
|
||||
domain = frappe.get_cached_value('Company', cstr(company), 'domain')
|
||||
domain = frappe.get_cached_value("Company", cstr(company), "domain")
|
||||
|
||||
return {
|
||||
'company': company,
|
||||
'domain': domain,
|
||||
'activation': get_level()
|
||||
}
|
||||
return {"company": company, "domain": domain, "activation": get_level()}
|
||||
|
||||
@@ -41,7 +41,7 @@ def get_level():
|
||||
"Supplier": 5,
|
||||
"Task": 5,
|
||||
"User": 5,
|
||||
"Work Order": 5
|
||||
"Work Order": 5,
|
||||
}
|
||||
|
||||
for doctype, min_count in doctypes.items():
|
||||
@@ -50,111 +50,118 @@ def get_level():
|
||||
activation_level += 1
|
||||
sales_data.append({doctype: count})
|
||||
|
||||
if frappe.db.get_single_value('System Settings', 'setup_complete'):
|
||||
if frappe.db.get_single_value("System Settings", "setup_complete"):
|
||||
activation_level += 1
|
||||
|
||||
communication_number = frappe.db.count('Communication', dict(communication_medium='Email'))
|
||||
communication_number = frappe.db.count("Communication", dict(communication_medium="Email"))
|
||||
if communication_number > 10:
|
||||
activation_level += 1
|
||||
sales_data.append({"Communication": communication_number})
|
||||
|
||||
# recent login
|
||||
if frappe.db.sql('select name from tabUser where last_login > date_sub(now(), interval 2 day) limit 1'):
|
||||
if frappe.db.sql(
|
||||
"select name from tabUser where last_login > date_sub(now(), interval 2 day) limit 1"
|
||||
):
|
||||
activation_level += 1
|
||||
|
||||
level = {"activation_level": activation_level, "sales_data": sales_data}
|
||||
|
||||
return level
|
||||
|
||||
|
||||
def get_help_messages():
|
||||
'''Returns help messages to be shown on Desktop'''
|
||||
"""Returns help messages to be shown on Desktop"""
|
||||
if get_level() > 6:
|
||||
return []
|
||||
|
||||
domain = frappe.get_cached_value('Company', erpnext.get_default_company(), 'domain')
|
||||
domain = frappe.get_cached_value("Company", erpnext.get_default_company(), "domain")
|
||||
messages = []
|
||||
|
||||
message_settings = [
|
||||
frappe._dict(
|
||||
doctype='Lead',
|
||||
title=_('Create Leads'),
|
||||
description=_('Leads help you get business, add all your contacts and more as your leads'),
|
||||
action=_('Create Lead'),
|
||||
route='List/Lead',
|
||||
domain=('Manufacturing', 'Retail', 'Services', 'Distribution'),
|
||||
target=3
|
||||
doctype="Lead",
|
||||
title=_("Create Leads"),
|
||||
description=_("Leads help you get business, add all your contacts and more as your leads"),
|
||||
action=_("Create Lead"),
|
||||
route="List/Lead",
|
||||
domain=("Manufacturing", "Retail", "Services", "Distribution"),
|
||||
target=3,
|
||||
),
|
||||
frappe._dict(
|
||||
doctype='Quotation',
|
||||
title=_('Create customer quotes'),
|
||||
description=_('Quotations are proposals, bids you have sent to your customers'),
|
||||
action=_('Create Quotation'),
|
||||
route='List/Quotation',
|
||||
domain=('Manufacturing', 'Retail', 'Services', 'Distribution'),
|
||||
target=3
|
||||
doctype="Quotation",
|
||||
title=_("Create customer quotes"),
|
||||
description=_("Quotations are proposals, bids you have sent to your customers"),
|
||||
action=_("Create Quotation"),
|
||||
route="List/Quotation",
|
||||
domain=("Manufacturing", "Retail", "Services", "Distribution"),
|
||||
target=3,
|
||||
),
|
||||
frappe._dict(
|
||||
doctype='Sales Order',
|
||||
title=_('Manage your orders'),
|
||||
description=_('Create Sales Orders to help you plan your work and deliver on-time'),
|
||||
action=_('Create Sales Order'),
|
||||
route='List/Sales Order',
|
||||
domain=('Manufacturing', 'Retail', 'Services', 'Distribution'),
|
||||
target=3
|
||||
doctype="Sales Order",
|
||||
title=_("Manage your orders"),
|
||||
description=_("Create Sales Orders to help you plan your work and deliver on-time"),
|
||||
action=_("Create Sales Order"),
|
||||
route="List/Sales Order",
|
||||
domain=("Manufacturing", "Retail", "Services", "Distribution"),
|
||||
target=3,
|
||||
),
|
||||
frappe._dict(
|
||||
doctype='Purchase Order',
|
||||
title=_('Create Purchase Orders'),
|
||||
description=_('Purchase orders help you plan and follow up on your purchases'),
|
||||
action=_('Create Purchase Order'),
|
||||
route='List/Purchase Order',
|
||||
domain=('Manufacturing', 'Retail', 'Services', 'Distribution'),
|
||||
target=3
|
||||
doctype="Purchase Order",
|
||||
title=_("Create Purchase Orders"),
|
||||
description=_("Purchase orders help you plan and follow up on your purchases"),
|
||||
action=_("Create Purchase Order"),
|
||||
route="List/Purchase Order",
|
||||
domain=("Manufacturing", "Retail", "Services", "Distribution"),
|
||||
target=3,
|
||||
),
|
||||
frappe._dict(
|
||||
doctype='User',
|
||||
title=_('Create Users'),
|
||||
description=_('Add the rest of your organization as your users. You can also add invite Customers to your portal by adding them from Contacts'),
|
||||
action=_('Create User'),
|
||||
route='List/User',
|
||||
domain=('Manufacturing', 'Retail', 'Services', 'Distribution'),
|
||||
target=3
|
||||
doctype="User",
|
||||
title=_("Create Users"),
|
||||
description=_(
|
||||
"Add the rest of your organization as your users. You can also add invite Customers to your portal by adding them from Contacts"
|
||||
),
|
||||
action=_("Create User"),
|
||||
route="List/User",
|
||||
domain=("Manufacturing", "Retail", "Services", "Distribution"),
|
||||
target=3,
|
||||
),
|
||||
frappe._dict(
|
||||
doctype='Timesheet',
|
||||
title=_('Add Timesheets'),
|
||||
description=_('Timesheets help keep track of time, cost and billing for activites done by your team'),
|
||||
action=_('Create Timesheet'),
|
||||
route='List/Timesheet',
|
||||
domain=('Services',),
|
||||
target=5
|
||||
doctype="Timesheet",
|
||||
title=_("Add Timesheets"),
|
||||
description=_(
|
||||
"Timesheets help keep track of time, cost and billing for activites done by your team"
|
||||
),
|
||||
action=_("Create Timesheet"),
|
||||
route="List/Timesheet",
|
||||
domain=("Services",),
|
||||
target=5,
|
||||
),
|
||||
frappe._dict(
|
||||
doctype='Student',
|
||||
title=_('Add Students'),
|
||||
description=_('Students are at the heart of the system, add all your students'),
|
||||
action=_('Create Student'),
|
||||
route='List/Student',
|
||||
domain=('Education',),
|
||||
target=5
|
||||
doctype="Student",
|
||||
title=_("Add Students"),
|
||||
description=_("Students are at the heart of the system, add all your students"),
|
||||
action=_("Create Student"),
|
||||
route="List/Student",
|
||||
domain=("Education",),
|
||||
target=5,
|
||||
),
|
||||
frappe._dict(
|
||||
doctype='Student Batch',
|
||||
title=_('Group your students in batches'),
|
||||
description=_('Student Batches help you track attendance, assessments and fees for students'),
|
||||
action=_('Create Student Batch'),
|
||||
route='List/Student Batch',
|
||||
domain=('Education',),
|
||||
target=3
|
||||
doctype="Student Batch",
|
||||
title=_("Group your students in batches"),
|
||||
description=_("Student Batches help you track attendance, assessments and fees for students"),
|
||||
action=_("Create Student Batch"),
|
||||
route="List/Student Batch",
|
||||
domain=("Education",),
|
||||
target=3,
|
||||
),
|
||||
frappe._dict(
|
||||
doctype='Employee',
|
||||
title=_('Create Employee Records'),
|
||||
description=_('Create Employee records to manage leaves, expense claims and payroll'),
|
||||
action=_('Create Employee'),
|
||||
route='List/Employee',
|
||||
target=3
|
||||
)
|
||||
doctype="Employee",
|
||||
title=_("Create Employee Records"),
|
||||
description=_("Create Employee records to manage leaves, expense claims and payroll"),
|
||||
action=_("Create Employee"),
|
||||
route="List/Employee",
|
||||
target=3,
|
||||
),
|
||||
]
|
||||
|
||||
for m in message_settings:
|
||||
|
||||
@@ -9,13 +9,16 @@ from frappe.utils.bot import BotParser
|
||||
|
||||
class FindItemBot(BotParser):
|
||||
def get_reply(self):
|
||||
if self.startswith('where is', 'find item', 'locate'):
|
||||
if not frappe.has_permission('Warehouse'):
|
||||
if self.startswith("where is", "find item", "locate"):
|
||||
if not frappe.has_permission("Warehouse"):
|
||||
raise frappe.PermissionError
|
||||
|
||||
item = '%{0}%'.format(self.strip_words(self.query, 'where is', 'find item', 'locate'))
|
||||
items = frappe.db.sql('''select name from `tabItem` where item_code like %(txt)s
|
||||
or item_name like %(txt)s or description like %(txt)s''', dict(txt=item))
|
||||
item = "%{0}%".format(self.strip_words(self.query, "where is", "find item", "locate"))
|
||||
items = frappe.db.sql(
|
||||
"""select name from `tabItem` where item_code like %(txt)s
|
||||
or item_name like %(txt)s or description like %(txt)s""",
|
||||
dict(txt=item),
|
||||
)
|
||||
|
||||
if items:
|
||||
out = []
|
||||
@@ -23,14 +26,19 @@ class FindItemBot(BotParser):
|
||||
for item in items:
|
||||
found = False
|
||||
for warehouse in warehouses:
|
||||
qty = frappe.db.get_value("Bin", {'item_code': item[0], 'warehouse': warehouse.name}, 'actual_qty')
|
||||
qty = frappe.db.get_value(
|
||||
"Bin", {"item_code": item[0], "warehouse": warehouse.name}, "actual_qty"
|
||||
)
|
||||
if qty:
|
||||
out.append(_('{0} units of [{1}](/app/Form/Item/{1}) found in [{2}](/app/Form/Warehouse/{2})').format(qty,
|
||||
item[0], warehouse.name))
|
||||
out.append(
|
||||
_("{0} units of [{1}](/app/Form/Item/{1}) found in [{2}](/app/Form/Warehouse/{2})").format(
|
||||
qty, item[0], warehouse.name
|
||||
)
|
||||
)
|
||||
found = True
|
||||
|
||||
if not found:
|
||||
out.append(_('[{0}](/app/Form/Item/{0}) is out of stock').format(item[0]))
|
||||
out.append(_("[{0}](/app/Form/Item/{0}) is out of stock").format(item[0]))
|
||||
|
||||
return "\n\n".join(out)
|
||||
|
||||
|
||||
@@ -45,9 +45,13 @@ def job(deserialized_data, from_doctype, to_doctype):
|
||||
frappe.db.rollback(save_point="before_creation_state")
|
||||
failed_history.append(e)
|
||||
failed.append(e)
|
||||
update_logger(doc_name, e, from_doctype, to_doctype, status="Failed", log_date=str(date.today()))
|
||||
update_logger(
|
||||
doc_name, e, from_doctype, to_doctype, status="Failed", log_date=str(date.today())
|
||||
)
|
||||
if not failed:
|
||||
update_logger(doc_name, None, from_doctype, to_doctype, status="Success", log_date=str(date.today()))
|
||||
update_logger(
|
||||
doc_name, None, from_doctype, to_doctype, status="Success", log_date=str(date.today())
|
||||
)
|
||||
|
||||
show_job_status(failed_history, deserialized_data, to_doctype)
|
||||
|
||||
@@ -96,7 +100,7 @@ def task(doc_name, from_doctype, to_doctype):
|
||||
},
|
||||
"Purchase Receipt": {"Purchase Invoice": purchase_receipt.make_purchase_invoice},
|
||||
}
|
||||
if to_doctype in ['Advance Payment', 'Payment']:
|
||||
if to_doctype in ["Advance Payment", "Payment"]:
|
||||
obj = mapper[from_doctype][to_doctype](from_doctype, doc_name)
|
||||
else:
|
||||
obj = mapper[from_doctype][to_doctype](doc_name)
|
||||
@@ -142,9 +146,7 @@ def update_logger(doc_name, e, from_doctype, to_doctype, status, log_date=None,
|
||||
else:
|
||||
log_doc = get_logger_doc(log_date)
|
||||
if record_exists(log_doc, doc_name, status):
|
||||
append_data_to_logger(
|
||||
log_doc, doc_name, e, from_doctype, to_doctype, status, restarted
|
||||
)
|
||||
append_data_to_logger(log_doc, doc_name, e, from_doctype, to_doctype, status, restarted)
|
||||
log_doc.save()
|
||||
|
||||
|
||||
@@ -158,20 +160,20 @@ def show_job_status(failed_history, deserialized_data, to_doctype):
|
||||
|
||||
if len(failed_history) != 0 and len(failed_history) < len(deserialized_data):
|
||||
frappe.msgprint(
|
||||
_("""Creation of {0} partially successful.
|
||||
Check <b><a href="/app/bulk-transaction-log">Bulk Transaction Log</a></b>""").format(
|
||||
to_doctype
|
||||
),
|
||||
_(
|
||||
"""Creation of {0} partially successful.
|
||||
Check <b><a href="/app/bulk-transaction-log">Bulk Transaction Log</a></b>"""
|
||||
).format(to_doctype),
|
||||
title="Partially successful",
|
||||
indicator="orange",
|
||||
)
|
||||
|
||||
if len(failed_history) == len(deserialized_data):
|
||||
frappe.msgprint(
|
||||
_("""Creation of {0} failed.
|
||||
Check <b><a href="/app/bulk-transaction-log">Bulk Transaction Log</a></b>""").format(
|
||||
to_doctype
|
||||
),
|
||||
_(
|
||||
"""Creation of {0} failed.
|
||||
Check <b><a href="/app/bulk-transaction-log">Bulk Transaction Log</a></b>"""
|
||||
).format(to_doctype),
|
||||
title="Failed",
|
||||
indicator="red",
|
||||
)
|
||||
@@ -198,4 +200,4 @@ def mark_retrired_transaction(log_doc, doc_name):
|
||||
|
||||
log_doc.save()
|
||||
|
||||
return record
|
||||
return record
|
||||
|
||||
@@ -12,14 +12,19 @@ from frappe.model.rename_doc import bulk_rename
|
||||
class RenameTool(Document):
|
||||
pass
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_doctypes():
|
||||
return frappe.db.sql_list("""select name from tabDocType
|
||||
where allow_rename=1 and module!='Core' order by name""")
|
||||
return frappe.db.sql_list(
|
||||
"""select name from tabDocType
|
||||
where allow_rename=1 and module!='Core' order by name"""
|
||||
)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def upload(select_doctype=None, rows=None):
|
||||
from frappe.utils.csvutils import read_csv_content_from_attached_file
|
||||
|
||||
if not select_doctype:
|
||||
select_doctype = frappe.form_dict.select_doctype
|
||||
|
||||
|
||||
@@ -5,5 +5,6 @@ import unittest
|
||||
|
||||
# test_records = frappe.get_test_records('SMS Log')
|
||||
|
||||
|
||||
class TestSMSLog(unittest.TestCase):
|
||||
pass
|
||||
|
||||
@@ -28,16 +28,17 @@ class Video(Document):
|
||||
|
||||
try:
|
||||
video = api.get_video_by_id(video_id=self.youtube_video_id)
|
||||
video_stats = video.items[0].to_dict().get('statistics')
|
||||
video_stats = video.items[0].to_dict().get("statistics")
|
||||
|
||||
self.like_count = video_stats.get('likeCount')
|
||||
self.view_count = video_stats.get('viewCount')
|
||||
self.dislike_count = video_stats.get('dislikeCount')
|
||||
self.comment_count = video_stats.get('commentCount')
|
||||
self.like_count = video_stats.get("likeCount")
|
||||
self.view_count = video_stats.get("viewCount")
|
||||
self.dislike_count = video_stats.get("dislikeCount")
|
||||
self.comment_count = video_stats.get("commentCount")
|
||||
|
||||
except Exception:
|
||||
title = "Failed to Update YouTube Statistics for Video: {0}".format(self.name)
|
||||
frappe.log_error(title + "\n\n" + frappe.get_traceback(), title=title)
|
||||
frappe.log_error(title + "\n\n" + frappe.get_traceback(), title=title)
|
||||
|
||||
|
||||
def is_tracking_enabled():
|
||||
return frappe.db.get_single_value("Video Settings", "enable_youtube_tracking")
|
||||
@@ -54,7 +55,9 @@ def get_frequency(value):
|
||||
|
||||
def update_youtube_data():
|
||||
# Called every 30 minutes via hooks
|
||||
enable_youtube_tracking, frequency = frappe.db.get_value("Video Settings", "Video Settings", ["enable_youtube_tracking", "frequency"])
|
||||
enable_youtube_tracking, frequency = frappe.db.get_value(
|
||||
"Video Settings", "Video Settings", ["enable_youtube_tracking", "frequency"]
|
||||
)
|
||||
|
||||
if not enable_youtube_tracking:
|
||||
return
|
||||
@@ -77,19 +80,21 @@ def get_formatted_ids(video_list):
|
||||
for video in video_list:
|
||||
ids.append(video.youtube_video_id)
|
||||
|
||||
return ','.join(ids)
|
||||
return ",".join(ids)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_id_from_url(url):
|
||||
"""
|
||||
Returns video id from url
|
||||
:param youtube url: String URL
|
||||
Returns video id from url
|
||||
:param youtube url: String URL
|
||||
"""
|
||||
if not isinstance(url, str):
|
||||
frappe.throw(_("URL can only be a string"), title=_("Invalid URL"))
|
||||
|
||||
pattern = re.compile(r'[a-z\:\//\.]+(youtube|youtu)\.(com|be)/(watch\?v=|embed/|.+\?v=)?([^"&?\s]{11})?')
|
||||
pattern = re.compile(
|
||||
r'[a-z\:\//\.]+(youtube|youtu)\.(com|be)/(watch\?v=|embed/|.+\?v=)?([^"&?\s]{11})?'
|
||||
)
|
||||
id = pattern.match(url)
|
||||
return id.groups()[-1]
|
||||
|
||||
@@ -105,7 +110,7 @@ def batch_update_youtube_data():
|
||||
return video_stats
|
||||
except Exception:
|
||||
title = "Failed to Update YouTube Statistics"
|
||||
frappe.log_error(title + "\n\n" + frappe.get_traceback(), title=title)
|
||||
frappe.log_error(title + "\n\n" + frappe.get_traceback(), title=title)
|
||||
|
||||
def prepare_and_set_data(video_list):
|
||||
video_ids = get_formatted_ids(video_list)
|
||||
@@ -114,24 +119,27 @@ def batch_update_youtube_data():
|
||||
|
||||
def set_youtube_data(entries):
|
||||
for entry in entries:
|
||||
video_stats = entry.to_dict().get('statistics')
|
||||
video_id = entry.to_dict().get('id')
|
||||
video_stats = entry.to_dict().get("statistics")
|
||||
video_id = entry.to_dict().get("id")
|
||||
stats = {
|
||||
'like_count' : video_stats.get('likeCount'),
|
||||
'view_count' : video_stats.get('viewCount'),
|
||||
'dislike_count' : video_stats.get('dislikeCount'),
|
||||
'comment_count' : video_stats.get('commentCount'),
|
||||
'video_id': video_id
|
||||
"like_count": video_stats.get("likeCount"),
|
||||
"view_count": video_stats.get("viewCount"),
|
||||
"dislike_count": video_stats.get("dislikeCount"),
|
||||
"comment_count": video_stats.get("commentCount"),
|
||||
"video_id": video_id,
|
||||
}
|
||||
|
||||
frappe.db.sql("""
|
||||
frappe.db.sql(
|
||||
"""
|
||||
UPDATE `tabVideo`
|
||||
SET
|
||||
like_count = %(like_count)s,
|
||||
view_count = %(view_count)s,
|
||||
dislike_count = %(dislike_count)s,
|
||||
comment_count = %(comment_count)s
|
||||
WHERE youtube_video_id = %(video_id)s""", stats)
|
||||
WHERE youtube_video_id = %(video_id)s""",
|
||||
stats,
|
||||
)
|
||||
|
||||
video_list = frappe.get_all("Video", fields=["youtube_video_id"])
|
||||
if len(video_list) > 50:
|
||||
|
||||
@@ -18,5 +18,5 @@ class VideoSettings(Document):
|
||||
build("youtube", "v3", developerKey=self.api_key)
|
||||
except Exception:
|
||||
title = _("Failed to Authenticate the API key.")
|
||||
frappe.log_error(title + "\n\n" + frappe.get_traceback(), title=title)
|
||||
frappe.log_error(title + "\n\n" + frappe.get_traceback(), title=title)
|
||||
frappe.throw(title + " Please check the error logs.", title=_("Invalid Credentials"))
|
||||
|
||||
@@ -8,11 +8,11 @@ from frappe import _
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_all_nodes(method, company):
|
||||
'''Recursively gets all data from nodes'''
|
||||
"""Recursively gets all data from nodes"""
|
||||
method = frappe.get_attr(method)
|
||||
|
||||
if method not in frappe.whitelisted:
|
||||
frappe.throw(_('Not Permitted'), frappe.PermissionError)
|
||||
frappe.throw(_("Not Permitted"), frappe.PermissionError)
|
||||
|
||||
root_nodes = method(company=company)
|
||||
result = []
|
||||
@@ -21,14 +21,16 @@ def get_all_nodes(method, company):
|
||||
for root in root_nodes:
|
||||
data = method(root.id, company)
|
||||
result.append(dict(parent=root.id, parent_name=root.name, data=data))
|
||||
nodes_to_expand.extend([{'id': d.get('id'), 'name': d.get('name')} for d in data if d.get('expandable')])
|
||||
nodes_to_expand.extend(
|
||||
[{"id": d.get("id"), "name": d.get("name")} for d in data if d.get("expandable")]
|
||||
)
|
||||
|
||||
while nodes_to_expand:
|
||||
parent = nodes_to_expand.pop(0)
|
||||
data = method(parent.get('id'), company)
|
||||
result.append(dict(parent=parent.get('id'), parent_name=parent.get('name'), data=data))
|
||||
data = method(parent.get("id"), company)
|
||||
result.append(dict(parent=parent.get("id"), parent_name=parent.get("name"), data=data))
|
||||
for d in data:
|
||||
if d.get('expandable'):
|
||||
nodes_to_expand.append({'id': d.get('id'), 'name': d.get('name')})
|
||||
if d.get("expandable"):
|
||||
nodes_to_expand.append({"id": d.get("id"), "name": d.get("name")})
|
||||
|
||||
return result
|
||||
|
||||
@@ -9,32 +9,41 @@ from erpnext.stock.doctype.batch.batch import get_batch_qty
|
||||
|
||||
|
||||
def get_web_item_qty_in_stock(item_code, item_warehouse_field, warehouse=None):
|
||||
in_stock, stock_qty = 0, ''
|
||||
template_item_code, is_stock_item = frappe.db.get_value("Item", item_code, ["variant_of", "is_stock_item"])
|
||||
in_stock, stock_qty = 0, ""
|
||||
template_item_code, is_stock_item = frappe.db.get_value(
|
||||
"Item", item_code, ["variant_of", "is_stock_item"]
|
||||
)
|
||||
|
||||
if not warehouse:
|
||||
warehouse = frappe.db.get_value("Website Item", {"item_code": item_code}, item_warehouse_field)
|
||||
|
||||
if not warehouse and template_item_code and template_item_code != item_code:
|
||||
warehouse = frappe.db.get_value("Website Item", {"item_code": template_item_code}, item_warehouse_field)
|
||||
warehouse = frappe.db.get_value(
|
||||
"Website Item", {"item_code": template_item_code}, item_warehouse_field
|
||||
)
|
||||
|
||||
if warehouse:
|
||||
stock_qty = frappe.db.sql("""
|
||||
stock_qty = frappe.db.sql(
|
||||
"""
|
||||
select GREATEST(S.actual_qty - S.reserved_qty - S.reserved_qty_for_production - S.reserved_qty_for_sub_contract, 0) / IFNULL(C.conversion_factor, 1)
|
||||
from tabBin S
|
||||
inner join `tabItem` I on S.item_code = I.Item_code
|
||||
left join `tabUOM Conversion Detail` C on I.sales_uom = C.uom and C.parent = I.Item_code
|
||||
where S.item_code=%s and S.warehouse=%s""", (item_code, warehouse))
|
||||
where S.item_code=%s and S.warehouse=%s""",
|
||||
(item_code, warehouse),
|
||||
)
|
||||
|
||||
if stock_qty:
|
||||
stock_qty = adjust_qty_for_expired_items(item_code, stock_qty, warehouse)
|
||||
in_stock = stock_qty[0][0] > 0 and 1 or 0
|
||||
|
||||
return frappe._dict({"in_stock": in_stock, "stock_qty": stock_qty, "is_stock_item": is_stock_item})
|
||||
return frappe._dict(
|
||||
{"in_stock": in_stock, "stock_qty": stock_qty, "is_stock_item": is_stock_item}
|
||||
)
|
||||
|
||||
|
||||
def adjust_qty_for_expired_items(item_code, stock_qty, warehouse):
|
||||
batches = frappe.get_all('Batch', filters=[{'item': item_code}], fields=['expiry_date', 'name'])
|
||||
batches = frappe.get_all("Batch", filters=[{"item": item_code}], fields=["expiry_date", "name"])
|
||||
expired_batches = get_expired_batches(batches)
|
||||
stock_qty = [list(item) for item in stock_qty]
|
||||
|
||||
@@ -67,33 +76,42 @@ def qty_from_all_warehouses(batch_info):
|
||||
|
||||
return qty
|
||||
|
||||
|
||||
def get_price(item_code, price_list, customer_group, company, qty=1):
|
||||
from erpnext.e_commerce.shopping_cart.cart import get_party
|
||||
|
||||
template_item_code = frappe.db.get_value("Item", item_code, "variant_of")
|
||||
|
||||
if price_list:
|
||||
price = frappe.get_all("Item Price", fields=["price_list_rate", "currency"],
|
||||
filters={"price_list": price_list, "item_code": item_code})
|
||||
price = frappe.get_all(
|
||||
"Item Price",
|
||||
fields=["price_list_rate", "currency"],
|
||||
filters={"price_list": price_list, "item_code": item_code},
|
||||
)
|
||||
|
||||
if template_item_code and not price:
|
||||
price = frappe.get_all("Item Price", fields=["price_list_rate", "currency"],
|
||||
filters={"price_list": price_list, "item_code": template_item_code})
|
||||
price = frappe.get_all(
|
||||
"Item Price",
|
||||
fields=["price_list_rate", "currency"],
|
||||
filters={"price_list": price_list, "item_code": template_item_code},
|
||||
)
|
||||
|
||||
if price:
|
||||
party = get_party()
|
||||
pricing_rule_dict = frappe._dict({
|
||||
"item_code": item_code,
|
||||
"qty": qty,
|
||||
"stock_qty": qty,
|
||||
"transaction_type": "selling",
|
||||
"price_list": price_list,
|
||||
"customer_group": customer_group,
|
||||
"company": company,
|
||||
"conversion_rate": 1,
|
||||
"for_shopping_cart": True,
|
||||
"currency": frappe.db.get_value("Price List", price_list, "currency")
|
||||
})
|
||||
pricing_rule_dict = frappe._dict(
|
||||
{
|
||||
"item_code": item_code,
|
||||
"qty": qty,
|
||||
"stock_qty": qty,
|
||||
"transaction_type": "selling",
|
||||
"price_list": price_list,
|
||||
"customer_group": customer_group,
|
||||
"company": company,
|
||||
"conversion_rate": 1,
|
||||
"for_shopping_cart": True,
|
||||
"currency": frappe.db.get_value("Price List", price_list, "currency"),
|
||||
}
|
||||
)
|
||||
|
||||
if party and party.doctype == "Customer":
|
||||
pricing_rule_dict.update({"customer": party.name})
|
||||
@@ -108,7 +126,9 @@ def get_price(item_code, price_list, customer_group, company, qty=1):
|
||||
if pricing_rule.pricing_rule_for == "Discount Percentage":
|
||||
price_obj.discount_percent = pricing_rule.discount_percentage
|
||||
price_obj.formatted_discount_percent = str(flt(pricing_rule.discount_percentage, 0)) + "%"
|
||||
price_obj.price_list_rate = flt(price_obj.price_list_rate * (1.0 - (flt(pricing_rule.discount_percentage) / 100.0)))
|
||||
price_obj.price_list_rate = flt(
|
||||
price_obj.price_list_rate * (1.0 - (flt(pricing_rule.discount_percentage) / 100.0))
|
||||
)
|
||||
|
||||
if pricing_rule.pricing_rule_for == "Rate":
|
||||
rate_discount = flt(mrp) - flt(pricing_rule.price_list_rate)
|
||||
@@ -117,21 +137,33 @@ def get_price(item_code, price_list, customer_group, company, qty=1):
|
||||
price_obj.price_list_rate = pricing_rule.price_list_rate or 0
|
||||
|
||||
if price_obj:
|
||||
price_obj["formatted_price"] = fmt_money(price_obj["price_list_rate"], currency=price_obj["currency"])
|
||||
price_obj["formatted_price"] = fmt_money(
|
||||
price_obj["price_list_rate"], currency=price_obj["currency"]
|
||||
)
|
||||
if mrp != price_obj["price_list_rate"]:
|
||||
price_obj["formatted_mrp"] = fmt_money(mrp, currency=price_obj["currency"])
|
||||
|
||||
price_obj["currency_symbol"] = not cint(frappe.db.get_default("hide_currency_symbol")) \
|
||||
and (frappe.db.get_value("Currency", price_obj.currency, "symbol", cache=True) or price_obj.currency) \
|
||||
price_obj["currency_symbol"] = (
|
||||
not cint(frappe.db.get_default("hide_currency_symbol"))
|
||||
and (
|
||||
frappe.db.get_value("Currency", price_obj.currency, "symbol", cache=True)
|
||||
or price_obj.currency
|
||||
)
|
||||
or ""
|
||||
)
|
||||
|
||||
uom_conversion_factor = frappe.db.sql("""select C.conversion_factor
|
||||
uom_conversion_factor = frappe.db.sql(
|
||||
"""select C.conversion_factor
|
||||
from `tabUOM Conversion Detail` C
|
||||
inner join `tabItem` I on C.parent = I.name and C.uom = I.sales_uom
|
||||
where I.name = %s""", item_code)
|
||||
where I.name = %s""",
|
||||
item_code,
|
||||
)
|
||||
|
||||
uom_conversion_factor = uom_conversion_factor[0][0] if uom_conversion_factor else 1
|
||||
price_obj["formatted_price_sales_uom"] = fmt_money(price_obj["price_list_rate"] * uom_conversion_factor, currency=price_obj["currency"])
|
||||
price_obj["formatted_price_sales_uom"] = fmt_money(
|
||||
price_obj["price_list_rate"] * uom_conversion_factor, currency=price_obj["currency"]
|
||||
)
|
||||
|
||||
if not price_obj["price_list_rate"]:
|
||||
price_obj["price_list_rate"] = 0
|
||||
@@ -144,11 +176,17 @@ def get_price(item_code, price_list, customer_group, company, qty=1):
|
||||
|
||||
return price_obj
|
||||
|
||||
|
||||
def get_non_stock_item_status(item_code, item_warehouse_field):
|
||||
# if item is a product bundle, check if its bundle items are in stock
|
||||
if frappe.db.exists("Product Bundle", item_code):
|
||||
items = frappe.get_doc("Product Bundle", item_code).get_all_children()
|
||||
bundle_warehouse = frappe.db.get_value("Website Item", {"item_code": item_code}, item_warehouse_field)
|
||||
return all(get_web_item_qty_in_stock(d.item_code, item_warehouse_field, bundle_warehouse).in_stock for d in items)
|
||||
bundle_warehouse = frappe.db.get_value(
|
||||
"Website Item", {"item_code": item_code}, item_warehouse_field
|
||||
)
|
||||
return all(
|
||||
get_web_item_qty_in_stock(d.item_code, item_warehouse_field, bundle_warehouse).in_stock
|
||||
for d in items
|
||||
)
|
||||
else:
|
||||
return 1
|
||||
|
||||
@@ -16,91 +16,51 @@ def execute(filters=None):
|
||||
chart_data, summary = get_chart_summary_data(data)
|
||||
return columns, data, None, chart_data, summary
|
||||
|
||||
|
||||
def get_columns():
|
||||
return [
|
||||
{
|
||||
"label": _("Published Date"),
|
||||
"fieldname": "publish_date",
|
||||
"fieldtype": "Date",
|
||||
"width": 100
|
||||
},
|
||||
{
|
||||
"label": _("Title"),
|
||||
"fieldname": "title",
|
||||
"fieldtype": "Data",
|
||||
"width": 200
|
||||
},
|
||||
{
|
||||
"label": _("Duration"),
|
||||
"fieldname": "duration",
|
||||
"fieldtype": "Duration",
|
||||
"width": 100
|
||||
},
|
||||
{
|
||||
"label": _("Views"),
|
||||
"fieldname": "view_count",
|
||||
"fieldtype": "Float",
|
||||
"width": 200
|
||||
},
|
||||
{
|
||||
"label": _("Likes"),
|
||||
"fieldname": "like_count",
|
||||
"fieldtype": "Float",
|
||||
"width": 200
|
||||
},
|
||||
{
|
||||
"label": _("Dislikes"),
|
||||
"fieldname": "dislike_count",
|
||||
"fieldtype": "Float",
|
||||
"width": 100
|
||||
},
|
||||
{
|
||||
"label": _("Comments"),
|
||||
"fieldname": "comment_count",
|
||||
"fieldtype": "Float",
|
||||
"width": 100
|
||||
}
|
||||
{"label": _("Published Date"), "fieldname": "publish_date", "fieldtype": "Date", "width": 100},
|
||||
{"label": _("Title"), "fieldname": "title", "fieldtype": "Data", "width": 200},
|
||||
{"label": _("Duration"), "fieldname": "duration", "fieldtype": "Duration", "width": 100},
|
||||
{"label": _("Views"), "fieldname": "view_count", "fieldtype": "Float", "width": 200},
|
||||
{"label": _("Likes"), "fieldname": "like_count", "fieldtype": "Float", "width": 200},
|
||||
{"label": _("Dislikes"), "fieldname": "dislike_count", "fieldtype": "Float", "width": 100},
|
||||
{"label": _("Comments"), "fieldname": "comment_count", "fieldtype": "Float", "width": 100},
|
||||
]
|
||||
|
||||
|
||||
def get_data(filters):
|
||||
return frappe.db.sql("""
|
||||
return frappe.db.sql(
|
||||
"""
|
||||
SELECT
|
||||
publish_date, title, provider, duration,
|
||||
view_count, like_count, dislike_count, comment_count
|
||||
FROM `tabVideo`
|
||||
WHERE view_count is not null
|
||||
and publish_date between %(from_date)s and %(to_date)s
|
||||
ORDER BY view_count desc""", filters, as_dict=1)
|
||||
ORDER BY view_count desc""",
|
||||
filters,
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
|
||||
def get_chart_summary_data(data):
|
||||
labels, likes, views = [], [], []
|
||||
total_views = 0
|
||||
|
||||
for row in data:
|
||||
labels.append(row.get('title'))
|
||||
likes.append(row.get('like_count'))
|
||||
views.append(row.get('view_count'))
|
||||
total_views += flt(row.get('view_count'))
|
||||
|
||||
labels.append(row.get("title"))
|
||||
likes.append(row.get("like_count"))
|
||||
views.append(row.get("view_count"))
|
||||
total_views += flt(row.get("view_count"))
|
||||
|
||||
chart_data = {
|
||||
"data" : {
|
||||
"labels" : labels,
|
||||
"datasets" : [
|
||||
{
|
||||
"name" : "Likes",
|
||||
"values" : likes
|
||||
},
|
||||
{
|
||||
"name" : "Views",
|
||||
"values" : views
|
||||
}
|
||||
]
|
||||
"data": {
|
||||
"labels": labels,
|
||||
"datasets": [{"name": "Likes", "values": likes}, {"name": "Views", "values": views}],
|
||||
},
|
||||
"type": "bar",
|
||||
"barOptions": {
|
||||
"stacked": 1
|
||||
},
|
||||
"barOptions": {"stacked": 1},
|
||||
}
|
||||
|
||||
summary = [
|
||||
|
||||
@@ -10,7 +10,9 @@ from frappe.utils import cint, cstr, flt, get_time, now_datetime
|
||||
from erpnext.controllers.status_updater import StatusUpdater
|
||||
|
||||
|
||||
class UOMMustBeIntegerError(frappe.ValidationError): pass
|
||||
class UOMMustBeIntegerError(frappe.ValidationError):
|
||||
pass
|
||||
|
||||
|
||||
class TransactionBase(StatusUpdater):
|
||||
def validate_posting_time(self):
|
||||
@@ -18,69 +20,79 @@ class TransactionBase(StatusUpdater):
|
||||
if frappe.flags.in_import and self.posting_date:
|
||||
self.set_posting_time = 1
|
||||
|
||||
if not getattr(self, 'set_posting_time', None):
|
||||
if not getattr(self, "set_posting_time", None):
|
||||
now = now_datetime()
|
||||
self.posting_date = now.strftime('%Y-%m-%d')
|
||||
self.posting_time = now.strftime('%H:%M:%S.%f')
|
||||
self.posting_date = now.strftime("%Y-%m-%d")
|
||||
self.posting_time = now.strftime("%H:%M:%S.%f")
|
||||
elif self.posting_time:
|
||||
try:
|
||||
get_time(self.posting_time)
|
||||
except ValueError:
|
||||
frappe.throw(_('Invalid Posting Time'))
|
||||
frappe.throw(_("Invalid Posting Time"))
|
||||
|
||||
def add_calendar_event(self, opts, force=False):
|
||||
if cstr(self.contact_by) != cstr(self._prev.contact_by) or \
|
||||
cstr(self.contact_date) != cstr(self._prev.contact_date) or force or \
|
||||
(hasattr(self, "ends_on") and cstr(self.ends_on) != cstr(self._prev.ends_on)):
|
||||
if (
|
||||
cstr(self.contact_by) != cstr(self._prev.contact_by)
|
||||
or cstr(self.contact_date) != cstr(self._prev.contact_date)
|
||||
or force
|
||||
or (hasattr(self, "ends_on") and cstr(self.ends_on) != cstr(self._prev.ends_on))
|
||||
):
|
||||
|
||||
self.delete_events()
|
||||
self._add_calendar_event(opts)
|
||||
|
||||
def delete_events(self):
|
||||
participations = frappe.get_all("Event Participants", filters={"reference_doctype": self.doctype, "reference_docname": self.name,
|
||||
"parenttype": "Event"}, fields=["name", "parent"])
|
||||
participations = frappe.get_all(
|
||||
"Event Participants",
|
||||
filters={
|
||||
"reference_doctype": self.doctype,
|
||||
"reference_docname": self.name,
|
||||
"parenttype": "Event",
|
||||
},
|
||||
fields=["name", "parent"],
|
||||
)
|
||||
|
||||
if participations:
|
||||
for participation in participations:
|
||||
total_participants = frappe.get_all("Event Participants", filters={"parenttype": "Event", "parent": participation.parent})
|
||||
total_participants = frappe.get_all(
|
||||
"Event Participants", filters={"parenttype": "Event", "parent": participation.parent}
|
||||
)
|
||||
|
||||
if len(total_participants) <= 1:
|
||||
frappe.db.sql("delete from `tabEvent` where name='%s'" % participation.parent)
|
||||
|
||||
frappe.db.sql("delete from `tabEvent Participants` where name='%s'" % participation.name)
|
||||
|
||||
|
||||
def _add_calendar_event(self, opts):
|
||||
opts = frappe._dict(opts)
|
||||
|
||||
if self.contact_date:
|
||||
event = frappe.get_doc({
|
||||
"doctype": "Event",
|
||||
"owner": opts.owner or self.owner,
|
||||
"subject": opts.subject,
|
||||
"description": opts.description,
|
||||
"starts_on": self.contact_date,
|
||||
"ends_on": opts.ends_on,
|
||||
"event_type": "Private"
|
||||
})
|
||||
|
||||
event.append('event_participants', {
|
||||
"reference_doctype": self.doctype,
|
||||
"reference_docname": self.name
|
||||
event = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Event",
|
||||
"owner": opts.owner or self.owner,
|
||||
"subject": opts.subject,
|
||||
"description": opts.description,
|
||||
"starts_on": self.contact_date,
|
||||
"ends_on": opts.ends_on,
|
||||
"event_type": "Private",
|
||||
}
|
||||
)
|
||||
|
||||
event.append(
|
||||
"event_participants", {"reference_doctype": self.doctype, "reference_docname": self.name}
|
||||
)
|
||||
|
||||
event.insert(ignore_permissions=True)
|
||||
|
||||
if frappe.db.exists("User", self.contact_by):
|
||||
frappe.share.add("Event", event.name, self.contact_by,
|
||||
flags={"ignore_share_permission": True})
|
||||
frappe.share.add("Event", event.name, self.contact_by, flags={"ignore_share_permission": True})
|
||||
|
||||
def validate_uom_is_integer(self, uom_field, qty_fields):
|
||||
validate_uom_is_integer(self, uom_field, qty_fields)
|
||||
|
||||
def validate_with_previous_doc(self, ref):
|
||||
self.exclude_fields = ["conversion_factor", "uom"] if self.get('is_return') else []
|
||||
self.exclude_fields = ["conversion_factor", "uom"] if self.get("is_return") else []
|
||||
|
||||
for key, val in ref.items():
|
||||
is_child = val.get("is_child_table")
|
||||
@@ -105,8 +117,9 @@ class TransactionBase(StatusUpdater):
|
||||
def compare_values(self, ref_doc, fields, doc=None):
|
||||
for reference_doctype, ref_dn_list in ref_doc.items():
|
||||
for reference_name in ref_dn_list:
|
||||
prevdoc_values = frappe.db.get_value(reference_doctype, reference_name,
|
||||
[d[0] for d in fields], as_dict=1)
|
||||
prevdoc_values = frappe.db.get_value(
|
||||
reference_doctype, reference_name, [d[0] for d in fields], as_dict=1
|
||||
)
|
||||
|
||||
if not prevdoc_values:
|
||||
frappe.throw(_("Invalid reference {0} {1}").format(reference_doctype, reference_name))
|
||||
@@ -115,7 +128,6 @@ class TransactionBase(StatusUpdater):
|
||||
if prevdoc_values[field] is not None and field not in self.exclude_fields:
|
||||
self.validate_value(field, condition, prevdoc_values[field], doc)
|
||||
|
||||
|
||||
def validate_rate_with_reference_doc(self, ref_details):
|
||||
buying_doctypes = ["Purchase Order", "Purchase Invoice", "Purchase Receipt"]
|
||||
|
||||
@@ -131,17 +143,26 @@ class TransactionBase(StatusUpdater):
|
||||
if d.get(ref_link_field):
|
||||
ref_rate = frappe.db.get_value(ref_dt + " Item", d.get(ref_link_field), "rate")
|
||||
|
||||
if abs(flt(d.rate - ref_rate, d.precision("rate"))) >= .01:
|
||||
if abs(flt(d.rate - ref_rate, d.precision("rate"))) >= 0.01:
|
||||
if action == "Stop":
|
||||
role_allowed_to_override = frappe.db.get_single_value(settings_doc, 'role_to_override_stop_action')
|
||||
role_allowed_to_override = frappe.db.get_single_value(
|
||||
settings_doc, "role_to_override_stop_action"
|
||||
)
|
||||
|
||||
if role_allowed_to_override not in frappe.get_roles():
|
||||
frappe.throw(_("Row #{0}: Rate must be same as {1}: {2} ({3} / {4})").format(
|
||||
d.idx, ref_dt, d.get(ref_dn_field), d.rate, ref_rate))
|
||||
frappe.throw(
|
||||
_("Row #{0}: Rate must be same as {1}: {2} ({3} / {4})").format(
|
||||
d.idx, ref_dt, d.get(ref_dn_field), d.rate, ref_rate
|
||||
)
|
||||
)
|
||||
else:
|
||||
frappe.msgprint(_("Row #{0}: Rate must be same as {1}: {2} ({3} / {4})").format(
|
||||
d.idx, ref_dt, d.get(ref_dn_field), d.rate, ref_rate), title=_("Warning"), indicator="orange")
|
||||
|
||||
frappe.msgprint(
|
||||
_("Row #{0}: Rate must be same as {1}: {2} ({3} / {4})").format(
|
||||
d.idx, ref_dt, d.get(ref_dn_field), d.rate, ref_rate
|
||||
),
|
||||
title=_("Warning"),
|
||||
indicator="orange",
|
||||
)
|
||||
|
||||
def get_link_filters(self, for_doctype):
|
||||
if hasattr(self, "prev_link_mapper") and self.prev_link_mapper.get(for_doctype):
|
||||
@@ -150,11 +171,7 @@ class TransactionBase(StatusUpdater):
|
||||
values = filter(None, tuple(item.as_dict()[fieldname] for item in self.items))
|
||||
|
||||
if values:
|
||||
ret = {
|
||||
for_doctype : {
|
||||
"filters": [[for_doctype, "name", "in", values]]
|
||||
}
|
||||
}
|
||||
ret = {for_doctype: {"filters": [[for_doctype, "name", "in", values]]}}
|
||||
else:
|
||||
ret = None
|
||||
else:
|
||||
@@ -163,17 +180,17 @@ class TransactionBase(StatusUpdater):
|
||||
return ret
|
||||
|
||||
def reset_default_field_value(self, default_field: str, child_table: str, child_table_field: str):
|
||||
""" Reset "Set default X" fields on forms to avoid confusion.
|
||||
"""Reset "Set default X" fields on forms to avoid confusion.
|
||||
|
||||
example:
|
||||
doc = {
|
||||
"set_from_warehouse": "Warehouse A",
|
||||
"items": [{"from_warehouse": "warehouse B"}, {"from_warehouse": "warehouse A"}],
|
||||
}
|
||||
Since this has dissimilar values in child table, the default field will be erased.
|
||||
example:
|
||||
doc = {
|
||||
"set_from_warehouse": "Warehouse A",
|
||||
"items": [{"from_warehouse": "warehouse B"}, {"from_warehouse": "warehouse A"}],
|
||||
}
|
||||
Since this has dissimilar values in child table, the default field will be erased.
|
||||
|
||||
doc.reset_default_field_value("set_from_warehouse", "items", "from_warehouse")
|
||||
"""
|
||||
doc.reset_default_field_value("set_from_warehouse", "items", "from_warehouse")
|
||||
"""
|
||||
child_table_values = set()
|
||||
|
||||
for row in self.get(child_table):
|
||||
@@ -182,8 +199,11 @@ class TransactionBase(StatusUpdater):
|
||||
if len(child_table_values) > 1:
|
||||
self.set(default_field, None)
|
||||
|
||||
|
||||
def delete_events(ref_type, ref_name):
|
||||
events = frappe.db.sql_list(""" SELECT
|
||||
events = (
|
||||
frappe.db.sql_list(
|
||||
""" SELECT
|
||||
distinct `tabEvent`.name
|
||||
from
|
||||
`tabEvent`, `tabEvent Participants`
|
||||
@@ -191,18 +211,27 @@ def delete_events(ref_type, ref_name):
|
||||
`tabEvent`.name = `tabEvent Participants`.parent
|
||||
and `tabEvent Participants`.reference_doctype = %s
|
||||
and `tabEvent Participants`.reference_docname = %s
|
||||
""", (ref_type, ref_name)) or []
|
||||
""",
|
||||
(ref_type, ref_name),
|
||||
)
|
||||
or []
|
||||
)
|
||||
|
||||
if events:
|
||||
frappe.delete_doc("Event", events, for_reload=True)
|
||||
|
||||
|
||||
def validate_uom_is_integer(doc, uom_field, qty_fields, child_dt=None):
|
||||
if isinstance(qty_fields, str):
|
||||
qty_fields = [qty_fields]
|
||||
|
||||
distinct_uoms = list(set(d.get(uom_field) for d in doc.get_all_children()))
|
||||
integer_uoms = list(filter(lambda uom: frappe.db.get_value("UOM", uom,
|
||||
"must_be_whole_number", cache=True) or None, distinct_uoms))
|
||||
integer_uoms = list(
|
||||
filter(
|
||||
lambda uom: frappe.db.get_value("UOM", uom, "must_be_whole_number", cache=True) or None,
|
||||
distinct_uoms,
|
||||
)
|
||||
)
|
||||
|
||||
if not integer_uoms:
|
||||
return
|
||||
@@ -213,6 +242,11 @@ def validate_uom_is_integer(doc, uom_field, qty_fields, child_dt=None):
|
||||
qty = d.get(f)
|
||||
if qty:
|
||||
if abs(cint(qty) - flt(qty)) > 0.0000001:
|
||||
frappe.throw(_("Row {1}: Quantity ({0}) cannot be a fraction. To allow this, disable '{2}' in UOM {3}.") \
|
||||
.format(qty, d.idx, frappe.bold(_("Must be Whole Number")), frappe.bold(d.get(uom_field))),
|
||||
UOMMustBeIntegerError)
|
||||
frappe.throw(
|
||||
_(
|
||||
"Row {1}: Quantity ({0}) cannot be a fraction. To allow this, disable '{2}' in UOM {3}."
|
||||
).format(
|
||||
qty, d.idx, frappe.bold(_("Must be Whole Number")), frappe.bold(d.get(uom_field))
|
||||
),
|
||||
UOMMustBeIntegerError,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user