style: format code with black

This commit is contained in:
Ankush Menat
2022-03-28 18:52:46 +05:30
parent 21e00da3d6
commit 494bd9ef78
1395 changed files with 91704 additions and 62532 deletions

View File

@@ -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()}

View File

@@ -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:

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -5,5 +5,6 @@ import unittest
# test_records = frappe.get_test_records('SMS Log')
class TestSMSLog(unittest.TestCase):
pass

View File

@@ -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:

View File

@@ -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"))

View File

@@ -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

View File

@@ -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

View File

@@ -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 = [

View File

@@ -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,
)