mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-31 23:33:43 +00:00
style: bulk format code with black
v13 port because otherwise backports will result in conflicts always
This commit is contained in:
@@ -1,57 +1,48 @@
|
||||
|
||||
from frappe import _
|
||||
|
||||
doctype_rule_map = {
|
||||
'Item': {
|
||||
'points': 5,
|
||||
'for_doc_event': 'New'
|
||||
"Item": {"points": 5, "for_doc_event": "New"},
|
||||
"Customer": {"points": 5, "for_doc_event": "New"},
|
||||
"Supplier": {"points": 5, "for_doc_event": "New"},
|
||||
"Lead": {"points": 2, "for_doc_event": "New"},
|
||||
"Opportunity": {
|
||||
"points": 10,
|
||||
"for_doc_event": "Custom",
|
||||
"condition": 'doc.status=="Converted"',
|
||||
"rule_name": _("On Converting Opportunity"),
|
||||
"user_field": "converted_by",
|
||||
},
|
||||
'Customer': {
|
||||
'points': 5,
|
||||
'for_doc_event': 'New'
|
||||
"Sales Order": {
|
||||
"points": 10,
|
||||
"for_doc_event": "Submit",
|
||||
"rule_name": _("On Sales Order Submission"),
|
||||
"user_field": "modified_by",
|
||||
},
|
||||
'Supplier': {
|
||||
'points': 5,
|
||||
'for_doc_event': 'New'
|
||||
"Purchase Order": {
|
||||
"points": 10,
|
||||
"for_doc_event": "Submit",
|
||||
"rule_name": _("On Purchase Order Submission"),
|
||||
"user_field": "modified_by",
|
||||
},
|
||||
'Lead': {
|
||||
'points': 2,
|
||||
'for_doc_event': 'New'
|
||||
"Task": {
|
||||
"points": 5,
|
||||
"condition": 'doc.status == "Completed"',
|
||||
"rule_name": _("On Task Completion"),
|
||||
"user_field": "completed_by",
|
||||
},
|
||||
'Opportunity': {
|
||||
'points': 10,
|
||||
'for_doc_event': 'Custom',
|
||||
'condition': 'doc.status=="Converted"',
|
||||
'rule_name': _('On Converting Opportunity'),
|
||||
'user_field': 'converted_by'
|
||||
},
|
||||
'Sales Order': {
|
||||
'points': 10,
|
||||
'for_doc_event': 'Submit',
|
||||
'rule_name': _('On Sales Order Submission'),
|
||||
'user_field': 'modified_by'
|
||||
},
|
||||
'Purchase Order': {
|
||||
'points': 10,
|
||||
'for_doc_event': 'Submit',
|
||||
'rule_name': _('On Purchase Order Submission'),
|
||||
'user_field': 'modified_by'
|
||||
},
|
||||
'Task': {
|
||||
'points': 5,
|
||||
'condition': 'doc.status == "Completed"',
|
||||
'rule_name': _('On Task Completion'),
|
||||
'user_field': 'completed_by'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def get_default_energy_point_rules():
|
||||
return [{
|
||||
'doctype': 'Energy Point Rule',
|
||||
'reference_doctype': doctype,
|
||||
'for_doc_event': rule.get('for_doc_event') or 'Custom',
|
||||
'condition': rule.get('condition'),
|
||||
'rule_name': rule.get('rule_name') or _('On {0} Creation').format(doctype),
|
||||
'points': rule.get('points'),
|
||||
'user_field': rule.get('user_field') or 'owner'
|
||||
} for doctype, rule in doctype_rule_map.items()]
|
||||
return [
|
||||
{
|
||||
"doctype": "Energy Point Rule",
|
||||
"reference_doctype": doctype,
|
||||
"for_doc_event": rule.get("for_doc_event") or "Custom",
|
||||
"condition": rule.get("condition"),
|
||||
"rule_name": rule.get("rule_name") or _("On {0} Creation").format(doctype),
|
||||
"points": rule.get("points"),
|
||||
"user_field": rule.get("user_field") or "owner",
|
||||
}
|
||||
for doctype, rule in doctype_rule_map.items()
|
||||
]
|
||||
|
||||
@@ -1,26 +1,31 @@
|
||||
|
||||
from frappe import _
|
||||
|
||||
doctype_list = [
|
||||
'Purchase Receipt',
|
||||
'Purchase Invoice',
|
||||
'Quotation',
|
||||
'Sales Order',
|
||||
'Delivery Note',
|
||||
'Sales Invoice'
|
||||
"Purchase Receipt",
|
||||
"Purchase Invoice",
|
||||
"Quotation",
|
||||
"Sales Order",
|
||||
"Delivery Note",
|
||||
"Sales Invoice",
|
||||
]
|
||||
|
||||
|
||||
def get_message(doctype):
|
||||
return _("{0} has been submitted successfully").format(_(doctype))
|
||||
|
||||
|
||||
def get_first_success_message(doctype):
|
||||
return get_message(doctype)
|
||||
|
||||
|
||||
def get_default_success_action():
|
||||
return [{
|
||||
'doctype': 'Success Action',
|
||||
'ref_doctype': doctype,
|
||||
'message': get_message(doctype),
|
||||
'first_success_message': get_first_success_message(doctype),
|
||||
'next_actions': 'new\nprint\nemail'
|
||||
} for doctype in doctype_list]
|
||||
return [
|
||||
{
|
||||
"doctype": "Success Action",
|
||||
"ref_doctype": doctype,
|
||||
"message": get_message(doctype),
|
||||
"first_success_message": get_first_success_message(doctype),
|
||||
"next_actions": "new\nprint\nemail",
|
||||
}
|
||||
for doctype in doctype_list
|
||||
]
|
||||
|
||||
@@ -12,90 +12,121 @@ from erpnext.utilities.transaction_base import TransactionBase
|
||||
class AuthorizationControl(TransactionBase):
|
||||
def get_appr_user_role(self, det, doctype_name, total, based_on, condition, item, company):
|
||||
amt_list, appr_users, appr_roles = [], [], []
|
||||
users, roles = '',''
|
||||
users, roles = "", ""
|
||||
if det:
|
||||
for x in det:
|
||||
amt_list.append(flt(x[0]))
|
||||
max_amount = max(amt_list)
|
||||
|
||||
app_dtl = frappe.db.sql("""select approving_user, approving_role from `tabAuthorization Rule`
|
||||
app_dtl = frappe.db.sql(
|
||||
"""select approving_user, approving_role from `tabAuthorization Rule`
|
||||
where transaction = %s and (value = %s or value > %s)
|
||||
and docstatus != 2 and based_on = %s and company = %s %s""" %
|
||||
('%s', '%s', '%s', '%s', '%s', condition),
|
||||
(doctype_name, flt(max_amount), total, based_on, company))
|
||||
and docstatus != 2 and based_on = %s and company = %s %s"""
|
||||
% ("%s", "%s", "%s", "%s", "%s", condition),
|
||||
(doctype_name, flt(max_amount), total, based_on, company),
|
||||
)
|
||||
|
||||
if not app_dtl:
|
||||
app_dtl = frappe.db.sql("""select approving_user, approving_role from `tabAuthorization Rule`
|
||||
app_dtl = frappe.db.sql(
|
||||
"""select approving_user, approving_role from `tabAuthorization Rule`
|
||||
where transaction = %s and (value = %s or value > %s) and docstatus != 2
|
||||
and based_on = %s and ifnull(company,'') = '' %s""" %
|
||||
('%s', '%s', '%s', '%s', condition), (doctype_name, flt(max_amount), total, based_on))
|
||||
and based_on = %s and ifnull(company,'') = '' %s"""
|
||||
% ("%s", "%s", "%s", "%s", condition),
|
||||
(doctype_name, flt(max_amount), total, based_on),
|
||||
)
|
||||
|
||||
for d in app_dtl:
|
||||
if(d[0]): appr_users.append(d[0])
|
||||
if(d[1]): appr_roles.append(d[1])
|
||||
if d[0]:
|
||||
appr_users.append(d[0])
|
||||
if d[1]:
|
||||
appr_roles.append(d[1])
|
||||
|
||||
if not has_common(appr_roles, frappe.get_roles()) and not has_common(appr_users, [session['user']]):
|
||||
if not has_common(appr_roles, frappe.get_roles()) and not has_common(
|
||||
appr_users, [session["user"]]
|
||||
):
|
||||
frappe.msgprint(_("Not authroized since {0} exceeds limits").format(_(based_on)))
|
||||
frappe.throw(_("Can be approved by {0}").format(comma_or(appr_roles + appr_users)))
|
||||
|
||||
def validate_auth_rule(self, doctype_name, total, based_on, cond, company, item = ''):
|
||||
def validate_auth_rule(self, doctype_name, total, based_on, cond, company, item=""):
|
||||
chk = 1
|
||||
add_cond1,add_cond2 = '',''
|
||||
if based_on == 'Itemwise Discount':
|
||||
add_cond1, add_cond2 = "", ""
|
||||
if based_on == "Itemwise Discount":
|
||||
add_cond1 += " and master_name = " + frappe.db.escape(cstr(item))
|
||||
itemwise_exists = frappe.db.sql("""select value from `tabAuthorization Rule`
|
||||
itemwise_exists = frappe.db.sql(
|
||||
"""select value from `tabAuthorization Rule`
|
||||
where transaction = %s and value <= %s
|
||||
and based_on = %s and company = %s and docstatus != 2 %s %s""" %
|
||||
('%s', '%s', '%s', '%s', cond, add_cond1), (doctype_name, total, based_on, company))
|
||||
and based_on = %s and company = %s and docstatus != 2 %s %s"""
|
||||
% ("%s", "%s", "%s", "%s", cond, add_cond1),
|
||||
(doctype_name, total, based_on, company),
|
||||
)
|
||||
|
||||
if not itemwise_exists:
|
||||
itemwise_exists = frappe.db.sql("""select value from `tabAuthorization Rule`
|
||||
itemwise_exists = frappe.db.sql(
|
||||
"""select value from `tabAuthorization Rule`
|
||||
where transaction = %s and value <= %s and based_on = %s
|
||||
and ifnull(company,'') = '' and docstatus != 2 %s %s""" %
|
||||
('%s', '%s', '%s', cond, add_cond1), (doctype_name, total, based_on))
|
||||
and ifnull(company,'') = '' and docstatus != 2 %s %s"""
|
||||
% ("%s", "%s", "%s", cond, add_cond1),
|
||||
(doctype_name, total, based_on),
|
||||
)
|
||||
|
||||
if itemwise_exists:
|
||||
self.get_appr_user_role(itemwise_exists, doctype_name, total, based_on, cond+add_cond1, item,company)
|
||||
self.get_appr_user_role(
|
||||
itemwise_exists, doctype_name, total, based_on, cond + add_cond1, item, company
|
||||
)
|
||||
chk = 0
|
||||
if chk == 1:
|
||||
if based_on == 'Itemwise Discount':
|
||||
if based_on == "Itemwise Discount":
|
||||
add_cond2 += " and ifnull(master_name,'') = ''"
|
||||
|
||||
appr = frappe.db.sql("""select value from `tabAuthorization Rule`
|
||||
appr = frappe.db.sql(
|
||||
"""select value from `tabAuthorization Rule`
|
||||
where transaction = %s and value <= %s and based_on = %s
|
||||
and company = %s and docstatus != 2 %s %s""" %
|
||||
('%s', '%s', '%s', '%s', cond, add_cond2), (doctype_name, total, based_on, company))
|
||||
and company = %s and docstatus != 2 %s %s"""
|
||||
% ("%s", "%s", "%s", "%s", cond, add_cond2),
|
||||
(doctype_name, total, based_on, company),
|
||||
)
|
||||
|
||||
if not appr:
|
||||
appr = frappe.db.sql("""select value from `tabAuthorization Rule`
|
||||
appr = frappe.db.sql(
|
||||
"""select value from `tabAuthorization Rule`
|
||||
where transaction = %s and value <= %s and based_on = %s
|
||||
and ifnull(company,'') = '' and docstatus != 2 %s %s""" %
|
||||
('%s', '%s', '%s', cond, add_cond2), (doctype_name, total, based_on))
|
||||
and ifnull(company,'') = '' and docstatus != 2 %s %s"""
|
||||
% ("%s", "%s", "%s", cond, add_cond2),
|
||||
(doctype_name, total, based_on),
|
||||
)
|
||||
|
||||
self.get_appr_user_role(appr, doctype_name, total, based_on, cond+add_cond2, item, company)
|
||||
self.get_appr_user_role(appr, doctype_name, total, based_on, cond + add_cond2, item, company)
|
||||
|
||||
def bifurcate_based_on_type(self, doctype_name, total, av_dis, based_on, doc_obj, val, company):
|
||||
add_cond = ''
|
||||
add_cond = ""
|
||||
auth_value = av_dis
|
||||
|
||||
if val == 1: add_cond += " and system_user = {}".format(frappe.db.escape(session['user']))
|
||||
elif val == 2: add_cond += " and system_role IN %s" % ("('"+"','".join(frappe.get_roles())+"')")
|
||||
else: add_cond += " and ifnull(system_user,'') = '' and ifnull(system_role,'') = ''"
|
||||
if val == 1:
|
||||
add_cond += " and system_user = {}".format(frappe.db.escape(session["user"]))
|
||||
elif val == 2:
|
||||
add_cond += " and system_role IN %s" % ("('" + "','".join(frappe.get_roles()) + "')")
|
||||
else:
|
||||
add_cond += " and ifnull(system_user,'') = '' and ifnull(system_role,'') = ''"
|
||||
|
||||
if based_on == 'Grand Total': auth_value = total
|
||||
elif based_on == 'Customerwise Discount':
|
||||
if based_on == "Grand Total":
|
||||
auth_value = total
|
||||
elif based_on == "Customerwise Discount":
|
||||
if doc_obj:
|
||||
if doc_obj.doctype == 'Sales Invoice': customer = doc_obj.customer
|
||||
else: customer = doc_obj.customer_name
|
||||
if doc_obj.doctype == "Sales Invoice":
|
||||
customer = doc_obj.customer
|
||||
else:
|
||||
customer = doc_obj.customer_name
|
||||
add_cond = " and master_name = {}".format(frappe.db.escape(customer))
|
||||
if based_on == 'Itemwise Discount':
|
||||
if based_on == "Itemwise Discount":
|
||||
if doc_obj:
|
||||
for t in doc_obj.get("items"):
|
||||
self.validate_auth_rule(doctype_name, t.discount_percentage, based_on, add_cond, company,t.item_code )
|
||||
self.validate_auth_rule(
|
||||
doctype_name, t.discount_percentage, based_on, add_cond, company, t.item_code
|
||||
)
|
||||
else:
|
||||
self.validate_auth_rule(doctype_name, auth_value, based_on, add_cond, company)
|
||||
|
||||
def validate_approving_authority(self, doctype_name,company, total, doc_obj = ''):
|
||||
def validate_approving_authority(self, doctype_name, company, total, doc_obj=""):
|
||||
if not frappe.db.count("Authorization Rule"):
|
||||
return
|
||||
|
||||
@@ -109,56 +140,85 @@ class AuthorizationControl(TransactionBase):
|
||||
if doc_obj.get("discount_amount"):
|
||||
base_rate -= flt(doc_obj.discount_amount)
|
||||
|
||||
if price_list_rate: av_dis = 100 - flt(base_rate * 100 / price_list_rate)
|
||||
if price_list_rate:
|
||||
av_dis = 100 - flt(base_rate * 100 / price_list_rate)
|
||||
|
||||
final_based_on = ['Grand Total','Average Discount','Customerwise Discount','Itemwise Discount']
|
||||
final_based_on = [
|
||||
"Grand Total",
|
||||
"Average Discount",
|
||||
"Customerwise Discount",
|
||||
"Itemwise Discount",
|
||||
]
|
||||
|
||||
# Check for authorization set for individual user
|
||||
based_on = [x[0] for x in frappe.db.sql("""select distinct based_on from `tabAuthorization Rule`
|
||||
based_on = [
|
||||
x[0]
|
||||
for x in frappe.db.sql(
|
||||
"""select distinct based_on from `tabAuthorization Rule`
|
||||
where transaction = %s and system_user = %s
|
||||
and (company = %s or ifnull(company,'')='') and docstatus != 2""",
|
||||
(doctype_name, session['user'], company))]
|
||||
(doctype_name, session["user"], company),
|
||||
)
|
||||
]
|
||||
|
||||
for d in based_on:
|
||||
self.bifurcate_based_on_type(doctype_name, total, av_dis, d, doc_obj, 1, company)
|
||||
|
||||
# Remove user specific rules from global authorization rules
|
||||
for r in based_on:
|
||||
if r in final_based_on and r != 'Itemwise Discount': final_based_on.remove(r)
|
||||
if r in final_based_on and r != "Itemwise Discount":
|
||||
final_based_on.remove(r)
|
||||
|
||||
# Check for authorization set on particular roles
|
||||
based_on = [x[0] for x in frappe.db.sql("""select based_on
|
||||
based_on = [
|
||||
x[0]
|
||||
for x in frappe.db.sql(
|
||||
"""select based_on
|
||||
from `tabAuthorization Rule`
|
||||
where transaction = %s and system_role IN (%s) and based_on IN (%s)
|
||||
and (company = %s or ifnull(company,'')='')
|
||||
and docstatus != 2
|
||||
""" % ('%s', "'"+"','".join(frappe.get_roles())+"'", "'"+"','".join(final_based_on)+"'", '%s'), (doctype_name, company))]
|
||||
"""
|
||||
% (
|
||||
"%s",
|
||||
"'" + "','".join(frappe.get_roles()) + "'",
|
||||
"'" + "','".join(final_based_on) + "'",
|
||||
"%s",
|
||||
),
|
||||
(doctype_name, company),
|
||||
)
|
||||
]
|
||||
|
||||
for d in based_on:
|
||||
self.bifurcate_based_on_type(doctype_name, total, av_dis, d, doc_obj, 2, company)
|
||||
|
||||
# Remove role specific rules from global authorization rules
|
||||
for r in based_on:
|
||||
if r in final_based_on and r != 'Itemwise Discount': final_based_on.remove(r)
|
||||
if r in final_based_on and r != "Itemwise Discount":
|
||||
final_based_on.remove(r)
|
||||
|
||||
# Check for global authorization
|
||||
for g in final_based_on:
|
||||
self.bifurcate_based_on_type(doctype_name, total, av_dis, g, doc_obj, 0, company)
|
||||
|
||||
def get_value_based_rule(self,doctype_name,employee,total_claimed_amount,company):
|
||||
val_lst =[]
|
||||
val = frappe.db.sql("""select value from `tabAuthorization Rule`
|
||||
def get_value_based_rule(self, doctype_name, employee, total_claimed_amount, company):
|
||||
val_lst = []
|
||||
val = frappe.db.sql(
|
||||
"""select value from `tabAuthorization Rule`
|
||||
where transaction=%s and (to_emp=%s or
|
||||
to_designation IN (select designation from `tabEmployee` where name=%s))
|
||||
and ifnull(value,0)< %s and company = %s and docstatus!=2""",
|
||||
(doctype_name,employee,employee,total_claimed_amount,company))
|
||||
(doctype_name, employee, employee, total_claimed_amount, company),
|
||||
)
|
||||
|
||||
if not val:
|
||||
val = frappe.db.sql("""select value from `tabAuthorization Rule`
|
||||
val = frappe.db.sql(
|
||||
"""select value from `tabAuthorization Rule`
|
||||
where transaction=%s and (to_emp=%s or
|
||||
to_designation IN (select designation from `tabEmployee` where name=%s))
|
||||
and ifnull(value,0)< %s and ifnull(company,'') = '' and docstatus!=2""",
|
||||
(doctype_name, employee, employee, total_claimed_amount))
|
||||
(doctype_name, employee, employee, total_claimed_amount),
|
||||
)
|
||||
|
||||
if val:
|
||||
val_lst = [y[0] for y in val]
|
||||
@@ -166,64 +226,83 @@ class AuthorizationControl(TransactionBase):
|
||||
val_lst.append(0)
|
||||
|
||||
max_val = max(val_lst)
|
||||
rule = frappe.db.sql("""select name, to_emp, to_designation, approving_role, approving_user
|
||||
rule = frappe.db.sql(
|
||||
"""select name, to_emp, to_designation, approving_role, approving_user
|
||||
from `tabAuthorization Rule`
|
||||
where transaction=%s and company = %s
|
||||
and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s))
|
||||
and ifnull(value,0)= %s and docstatus!=2""",
|
||||
(doctype_name,company,employee,employee,flt(max_val)), as_dict=1)
|
||||
(doctype_name, company, employee, employee, flt(max_val)),
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
if not rule:
|
||||
rule = frappe.db.sql("""select name, to_emp, to_designation, approving_role, approving_user
|
||||
rule = frappe.db.sql(
|
||||
"""select name, to_emp, to_designation, approving_role, approving_user
|
||||
from `tabAuthorization Rule`
|
||||
where transaction=%s and ifnull(company,'') = ''
|
||||
and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s))
|
||||
and ifnull(value,0)= %s and docstatus!=2""",
|
||||
(doctype_name,employee,employee,flt(max_val)), as_dict=1)
|
||||
(doctype_name, employee, employee, flt(max_val)),
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
return rule
|
||||
|
||||
# related to payroll module only
|
||||
def get_approver_name(self, doctype_name, total, doc_obj=''):
|
||||
app_user=[]
|
||||
app_specific_user =[]
|
||||
rule ={}
|
||||
def get_approver_name(self, doctype_name, total, doc_obj=""):
|
||||
app_user = []
|
||||
app_specific_user = []
|
||||
rule = {}
|
||||
|
||||
if doc_obj:
|
||||
if doctype_name == 'Expense Claim':
|
||||
rule = self.get_value_based_rule(doctype_name, doc_obj.employee,
|
||||
doc_obj.total_claimed_amount, doc_obj.company)
|
||||
elif doctype_name == 'Appraisal':
|
||||
rule = frappe.db.sql("""select name, to_emp, to_designation, approving_role, approving_user
|
||||
if doctype_name == "Expense Claim":
|
||||
rule = self.get_value_based_rule(
|
||||
doctype_name, doc_obj.employee, doc_obj.total_claimed_amount, doc_obj.company
|
||||
)
|
||||
elif doctype_name == "Appraisal":
|
||||
rule = frappe.db.sql(
|
||||
"""select name, to_emp, to_designation, approving_role, approving_user
|
||||
from `tabAuthorization Rule` where transaction=%s
|
||||
and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s))
|
||||
and company = %s and docstatus!=2""",
|
||||
(doctype_name,doc_obj.employee, doc_obj.employee, doc_obj.company),as_dict=1)
|
||||
(doctype_name, doc_obj.employee, doc_obj.employee, doc_obj.company),
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
if not rule:
|
||||
rule = frappe.db.sql("""select name, to_emp, to_designation, approving_role, approving_user
|
||||
rule = frappe.db.sql(
|
||||
"""select name, to_emp, to_designation, approving_role, approving_user
|
||||
from `tabAuthorization Rule`
|
||||
where transaction=%s and (to_emp=%s or
|
||||
to_designation IN (select designation from `tabEmployee` where name=%s))
|
||||
and ifnull(company,'') = '' and docstatus!=2""",
|
||||
(doctype_name,doc_obj.employee, doc_obj.employee), as_dict=1)
|
||||
(doctype_name, doc_obj.employee, doc_obj.employee),
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
if rule:
|
||||
for m in rule:
|
||||
if m['to_emp'] or m['to_designation']:
|
||||
if m['approving_user']:
|
||||
app_specific_user.append(m['approving_user'])
|
||||
elif m['approving_role']:
|
||||
user_lst = [z[0] for z in frappe.db.sql("""select distinct t1.name
|
||||
if m["to_emp"] or m["to_designation"]:
|
||||
if m["approving_user"]:
|
||||
app_specific_user.append(m["approving_user"])
|
||||
elif m["approving_role"]:
|
||||
user_lst = [
|
||||
z[0]
|
||||
for z in frappe.db.sql(
|
||||
"""select distinct t1.name
|
||||
from `tabUser` t1, `tabHas Role` t2 where t2.role=%s
|
||||
and t2.parent=t1.name and t1.name !='Administrator'
|
||||
and t1.name != 'Guest' and t1.docstatus !=2""", m['approving_role'])]
|
||||
and t1.name != 'Guest' and t1.docstatus !=2""",
|
||||
m["approving_role"],
|
||||
)
|
||||
]
|
||||
|
||||
for x in user_lst:
|
||||
if not x in app_user:
|
||||
app_user.append(x)
|
||||
|
||||
if len(app_specific_user) >0:
|
||||
if len(app_specific_user) > 0:
|
||||
return app_specific_user
|
||||
else:
|
||||
return app_user
|
||||
|
||||
@@ -10,40 +10,58 @@ from frappe.utils import cstr, flt
|
||||
|
||||
class AuthorizationRule(Document):
|
||||
def check_duplicate_entry(self):
|
||||
exists = frappe.db.sql("""select name, docstatus from `tabAuthorization Rule`
|
||||
exists = frappe.db.sql(
|
||||
"""select name, docstatus from `tabAuthorization Rule`
|
||||
where transaction = %s and based_on = %s and system_user = %s
|
||||
and system_role = %s and approving_user = %s and approving_role = %s
|
||||
and to_emp =%s and to_designation=%s and name != %s""",
|
||||
(self.transaction, self.based_on, cstr(self.system_user),
|
||||
cstr(self.system_role), cstr(self.approving_user),
|
||||
cstr(self.approving_role), cstr(self.to_emp),
|
||||
cstr(self.to_designation), self.name))
|
||||
auth_exists = exists and exists[0][0] or ''
|
||||
(
|
||||
self.transaction,
|
||||
self.based_on,
|
||||
cstr(self.system_user),
|
||||
cstr(self.system_role),
|
||||
cstr(self.approving_user),
|
||||
cstr(self.approving_role),
|
||||
cstr(self.to_emp),
|
||||
cstr(self.to_designation),
|
||||
self.name,
|
||||
),
|
||||
)
|
||||
auth_exists = exists and exists[0][0] or ""
|
||||
if auth_exists:
|
||||
frappe.throw(_("Duplicate Entry. Please check Authorization Rule {0}").format(auth_exists))
|
||||
|
||||
|
||||
def validate_rule(self):
|
||||
if self.transaction != 'Appraisal':
|
||||
if self.transaction != "Appraisal":
|
||||
if not self.approving_role and not self.approving_user:
|
||||
frappe.throw(_("Please enter Approving Role or Approving User"))
|
||||
elif self.system_user and self.system_user == self.approving_user:
|
||||
frappe.throw(_("Approving User cannot be same as user the rule is Applicable To"))
|
||||
elif self.system_role and self.system_role == self.approving_role:
|
||||
frappe.throw(_("Approving Role cannot be same as role the rule is Applicable To"))
|
||||
elif self.transaction in ['Purchase Order', 'Purchase Receipt', \
|
||||
'Purchase Invoice', 'Stock Entry'] and self.based_on \
|
||||
in ['Average Discount', 'Customerwise Discount', 'Itemwise Discount']:
|
||||
frappe.throw(_("Cannot set authorization on basis of Discount for {0}").format(self.transaction))
|
||||
elif self.based_on == 'Average Discount' and flt(self.value) > 100.00:
|
||||
elif self.transaction in [
|
||||
"Purchase Order",
|
||||
"Purchase Receipt",
|
||||
"Purchase Invoice",
|
||||
"Stock Entry",
|
||||
] and self.based_on in [
|
||||
"Average Discount",
|
||||
"Customerwise Discount",
|
||||
"Itemwise Discount",
|
||||
]:
|
||||
frappe.throw(
|
||||
_("Cannot set authorization on basis of Discount for {0}").format(self.transaction)
|
||||
)
|
||||
elif self.based_on == "Average Discount" and flt(self.value) > 100.00:
|
||||
frappe.throw(_("Discount must be less than 100"))
|
||||
elif self.based_on == 'Customerwise Discount' and not self.master_name:
|
||||
elif self.based_on == "Customerwise Discount" and not self.master_name:
|
||||
frappe.throw(_("Customer required for 'Customerwise Discount'"))
|
||||
else:
|
||||
if self.transaction == 'Appraisal':
|
||||
if self.transaction == "Appraisal":
|
||||
self.based_on = "Not Applicable"
|
||||
|
||||
def validate(self):
|
||||
self.check_duplicate_entry()
|
||||
self.validate_rule()
|
||||
if not self.value: self.value = 0.0
|
||||
if not self.value:
|
||||
self.value = 0.0
|
||||
|
||||
@@ -5,5 +5,6 @@ import unittest
|
||||
|
||||
# test_records = frappe.get_test_records('Authorization Rule')
|
||||
|
||||
|
||||
class TestAuthorizationRule(unittest.TestCase):
|
||||
pass
|
||||
|
||||
@@ -11,6 +11,7 @@ from frappe.model.document import Document
|
||||
class Brand(Document):
|
||||
pass
|
||||
|
||||
|
||||
def get_brand_defaults(item, company):
|
||||
item = frappe.get_cached_doc("Item", item)
|
||||
if item.brand:
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
import frappe
|
||||
|
||||
test_records = frappe.get_test_records('Brand')
|
||||
test_records = frappe.get_test_records("Brand")
|
||||
|
||||
@@ -21,7 +21,7 @@ from erpnext.setup.setup_wizard.operations.taxes_setup import setup_taxes_and_ch
|
||||
|
||||
|
||||
class Company(NestedSet):
|
||||
nsm_parent_field = 'parent_company'
|
||||
nsm_parent_field = "parent_company"
|
||||
|
||||
def onload(self):
|
||||
load_address_and_contact(self, "company")
|
||||
@@ -29,12 +29,24 @@ class Company(NestedSet):
|
||||
@frappe.whitelist()
|
||||
def check_if_transactions_exist(self):
|
||||
exists = False
|
||||
for doctype in ["Sales Invoice", "Delivery Note", "Sales Order", "Quotation",
|
||||
"Purchase Invoice", "Purchase Receipt", "Purchase Order", "Supplier Quotation"]:
|
||||
if frappe.db.sql("""select name from `tab%s` where company=%s and docstatus=1
|
||||
limit 1""" % (doctype, "%s"), self.name):
|
||||
exists = True
|
||||
break
|
||||
for doctype in [
|
||||
"Sales Invoice",
|
||||
"Delivery Note",
|
||||
"Sales Order",
|
||||
"Quotation",
|
||||
"Purchase Invoice",
|
||||
"Purchase Receipt",
|
||||
"Purchase Order",
|
||||
"Supplier Quotation",
|
||||
]:
|
||||
if frappe.db.sql(
|
||||
"""select name from `tab%s` where company=%s and docstatus=1
|
||||
limit 1"""
|
||||
% (doctype, "%s"),
|
||||
self.name,
|
||||
):
|
||||
exists = True
|
||||
break
|
||||
|
||||
return exists
|
||||
|
||||
@@ -56,7 +68,7 @@ class Company(NestedSet):
|
||||
|
||||
def validate_abbr(self):
|
||||
if not self.abbr:
|
||||
self.abbr = ''.join(c[0] for c in self.company_name.split()).upper()
|
||||
self.abbr = "".join(c[0] for c in self.company_name.split()).upper()
|
||||
|
||||
self.abbr = self.abbr.strip()
|
||||
|
||||
@@ -66,7 +78,9 @@ class Company(NestedSet):
|
||||
if not self.abbr.strip():
|
||||
frappe.throw(_("Abbreviation is mandatory"))
|
||||
|
||||
if frappe.db.sql("select abbr from tabCompany where name!=%s and abbr=%s", (self.name, self.abbr)):
|
||||
if frappe.db.sql(
|
||||
"select abbr from tabCompany where name!=%s and abbr=%s", (self.name, self.abbr)
|
||||
):
|
||||
frappe.throw(_("Abbreviation already used for another company"))
|
||||
|
||||
@frappe.whitelist()
|
||||
@@ -75,37 +89,57 @@ class Company(NestedSet):
|
||||
|
||||
def validate_default_accounts(self):
|
||||
accounts = [
|
||||
["Default Bank Account", "default_bank_account"], ["Default Cash Account", "default_cash_account"],
|
||||
["Default Receivable Account", "default_receivable_account"], ["Default Payable Account", "default_payable_account"],
|
||||
["Default Expense Account", "default_expense_account"], ["Default Income Account", "default_income_account"],
|
||||
["Stock Received But Not Billed Account", "stock_received_but_not_billed"], ["Stock Adjustment Account", "stock_adjustment_account"],
|
||||
["Expense Included In Valuation Account", "expenses_included_in_valuation"], ["Default Payroll Payable Account", "default_payroll_payable_account"]
|
||||
["Default Bank Account", "default_bank_account"],
|
||||
["Default Cash Account", "default_cash_account"],
|
||||
["Default Receivable Account", "default_receivable_account"],
|
||||
["Default Payable Account", "default_payable_account"],
|
||||
["Default Expense Account", "default_expense_account"],
|
||||
["Default Income Account", "default_income_account"],
|
||||
["Stock Received But Not Billed Account", "stock_received_but_not_billed"],
|
||||
["Stock Adjustment Account", "stock_adjustment_account"],
|
||||
["Expense Included In Valuation Account", "expenses_included_in_valuation"],
|
||||
["Default Payroll Payable Account", "default_payroll_payable_account"],
|
||||
]
|
||||
|
||||
for account in accounts:
|
||||
if self.get(account[1]):
|
||||
for_company = frappe.db.get_value("Account", self.get(account[1]), "company")
|
||||
if for_company != self.name:
|
||||
frappe.throw(_("Account {0} does not belong to company: {1}").format(self.get(account[1]), self.name))
|
||||
frappe.throw(
|
||||
_("Account {0} does not belong to company: {1}").format(self.get(account[1]), self.name)
|
||||
)
|
||||
|
||||
if get_account_currency(self.get(account[1])) != self.default_currency:
|
||||
error_message = _("{0} currency must be same as company's default currency. Please select another account.") \
|
||||
.format(frappe.bold(account[0]))
|
||||
error_message = _(
|
||||
"{0} currency must be same as company's default currency. Please select another account."
|
||||
).format(frappe.bold(account[0]))
|
||||
frappe.throw(error_message)
|
||||
|
||||
def validate_currency(self):
|
||||
if self.is_new():
|
||||
return
|
||||
self.previous_default_currency = frappe.get_cached_value('Company', self.name, "default_currency")
|
||||
if self.default_currency and self.previous_default_currency and \
|
||||
self.default_currency != self.previous_default_currency and \
|
||||
self.check_if_transactions_exist():
|
||||
frappe.throw(_("Cannot change company's default currency, because there are existing transactions. Transactions must be cancelled to change the default currency."))
|
||||
self.previous_default_currency = frappe.get_cached_value(
|
||||
"Company", self.name, "default_currency"
|
||||
)
|
||||
if (
|
||||
self.default_currency
|
||||
and self.previous_default_currency
|
||||
and self.default_currency != self.previous_default_currency
|
||||
and self.check_if_transactions_exist()
|
||||
):
|
||||
frappe.throw(
|
||||
_(
|
||||
"Cannot change company's default currency, because there are existing transactions. Transactions must be cancelled to change the default currency."
|
||||
)
|
||||
)
|
||||
|
||||
def on_update(self):
|
||||
NestedSet.on_update(self)
|
||||
if not frappe.db.sql("""select name from tabAccount
|
||||
where company=%s and docstatus<2 limit 1""", self.name):
|
||||
if not frappe.db.sql(
|
||||
"""select name from tabAccount
|
||||
where company=%s and docstatus<2 limit 1""",
|
||||
self.name,
|
||||
):
|
||||
if not frappe.local.flags.ignore_chart_of_accounts:
|
||||
frappe.flags.country_change = True
|
||||
self.create_default_accounts()
|
||||
@@ -120,7 +154,8 @@ class Company(NestedSet):
|
||||
|
||||
if not frappe.db.get_value("Department", {"company": self.name}):
|
||||
from erpnext.setup.setup_wizard.operations.install_fixtures import install_post_company_fixtures
|
||||
install_post_company_fixtures(frappe._dict({'company_name': self.name}))
|
||||
|
||||
install_post_company_fixtures(frappe._dict({"company_name": self.name}))
|
||||
|
||||
if not frappe.local.flags.ignore_chart_of_accounts:
|
||||
self.set_default_accounts()
|
||||
@@ -130,12 +165,15 @@ class Company(NestedSet):
|
||||
if self.default_currency:
|
||||
frappe.db.set_value("Currency", self.default_currency, "enabled", 1)
|
||||
|
||||
if hasattr(frappe.local, 'enable_perpetual_inventory') and \
|
||||
self.name in frappe.local.enable_perpetual_inventory:
|
||||
if (
|
||||
hasattr(frappe.local, "enable_perpetual_inventory")
|
||||
and self.name in frappe.local.enable_perpetual_inventory
|
||||
):
|
||||
frappe.local.enable_perpetual_inventory[self.name] = self.enable_perpetual_inventory
|
||||
|
||||
if frappe.flags.parent_company_changed:
|
||||
from frappe.utils.nestedset import rebuild_tree
|
||||
|
||||
rebuild_tree("Company", "parent_company")
|
||||
|
||||
frappe.clear_cache()
|
||||
@@ -146,31 +184,48 @@ class Company(NestedSet):
|
||||
{"warehouse_name": _("Stores"), "is_group": 0},
|
||||
{"warehouse_name": _("Work In Progress"), "is_group": 0},
|
||||
{"warehouse_name": _("Finished Goods"), "is_group": 0},
|
||||
{"warehouse_name": _("Goods In Transit"), "is_group": 0, "warehouse_type": "Transit"}]:
|
||||
{"warehouse_name": _("Goods In Transit"), "is_group": 0, "warehouse_type": "Transit"},
|
||||
]:
|
||||
|
||||
if not frappe.db.exists("Warehouse", "{0} - {1}".format(wh_detail["warehouse_name"], self.abbr)):
|
||||
warehouse = frappe.get_doc({
|
||||
"doctype":"Warehouse",
|
||||
"warehouse_name": wh_detail["warehouse_name"],
|
||||
"is_group": wh_detail["is_group"],
|
||||
"company": self.name,
|
||||
"parent_warehouse": "{0} - {1}".format(_("All Warehouses"), self.abbr) \
|
||||
if not wh_detail["is_group"] else "",
|
||||
"warehouse_type" : wh_detail["warehouse_type"] if "warehouse_type" in wh_detail else None
|
||||
})
|
||||
if not frappe.db.exists(
|
||||
"Warehouse", "{0} - {1}".format(wh_detail["warehouse_name"], self.abbr)
|
||||
):
|
||||
warehouse = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Warehouse",
|
||||
"warehouse_name": wh_detail["warehouse_name"],
|
||||
"is_group": wh_detail["is_group"],
|
||||
"company": self.name,
|
||||
"parent_warehouse": "{0} - {1}".format(_("All Warehouses"), self.abbr)
|
||||
if not wh_detail["is_group"]
|
||||
else "",
|
||||
"warehouse_type": wh_detail["warehouse_type"] if "warehouse_type" in wh_detail else None,
|
||||
}
|
||||
)
|
||||
warehouse.flags.ignore_permissions = True
|
||||
warehouse.flags.ignore_mandatory = True
|
||||
warehouse.insert()
|
||||
|
||||
def create_default_accounts(self):
|
||||
from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import create_charts
|
||||
|
||||
frappe.local.flags.ignore_root_company_validation = True
|
||||
create_charts(self.name, self.chart_of_accounts, self.existing_company)
|
||||
|
||||
frappe.db.set(self, "default_receivable_account", frappe.db.get_value("Account",
|
||||
{"company": self.name, "account_type": "Receivable", "is_group": 0}))
|
||||
frappe.db.set(self, "default_payable_account", frappe.db.get_value("Account",
|
||||
{"company": self.name, "account_type": "Payable", "is_group": 0}))
|
||||
frappe.db.set(
|
||||
self,
|
||||
"default_receivable_account",
|
||||
frappe.db.get_value(
|
||||
"Account", {"company": self.name, "account_type": "Receivable", "is_group": 0}
|
||||
),
|
||||
)
|
||||
frappe.db.set(
|
||||
self,
|
||||
"default_payable_account",
|
||||
frappe.db.get_value(
|
||||
"Account", {"company": self.name, "account_type": "Payable", "is_group": 0}
|
||||
),
|
||||
)
|
||||
|
||||
def validate_coa_input(self):
|
||||
if self.create_chart_of_accounts_based_on == "Existing Company":
|
||||
@@ -187,34 +242,46 @@ class Company(NestedSet):
|
||||
def validate_perpetual_inventory(self):
|
||||
if not self.get("__islocal"):
|
||||
if cint(self.enable_perpetual_inventory) == 1 and not self.default_inventory_account:
|
||||
frappe.msgprint(_("Set default inventory account for perpetual inventory"),
|
||||
alert=True, indicator='orange')
|
||||
frappe.msgprint(
|
||||
_("Set default inventory account for perpetual inventory"), alert=True, indicator="orange"
|
||||
)
|
||||
|
||||
def validate_provisional_account_for_non_stock_items(self):
|
||||
if not self.get("__islocal"):
|
||||
if cint(self.enable_provisional_accounting_for_non_stock_items) == 1 and not self.default_provisional_account:
|
||||
frappe.throw(_("Set default {0} account for non stock items").format(
|
||||
frappe.bold('Provisional Account')))
|
||||
if (
|
||||
cint(self.enable_provisional_accounting_for_non_stock_items) == 1
|
||||
and not self.default_provisional_account
|
||||
):
|
||||
frappe.throw(
|
||||
_("Set default {0} account for non stock items").format(frappe.bold("Provisional Account"))
|
||||
)
|
||||
|
||||
make_property_setter("Purchase Receipt", "provisional_expense_account", "hidden",
|
||||
not self.enable_provisional_accounting_for_non_stock_items, "Check", validate_fields_for_doctype=False)
|
||||
make_property_setter(
|
||||
"Purchase Receipt",
|
||||
"provisional_expense_account",
|
||||
"hidden",
|
||||
not self.enable_provisional_accounting_for_non_stock_items,
|
||||
"Check",
|
||||
validate_fields_for_doctype=False,
|
||||
)
|
||||
|
||||
def check_country_change(self):
|
||||
frappe.flags.country_change = False
|
||||
|
||||
if not self.is_new() and \
|
||||
self.country != frappe.get_cached_value('Company', self.name, 'country'):
|
||||
if not self.is_new() and self.country != frappe.get_cached_value(
|
||||
"Company", self.name, "country"
|
||||
):
|
||||
frappe.flags.country_change = True
|
||||
|
||||
def set_chart_of_accounts(self):
|
||||
''' If parent company is set, chart of accounts will be based on that company '''
|
||||
"""If parent company is set, chart of accounts will be based on that company"""
|
||||
if self.parent_company:
|
||||
self.create_chart_of_accounts_based_on = "Existing Company"
|
||||
self.existing_company = self.parent_company
|
||||
|
||||
def validate_parent_company(self):
|
||||
if self.parent_company:
|
||||
is_group = frappe.get_value('Company', self.parent_company, 'is_group')
|
||||
is_group = frappe.get_value("Company", self.parent_company, "is_group")
|
||||
|
||||
if not is_group:
|
||||
frappe.throw(_("Parent Company must be a group company"))
|
||||
@@ -228,29 +295,33 @@ class Company(NestedSet):
|
||||
"depreciation_expense_account": "Depreciation",
|
||||
"capital_work_in_progress_account": "Capital Work in Progress",
|
||||
"asset_received_but_not_billed": "Asset Received But Not Billed",
|
||||
"expenses_included_in_asset_valuation": "Expenses Included In Asset Valuation"
|
||||
"expenses_included_in_asset_valuation": "Expenses Included In Asset Valuation",
|
||||
}
|
||||
|
||||
if self.enable_perpetual_inventory:
|
||||
default_accounts.update({
|
||||
"stock_received_but_not_billed": "Stock Received But Not Billed",
|
||||
"default_inventory_account": "Stock",
|
||||
"stock_adjustment_account": "Stock Adjustment",
|
||||
"expenses_included_in_valuation": "Expenses Included In Valuation",
|
||||
"default_expense_account": "Cost of Goods Sold"
|
||||
})
|
||||
default_accounts.update(
|
||||
{
|
||||
"stock_received_but_not_billed": "Stock Received But Not Billed",
|
||||
"default_inventory_account": "Stock",
|
||||
"stock_adjustment_account": "Stock Adjustment",
|
||||
"expenses_included_in_valuation": "Expenses Included In Valuation",
|
||||
"default_expense_account": "Cost of Goods Sold",
|
||||
}
|
||||
)
|
||||
|
||||
if self.update_default_account:
|
||||
for default_account in default_accounts:
|
||||
self._set_default_account(default_account, default_accounts.get(default_account))
|
||||
|
||||
if not self.default_income_account:
|
||||
income_account = frappe.db.get_value("Account",
|
||||
{"account_name": _("Sales"), "company": self.name, "is_group": 0})
|
||||
income_account = frappe.db.get_value(
|
||||
"Account", {"account_name": _("Sales"), "company": self.name, "is_group": 0}
|
||||
)
|
||||
|
||||
if not income_account:
|
||||
income_account = frappe.db.get_value("Account",
|
||||
{"account_name": _("Sales Account"), "company": self.name})
|
||||
income_account = frappe.db.get_value(
|
||||
"Account", {"account_name": _("Sales Account"), "company": self.name}
|
||||
)
|
||||
|
||||
self.db_set("default_income_account", income_account)
|
||||
|
||||
@@ -258,32 +329,38 @@ class Company(NestedSet):
|
||||
self.db_set("default_payable_account", self.default_payable_account)
|
||||
|
||||
if not self.default_payroll_payable_account:
|
||||
payroll_payable_account = frappe.db.get_value("Account",
|
||||
{"account_name": _("Payroll Payable"), "company": self.name, "is_group": 0})
|
||||
payroll_payable_account = frappe.db.get_value(
|
||||
"Account", {"account_name": _("Payroll Payable"), "company": self.name, "is_group": 0}
|
||||
)
|
||||
|
||||
self.db_set("default_payroll_payable_account", payroll_payable_account)
|
||||
|
||||
if not self.default_employee_advance_account:
|
||||
employe_advance_account = frappe.db.get_value("Account",
|
||||
{"account_name": _("Employee Advances"), "company": self.name, "is_group": 0})
|
||||
employe_advance_account = frappe.db.get_value(
|
||||
"Account", {"account_name": _("Employee Advances"), "company": self.name, "is_group": 0}
|
||||
)
|
||||
|
||||
self.db_set("default_employee_advance_account", employe_advance_account)
|
||||
|
||||
if not self.write_off_account:
|
||||
write_off_acct = frappe.db.get_value("Account",
|
||||
{"account_name": _("Write Off"), "company": self.name, "is_group": 0})
|
||||
write_off_acct = frappe.db.get_value(
|
||||
"Account", {"account_name": _("Write Off"), "company": self.name, "is_group": 0}
|
||||
)
|
||||
|
||||
self.db_set("write_off_account", write_off_acct)
|
||||
|
||||
if not self.exchange_gain_loss_account:
|
||||
exchange_gain_loss_acct = frappe.db.get_value("Account",
|
||||
{"account_name": _("Exchange Gain/Loss"), "company": self.name, "is_group": 0})
|
||||
exchange_gain_loss_acct = frappe.db.get_value(
|
||||
"Account", {"account_name": _("Exchange Gain/Loss"), "company": self.name, "is_group": 0}
|
||||
)
|
||||
|
||||
self.db_set("exchange_gain_loss_account", exchange_gain_loss_acct)
|
||||
|
||||
if not self.disposal_account:
|
||||
disposal_acct = frappe.db.get_value("Account",
|
||||
{"account_name": _("Gain/Loss on Asset Disposal"), "company": self.name, "is_group": 0})
|
||||
disposal_acct = frappe.db.get_value(
|
||||
"Account",
|
||||
{"account_name": _("Gain/Loss on Asset Disposal"), "company": self.name, "is_group": 0},
|
||||
)
|
||||
|
||||
self.db_set("disposal_account", disposal_acct)
|
||||
|
||||
@@ -291,35 +368,39 @@ class Company(NestedSet):
|
||||
if self.get(fieldname):
|
||||
return
|
||||
|
||||
account = frappe.db.get_value("Account", {"account_type": account_type, "is_group": 0, "company": self.name})
|
||||
account = frappe.db.get_value(
|
||||
"Account", {"account_type": account_type, "is_group": 0, "company": self.name}
|
||||
)
|
||||
|
||||
if account:
|
||||
self.db_set(fieldname, account)
|
||||
|
||||
def set_mode_of_payment_account(self):
|
||||
cash = frappe.db.get_value('Mode of Payment', {'type': 'Cash'}, 'name')
|
||||
if cash and self.default_cash_account \
|
||||
and not frappe.db.get_value('Mode of Payment Account', {'company': self.name, 'parent': cash}):
|
||||
mode_of_payment = frappe.get_doc('Mode of Payment', cash, for_update=True)
|
||||
mode_of_payment.append('accounts', {
|
||||
'company': self.name,
|
||||
'default_account': self.default_cash_account
|
||||
})
|
||||
cash = frappe.db.get_value("Mode of Payment", {"type": "Cash"}, "name")
|
||||
if (
|
||||
cash
|
||||
and self.default_cash_account
|
||||
and not frappe.db.get_value("Mode of Payment Account", {"company": self.name, "parent": cash})
|
||||
):
|
||||
mode_of_payment = frappe.get_doc("Mode of Payment", cash, for_update=True)
|
||||
mode_of_payment.append(
|
||||
"accounts", {"company": self.name, "default_account": self.default_cash_account}
|
||||
)
|
||||
mode_of_payment.save(ignore_permissions=True)
|
||||
|
||||
def create_default_cost_center(self):
|
||||
cc_list = [
|
||||
{
|
||||
'cost_center_name': self.name,
|
||||
'company':self.name,
|
||||
'is_group': 1,
|
||||
'parent_cost_center':None
|
||||
"cost_center_name": self.name,
|
||||
"company": self.name,
|
||||
"is_group": 1,
|
||||
"parent_cost_center": None,
|
||||
},
|
||||
{
|
||||
'cost_center_name':_('Main'),
|
||||
'company':self.name,
|
||||
'is_group':0,
|
||||
'parent_cost_center':self.name + ' - ' + self.abbr
|
||||
"cost_center_name": _("Main"),
|
||||
"company": self.name,
|
||||
"is_group": 0,
|
||||
"parent_cost_center": self.name + " - " + self.abbr,
|
||||
},
|
||||
]
|
||||
for cc in cc_list:
|
||||
@@ -338,26 +419,32 @@ class Company(NestedSet):
|
||||
def after_rename(self, olddn, newdn, merge=False):
|
||||
frappe.db.set(self, "company_name", newdn)
|
||||
|
||||
frappe.db.sql("""update `tabDefaultValue` set defvalue=%s
|
||||
where defkey='Company' and defvalue=%s""", (newdn, olddn))
|
||||
frappe.db.sql(
|
||||
"""update `tabDefaultValue` set defvalue=%s
|
||||
where defkey='Company' and defvalue=%s""",
|
||||
(newdn, olddn),
|
||||
)
|
||||
|
||||
clear_defaults_cache()
|
||||
|
||||
def abbreviate(self):
|
||||
self.abbr = ''.join(c[0].upper() for c in self.company_name.split())
|
||||
self.abbr = "".join(c[0].upper() for c in self.company_name.split())
|
||||
|
||||
def on_trash(self):
|
||||
"""
|
||||
Trash accounts and cost centers for this company if no gl entry exists
|
||||
Trash accounts and cost centers for this company if no gl entry exists
|
||||
"""
|
||||
NestedSet.validate_if_child_exists(self)
|
||||
frappe.utils.nestedset.update_nsm(self)
|
||||
|
||||
rec = frappe.db.sql("SELECT name from `tabGL Entry` where company = %s", self.name)
|
||||
if not rec:
|
||||
frappe.db.sql("""delete from `tabBudget Account`
|
||||
frappe.db.sql(
|
||||
"""delete from `tabBudget Account`
|
||||
where exists(select name from tabBudget
|
||||
where name=`tabBudget Account`.parent and company = %s)""", self.name)
|
||||
where name=`tabBudget Account`.parent and company = %s)""",
|
||||
self.name,
|
||||
)
|
||||
|
||||
for doctype in ["Account", "Cost Center", "Budget", "Party Account"]:
|
||||
frappe.db.sql("delete from `tab{0}` where company = %s".format(doctype), self.name)
|
||||
@@ -372,26 +459,37 @@ class Company(NestedSet):
|
||||
# clear default accounts, warehouses from item
|
||||
warehouses = frappe.db.sql_list("select name from tabWarehouse where company=%s", self.name)
|
||||
if warehouses:
|
||||
frappe.db.sql("""delete from `tabItem Reorder` where warehouse in (%s)"""
|
||||
% ', '.join(['%s']*len(warehouses)), tuple(warehouses))
|
||||
frappe.db.sql(
|
||||
"""delete from `tabItem Reorder` where warehouse in (%s)"""
|
||||
% ", ".join(["%s"] * len(warehouses)),
|
||||
tuple(warehouses),
|
||||
)
|
||||
|
||||
# reset default company
|
||||
frappe.db.sql("""update `tabSingles` set value=""
|
||||
frappe.db.sql(
|
||||
"""update `tabSingles` set value=""
|
||||
where doctype='Global Defaults' and field='default_company'
|
||||
and value=%s""", self.name)
|
||||
and value=%s""",
|
||||
self.name,
|
||||
)
|
||||
|
||||
# reset default company
|
||||
frappe.db.sql("""update `tabSingles` set value=""
|
||||
frappe.db.sql(
|
||||
"""update `tabSingles` set value=""
|
||||
where doctype='Chart of Accounts Importer' and field='company'
|
||||
and value=%s""", self.name)
|
||||
and value=%s""",
|
||||
self.name,
|
||||
)
|
||||
|
||||
# delete BOMs
|
||||
boms = frappe.db.sql_list("select name from tabBOM where company=%s", self.name)
|
||||
if boms:
|
||||
frappe.db.sql("delete from tabBOM where company=%s", self.name)
|
||||
for dt in ("BOM Operation", "BOM Item", "BOM Scrap Item", "BOM Explosion Item"):
|
||||
frappe.db.sql("delete from `tab%s` where parent in (%s)"""
|
||||
% (dt, ', '.join(['%s']*len(boms))), tuple(boms))
|
||||
frappe.db.sql(
|
||||
"delete from `tab%s` where parent in (%s)" "" % (dt, ", ".join(["%s"] * len(boms))),
|
||||
tuple(boms),
|
||||
)
|
||||
|
||||
frappe.db.sql("delete from tabEmployee where company=%s", self.name)
|
||||
frappe.db.sql("delete from tabDepartment where company=%s", self.name)
|
||||
@@ -404,18 +502,20 @@ class Company(NestedSet):
|
||||
frappe.db.sql("delete from `tabItem Tax Template` where company=%s", self.name)
|
||||
|
||||
# delete Process Deferred Accounts if no GL Entry found
|
||||
if not frappe.db.get_value('GL Entry', {'company': self.name}):
|
||||
if not frappe.db.get_value("GL Entry", {"company": self.name}):
|
||||
frappe.db.sql("delete from `tabProcess Deferred Accounting` where company=%s", self.name)
|
||||
|
||||
def check_parent_changed(self):
|
||||
frappe.flags.parent_company_changed = False
|
||||
|
||||
if not self.is_new() and \
|
||||
self.parent_company != frappe.db.get_value("Company", self.name, "parent_company"):
|
||||
if not self.is_new() and self.parent_company != frappe.db.get_value(
|
||||
"Company", self.name, "parent_company"
|
||||
):
|
||||
frappe.flags.parent_company_changed = True
|
||||
|
||||
|
||||
def get_name_with_abbr(name, company):
|
||||
company_abbr = frappe.get_cached_value('Company', company, "abbr")
|
||||
company_abbr = frappe.get_cached_value("Company", company, "abbr")
|
||||
parts = name.split(" - ")
|
||||
|
||||
if parts[-1].lower() != company_abbr.lower():
|
||||
@@ -423,21 +523,27 @@ def get_name_with_abbr(name, company):
|
||||
|
||||
return " - ".join(parts)
|
||||
|
||||
|
||||
def install_country_fixtures(company, country):
|
||||
path = frappe.get_app_path('erpnext', 'regional', frappe.scrub(country))
|
||||
path = frappe.get_app_path("erpnext", "regional", frappe.scrub(country))
|
||||
if os.path.exists(path.encode("utf-8")):
|
||||
try:
|
||||
module_name = "erpnext.regional.{0}.setup.setup".format(frappe.scrub(country))
|
||||
frappe.get_attr(module_name)(company, False)
|
||||
except Exception as e:
|
||||
frappe.log_error()
|
||||
frappe.throw(_("Failed to setup defaults for country {0}. Please contact support@erpnext.com").format(frappe.bold(country)))
|
||||
frappe.throw(
|
||||
_("Failed to setup defaults for country {0}. Please contact support@erpnext.com").format(
|
||||
frappe.bold(country)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def update_company_current_month_sales(company):
|
||||
current_month_year = formatdate(today(), "MM-yyyy")
|
||||
|
||||
results = frappe.db.sql('''
|
||||
results = frappe.db.sql(
|
||||
"""
|
||||
SELECT
|
||||
SUM(base_grand_total) AS total,
|
||||
DATE_FORMAT(`posting_date`, '%m-%Y') AS month_year
|
||||
@@ -449,44 +555,58 @@ def update_company_current_month_sales(company):
|
||||
AND company = {company}
|
||||
GROUP BY
|
||||
month_year
|
||||
'''.format(current_month_year=current_month_year, company=frappe.db.escape(company)),
|
||||
as_dict = True)
|
||||
""".format(
|
||||
current_month_year=current_month_year, company=frappe.db.escape(company)
|
||||
),
|
||||
as_dict=True,
|
||||
)
|
||||
|
||||
monthly_total = results[0]['total'] if len(results) > 0 else 0
|
||||
monthly_total = results[0]["total"] if len(results) > 0 else 0
|
||||
|
||||
frappe.db.set_value("Company", company, "total_monthly_sales", monthly_total)
|
||||
|
||||
|
||||
def update_company_monthly_sales(company):
|
||||
'''Cache past year monthly sales of every company based on sales invoices'''
|
||||
"""Cache past year monthly sales of every company based on sales invoices"""
|
||||
import json
|
||||
|
||||
from frappe.utils.goal import get_monthly_results
|
||||
filter_str = "company = {0} and status != 'Draft' and docstatus=1".format(frappe.db.escape(company))
|
||||
month_to_value_dict = get_monthly_results("Sales Invoice", "base_grand_total",
|
||||
"posting_date", filter_str, "sum")
|
||||
|
||||
filter_str = "company = {0} and status != 'Draft' and docstatus=1".format(
|
||||
frappe.db.escape(company)
|
||||
)
|
||||
month_to_value_dict = get_monthly_results(
|
||||
"Sales Invoice", "base_grand_total", "posting_date", filter_str, "sum"
|
||||
)
|
||||
|
||||
frappe.db.set_value("Company", company, "sales_monthly_history", json.dumps(month_to_value_dict))
|
||||
|
||||
|
||||
def update_transactions_annual_history(company, commit=False):
|
||||
transactions_history = get_all_transactions_annual_history(company)
|
||||
frappe.db.set_value("Company", company, "transactions_annual_history", json.dumps(transactions_history))
|
||||
frappe.db.set_value(
|
||||
"Company", company, "transactions_annual_history", json.dumps(transactions_history)
|
||||
)
|
||||
|
||||
if commit:
|
||||
frappe.db.commit()
|
||||
|
||||
|
||||
def cache_companies_monthly_sales_history():
|
||||
companies = [d['name'] for d in frappe.get_list("Company")]
|
||||
companies = [d["name"] for d in frappe.get_list("Company")]
|
||||
for company in companies:
|
||||
update_company_monthly_sales(company)
|
||||
update_transactions_annual_history(company)
|
||||
frappe.db.commit()
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_children(doctype, parent=None, company=None, is_root=False):
|
||||
if parent == None or parent == "All Companies":
|
||||
parent = ""
|
||||
|
||||
return frappe.db.sql("""
|
||||
return frappe.db.sql(
|
||||
"""
|
||||
select
|
||||
name as value,
|
||||
is_group as expandable
|
||||
@@ -495,25 +615,30 @@ def get_children(doctype, parent=None, company=None, is_root=False):
|
||||
where
|
||||
ifnull(parent_company, "")={parent}
|
||||
""".format(
|
||||
doctype = doctype,
|
||||
parent=frappe.db.escape(parent)
|
||||
), as_dict=1)
|
||||
doctype=doctype, parent=frappe.db.escape(parent)
|
||||
),
|
||||
as_dict=1,
|
||||
)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def add_node():
|
||||
from frappe.desk.treeview import make_tree_args
|
||||
|
||||
args = frappe.form_dict
|
||||
args = make_tree_args(**args)
|
||||
|
||||
if args.parent_company == 'All Companies':
|
||||
if args.parent_company == "All Companies":
|
||||
args.parent_company = None
|
||||
|
||||
frappe.get_doc(args).insert()
|
||||
|
||||
|
||||
def get_all_transactions_annual_history(company):
|
||||
out = {}
|
||||
|
||||
items = frappe.db.sql('''
|
||||
items = frappe.db.sql(
|
||||
"""
|
||||
select transaction_date, count(*) as count
|
||||
|
||||
from (
|
||||
@@ -553,61 +678,68 @@ def get_all_transactions_annual_history(company):
|
||||
|
||||
group by
|
||||
transaction_date
|
||||
''', (company), as_dict=True)
|
||||
""",
|
||||
(company),
|
||||
as_dict=True,
|
||||
)
|
||||
|
||||
for d in items:
|
||||
timestamp = get_timestamp(d["transaction_date"])
|
||||
out.update({ timestamp: d["count"] })
|
||||
out.update({timestamp: d["count"]})
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def get_timeline_data(doctype, name):
|
||||
'''returns timeline data based on linked records in dashboard'''
|
||||
"""returns timeline data based on linked records in dashboard"""
|
||||
out = {}
|
||||
date_to_value_dict = {}
|
||||
|
||||
history = frappe.get_cached_value('Company', name, "transactions_annual_history")
|
||||
history = frappe.get_cached_value("Company", name, "transactions_annual_history")
|
||||
|
||||
try:
|
||||
date_to_value_dict = json.loads(history) if history and '{' in history else None
|
||||
date_to_value_dict = json.loads(history) if history and "{" in history else None
|
||||
except ValueError:
|
||||
date_to_value_dict = None
|
||||
|
||||
if date_to_value_dict is None:
|
||||
update_transactions_annual_history(name, True)
|
||||
history = frappe.get_cached_value('Company', name, "transactions_annual_history")
|
||||
return json.loads(history) if history and '{' in history else {}
|
||||
history = frappe.get_cached_value("Company", name, "transactions_annual_history")
|
||||
return json.loads(history) if history and "{" in history else {}
|
||||
|
||||
return date_to_value_dict
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_default_company_address(name, sort_key='is_primary_address', existing_address=None):
|
||||
if sort_key not in ['is_shipping_address', 'is_primary_address']:
|
||||
def get_default_company_address(name, sort_key="is_primary_address", existing_address=None):
|
||||
if sort_key not in ["is_shipping_address", "is_primary_address"]:
|
||||
return None
|
||||
|
||||
out = frappe.db.sql(""" SELECT
|
||||
out = frappe.db.sql(
|
||||
""" SELECT
|
||||
addr.name, addr.%s
|
||||
FROM
|
||||
`tabAddress` addr, `tabDynamic Link` dl
|
||||
WHERE
|
||||
dl.parent = addr.name and dl.link_doctype = 'Company' and
|
||||
dl.link_name = %s and ifnull(addr.disabled, 0) = 0
|
||||
""" %(sort_key, '%s'), (name)) #nosec
|
||||
"""
|
||||
% (sort_key, "%s"),
|
||||
(name),
|
||||
) # nosec
|
||||
|
||||
if existing_address:
|
||||
if existing_address in [d[0] for d in out]:
|
||||
return existing_address
|
||||
|
||||
if out:
|
||||
return sorted(out, key = functools.cmp_to_key(lambda x,y: cmp(y[1], x[1])))[0][0]
|
||||
return sorted(out, key=functools.cmp_to_key(lambda x, y: cmp(y[1], x[1])))[0][0]
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_transaction_deletion_request(company):
|
||||
tdr = frappe.get_doc({
|
||||
'doctype': 'Transaction Deletion Record',
|
||||
'company': company
|
||||
})
|
||||
tdr = frappe.get_doc({"doctype": "Transaction Deletion Record", "company": company})
|
||||
tdr.insert()
|
||||
tdr.submit()
|
||||
|
||||
@@ -1,41 +1,27 @@
|
||||
|
||||
from frappe import _
|
||||
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'graph': True,
|
||||
'graph_method': "frappe.utils.goal.get_monthly_goal_graph_data",
|
||||
'graph_method_args': {
|
||||
'title': _('Sales'),
|
||||
'goal_value_field': 'monthly_sales_target',
|
||||
'goal_total_field': 'total_monthly_sales',
|
||||
'goal_history_field': 'sales_monthly_history',
|
||||
'goal_doctype': 'Sales Invoice',
|
||||
'goal_doctype_link': 'company',
|
||||
'goal_field': 'base_grand_total',
|
||||
'date_field': 'posting_date',
|
||||
'filter_str': "docstatus = 1 and is_opening != 'Yes'",
|
||||
'aggregation': 'sum'
|
||||
"graph": True,
|
||||
"graph_method": "frappe.utils.goal.get_monthly_goal_graph_data",
|
||||
"graph_method_args": {
|
||||
"title": _("Sales"),
|
||||
"goal_value_field": "monthly_sales_target",
|
||||
"goal_total_field": "total_monthly_sales",
|
||||
"goal_history_field": "sales_monthly_history",
|
||||
"goal_doctype": "Sales Invoice",
|
||||
"goal_doctype_link": "company",
|
||||
"goal_field": "base_grand_total",
|
||||
"date_field": "posting_date",
|
||||
"filter_str": "docstatus = 1 and is_opening != 'Yes'",
|
||||
"aggregation": "sum",
|
||||
},
|
||||
|
||||
'fieldname': 'company',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Pre Sales'),
|
||||
'items': ['Quotation']
|
||||
},
|
||||
{
|
||||
'label': _('Orders'),
|
||||
'items': ['Sales Order', 'Delivery Note', 'Sales Invoice']
|
||||
},
|
||||
{
|
||||
'label': _('Support'),
|
||||
'items': ['Issue']
|
||||
},
|
||||
{
|
||||
'label': _('Projects'),
|
||||
'items': ['Project']
|
||||
}
|
||||
]
|
||||
"fieldname": "company",
|
||||
"transactions": [
|
||||
{"label": _("Pre Sales"), "items": ["Quotation"]},
|
||||
{"label": _("Orders"), "items": ["Sales Order", "Delivery Note", "Sales Invoice"]},
|
||||
{"label": _("Support"), "items": ["Issue"]},
|
||||
{"label": _("Projects"), "items": ["Project"]},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -14,7 +14,8 @@ from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import
|
||||
|
||||
test_ignore = ["Account", "Cost Center", "Payment Terms Template", "Salary Component", "Warehouse"]
|
||||
test_dependencies = ["Fiscal Year"]
|
||||
test_records = frappe.get_test_records('Company')
|
||||
test_records = frappe.get_test_records("Company")
|
||||
|
||||
|
||||
class TestCompany(unittest.TestCase):
|
||||
def test_coa_based_on_existing_company(self):
|
||||
@@ -37,8 +38,8 @@ class TestCompany(unittest.TestCase):
|
||||
"account_type": "Cash",
|
||||
"is_group": 0,
|
||||
"root_type": "Asset",
|
||||
"parent_account": "Cash In Hand - CFEC"
|
||||
}
|
||||
"parent_account": "Cash In Hand - CFEC",
|
||||
},
|
||||
}
|
||||
|
||||
for account, acc_property in expected_results.items():
|
||||
@@ -69,15 +70,22 @@ class TestCompany(unittest.TestCase):
|
||||
company.chart_of_accounts = template
|
||||
company.save()
|
||||
|
||||
account_types = ["Cost of Goods Sold", "Depreciation",
|
||||
"Expenses Included In Valuation", "Fixed Asset", "Payable", "Receivable",
|
||||
"Stock Adjustment", "Stock Received But Not Billed", "Bank", "Cash", "Stock"]
|
||||
account_types = [
|
||||
"Cost of Goods Sold",
|
||||
"Depreciation",
|
||||
"Expenses Included In Valuation",
|
||||
"Fixed Asset",
|
||||
"Payable",
|
||||
"Receivable",
|
||||
"Stock Adjustment",
|
||||
"Stock Received But Not Billed",
|
||||
"Bank",
|
||||
"Cash",
|
||||
"Stock",
|
||||
]
|
||||
|
||||
for account_type in account_types:
|
||||
filters = {
|
||||
"company": template,
|
||||
"account_type": account_type
|
||||
}
|
||||
filters = {"company": template, "account_type": account_type}
|
||||
if account_type in ["Bank", "Cash"]:
|
||||
filters["is_group"] = 1
|
||||
|
||||
@@ -90,8 +98,11 @@ class TestCompany(unittest.TestCase):
|
||||
frappe.delete_doc("Company", template)
|
||||
|
||||
def delete_mode_of_payment(self, company):
|
||||
frappe.db.sql(""" delete from `tabMode of Payment Account`
|
||||
where company =%s """, (company))
|
||||
frappe.db.sql(
|
||||
""" delete from `tabMode of Payment Account`
|
||||
where company =%s """,
|
||||
(company),
|
||||
)
|
||||
|
||||
def test_basic_tree(self, records=None):
|
||||
min_lft = 1
|
||||
@@ -101,12 +112,12 @@ class TestCompany(unittest.TestCase):
|
||||
records = test_records[2:]
|
||||
|
||||
for company in records:
|
||||
lft, rgt, parent_company = frappe.db.get_value("Company", company["company_name"],
|
||||
["lft", "rgt", "parent_company"])
|
||||
lft, rgt, parent_company = frappe.db.get_value(
|
||||
"Company", company["company_name"], ["lft", "rgt", "parent_company"]
|
||||
)
|
||||
|
||||
if parent_company:
|
||||
parent_lft, parent_rgt = frappe.db.get_value("Company", parent_company,
|
||||
["lft", "rgt"])
|
||||
parent_lft, parent_rgt = frappe.db.get_value("Company", parent_company, ["lft", "rgt"])
|
||||
else:
|
||||
# root
|
||||
parent_lft = min_lft - 1
|
||||
@@ -125,8 +136,11 @@ class TestCompany(unittest.TestCase):
|
||||
def get_no_of_children(companies, no_of_children):
|
||||
children = []
|
||||
for company in companies:
|
||||
children += frappe.db.sql_list("""select name from `tabCompany`
|
||||
where ifnull(parent_company, '')=%s""", company or '')
|
||||
children += frappe.db.sql_list(
|
||||
"""select name from `tabCompany`
|
||||
where ifnull(parent_company, '')=%s""",
|
||||
company or "",
|
||||
)
|
||||
|
||||
if len(children):
|
||||
return get_no_of_children(children, no_of_children + len(children))
|
||||
@@ -148,40 +162,45 @@ class TestCompany(unittest.TestCase):
|
||||
child_company.save()
|
||||
self.test_basic_tree()
|
||||
|
||||
|
||||
def create_company_communication(doctype, docname):
|
||||
comm = frappe.get_doc({
|
||||
comm = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Communication",
|
||||
"communication_type": "Communication",
|
||||
"content": "Deduplication of Links",
|
||||
"communication_medium": "Email",
|
||||
"reference_doctype":doctype,
|
||||
"reference_name":docname
|
||||
})
|
||||
"reference_doctype": doctype,
|
||||
"reference_name": docname,
|
||||
}
|
||||
)
|
||||
comm.insert()
|
||||
|
||||
|
||||
def create_child_company():
|
||||
child_company = frappe.db.exists("Company", "Test Company")
|
||||
if not child_company:
|
||||
child_company = frappe.get_doc({
|
||||
"doctype":"Company",
|
||||
"company_name":"Test Company",
|
||||
"abbr":"test_company",
|
||||
"default_currency":"INR"
|
||||
})
|
||||
child_company = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Company",
|
||||
"company_name": "Test Company",
|
||||
"abbr": "test_company",
|
||||
"default_currency": "INR",
|
||||
}
|
||||
)
|
||||
child_company.insert()
|
||||
else:
|
||||
child_company = frappe.get_doc("Company", child_company)
|
||||
|
||||
return child_company.name
|
||||
|
||||
|
||||
def create_test_lead_in_company(company):
|
||||
lead = frappe.db.exists("Lead", "Test Lead in new company")
|
||||
if not lead:
|
||||
lead = frappe.get_doc({
|
||||
"doctype": "Lead",
|
||||
"lead_name": "Test Lead in new company",
|
||||
"scompany": company
|
||||
})
|
||||
lead = frappe.get_doc(
|
||||
{"doctype": "Lead", "lead_name": "Test Lead in new company", "scompany": company}
|
||||
)
|
||||
lead.insert()
|
||||
else:
|
||||
lead = frappe.get_doc("Lead", lead)
|
||||
|
||||
@@ -17,13 +17,17 @@ class CurrencyExchange(Document):
|
||||
|
||||
# If both selling and buying enabled
|
||||
purpose = "Selling-Buying"
|
||||
if cint(self.for_buying)==0 and cint(self.for_selling)==1:
|
||||
if cint(self.for_buying) == 0 and cint(self.for_selling) == 1:
|
||||
purpose = "Selling"
|
||||
if cint(self.for_buying)==1 and cint(self.for_selling)==0:
|
||||
if cint(self.for_buying) == 1 and cint(self.for_selling) == 0:
|
||||
purpose = "Buying"
|
||||
|
||||
self.name = '{0}-{1}-{2}{3}'.format(formatdate(get_datetime_str(self.date), "yyyy-MM-dd"),
|
||||
self.from_currency, self.to_currency, ("-" + purpose) if purpose else "")
|
||||
self.name = "{0}-{1}-{2}{3}".format(
|
||||
formatdate(get_datetime_str(self.date), "yyyy-MM-dd"),
|
||||
self.from_currency,
|
||||
self.to_currency,
|
||||
("-" + purpose) if purpose else "",
|
||||
)
|
||||
|
||||
def validate(self):
|
||||
self.validate_value("exchange_rate", ">", 0)
|
||||
|
||||
@@ -8,7 +8,7 @@ from frappe.utils import cint, flt
|
||||
|
||||
from erpnext.setup.utils import get_exchange_rate
|
||||
|
||||
test_records = frappe.get_test_records('Currency Exchange')
|
||||
test_records = frappe.get_test_records("Currency Exchange")
|
||||
|
||||
|
||||
def save_new_records(test_records):
|
||||
@@ -16,13 +16,19 @@ def save_new_records(test_records):
|
||||
# If both selling and buying enabled
|
||||
purpose = "Selling-Buying"
|
||||
|
||||
if cint(record.get("for_buying"))==0 and cint(record.get("for_selling"))==1:
|
||||
if cint(record.get("for_buying")) == 0 and cint(record.get("for_selling")) == 1:
|
||||
purpose = "Selling"
|
||||
if cint(record.get("for_buying"))==1 and cint(record.get("for_selling"))==0:
|
||||
if cint(record.get("for_buying")) == 1 and cint(record.get("for_selling")) == 0:
|
||||
purpose = "Buying"
|
||||
kwargs = dict(
|
||||
doctype=record.get("doctype"),
|
||||
docname=record.get("date") + '-' + record.get("from_currency") + '-' + record.get("to_currency") + '-' + purpose,
|
||||
docname=record.get("date")
|
||||
+ "-"
|
||||
+ record.get("from_currency")
|
||||
+ "-"
|
||||
+ record.get("to_currency")
|
||||
+ "-"
|
||||
+ purpose,
|
||||
fieldname="exchange_rate",
|
||||
value=record.get("exchange_rate"),
|
||||
)
|
||||
|
||||
@@ -8,7 +8,8 @@ from frappe.utils.nestedset import NestedSet, get_root_of
|
||||
|
||||
|
||||
class CustomerGroup(NestedSet):
|
||||
nsm_parent_field = 'parent_customer_group'
|
||||
nsm_parent_field = "parent_customer_group"
|
||||
|
||||
def validate(self):
|
||||
if not self.parent_customer_group:
|
||||
self.parent_customer_group = get_root_of("Customer Group")
|
||||
@@ -22,12 +23,18 @@ class CustomerGroup(NestedSet):
|
||||
if frappe.db.exists("Customer", self.name):
|
||||
frappe.msgprint(_("A customer with the same name already exists"), raise_exception=1)
|
||||
|
||||
def get_parent_customer_groups(customer_group):
|
||||
lft, rgt = frappe.db.get_value("Customer Group", customer_group, ['lft', 'rgt'])
|
||||
|
||||
return frappe.db.sql("""select name from `tabCustomer Group`
|
||||
def get_parent_customer_groups(customer_group):
|
||||
lft, rgt = frappe.db.get_value("Customer Group", customer_group, ["lft", "rgt"])
|
||||
|
||||
return frappe.db.sql(
|
||||
"""select name from `tabCustomer Group`
|
||||
where lft <= %s and rgt >= %s
|
||||
order by lft asc""", (lft, rgt), as_dict=True)
|
||||
order by lft asc""",
|
||||
(lft, rgt),
|
||||
as_dict=True,
|
||||
)
|
||||
|
||||
|
||||
def on_doctype_update():
|
||||
frappe.db.add_index("Customer Group", ["lft", "rgt"])
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
test_ignore = ["Price List"]
|
||||
|
||||
|
||||
|
||||
import frappe
|
||||
|
||||
test_records = frappe.get_test_records('Customer Group')
|
||||
test_records = frappe.get_test_records("Customer Group")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,34 +1,65 @@
|
||||
|
||||
import random
|
||||
|
||||
|
||||
def get_random_quote():
|
||||
quotes = [
|
||||
("Start by doing what's necessary; then do what's possible; and suddenly you are doing the impossible.", "Francis of Assisi"),
|
||||
("The best and most beautiful things in the world cannot be seen or even touched - they must be felt with the heart.", "Hellen Keller"),
|
||||
("I can't change the direction of the wind, but I can adjust my sails to always reach my destination.", "Jimmy Dean"),
|
||||
(
|
||||
"Start by doing what's necessary; then do what's possible; and suddenly you are doing the impossible.",
|
||||
"Francis of Assisi",
|
||||
),
|
||||
(
|
||||
"The best and most beautiful things in the world cannot be seen or even touched - they must be felt with the heart.",
|
||||
"Hellen Keller",
|
||||
),
|
||||
(
|
||||
"I can't change the direction of the wind, but I can adjust my sails to always reach my destination.",
|
||||
"Jimmy Dean",
|
||||
),
|
||||
("We know what we are, but know not what we may be.", "William Shakespeare"),
|
||||
("There are only two mistakes one can make along the road to truth; not going all the way, and not starting.", "Buddha"),
|
||||
(
|
||||
"There are only two mistakes one can make along the road to truth; not going all the way, and not starting.",
|
||||
"Buddha",
|
||||
),
|
||||
("Always remember that you are absolutely unique. Just like everyone else.", "Margaret Mead"),
|
||||
("You have to learn the rules of the game. And then you have to play better than anyone else.", "Albert Einstein"),
|
||||
(
|
||||
"You have to learn the rules of the game. And then you have to play better than anyone else.",
|
||||
"Albert Einstein",
|
||||
),
|
||||
("Once we accept our limits, we go beyond them.", "Albert Einstein"),
|
||||
("Quality is not an act, it is a habit.", "Aristotle"),
|
||||
("The more that you read, the more things you will know. The more that you learn, the more places you'll go.", "Dr. Seuss"),
|
||||
(
|
||||
"The more that you read, the more things you will know. The more that you learn, the more places you'll go.",
|
||||
"Dr. Seuss",
|
||||
),
|
||||
("From there to here, and here to there, funny things are everywhere.", "Dr. Seuss"),
|
||||
("The secret of getting ahead is getting started.", "Mark Twain"),
|
||||
("All generalizations are false, including this one.", "Mark Twain"),
|
||||
("Don't let schooling interfere with your education.", "Mark Twain"),
|
||||
("Cauliflower is nothing but cabbage with a college education.", "Mark Twain"),
|
||||
("It's not the size of the dog in the fight, it's the size of the fight in the dog.", "Mark Twain"),
|
||||
(
|
||||
"It's not the size of the dog in the fight, it's the size of the fight in the dog.",
|
||||
"Mark Twain",
|
||||
),
|
||||
("Climate is what we expect, weather is what we get.", "Mark Twain"),
|
||||
("There are lies, damned lies and statistics.", "Mark Twain"),
|
||||
("Happiness is when what you think, what you say, and what you do are in harmony.", "Mahatma Gandhi"),
|
||||
("First they ignore you, then they laugh at you, then they fight you, then you win.", "Mahatma Gandhi"),
|
||||
(
|
||||
"Happiness is when what you think, what you say, and what you do are in harmony.",
|
||||
"Mahatma Gandhi",
|
||||
),
|
||||
(
|
||||
"First they ignore you, then they laugh at you, then they fight you, then you win.",
|
||||
"Mahatma Gandhi",
|
||||
),
|
||||
("There is more to life than increasing its speed.", "Mahatma Gandhi"),
|
||||
("A small body of determined spirits fired by an unquenchable faith in their mission can alter the course of history.", "Mahatma Gandhi"),
|
||||
(
|
||||
"A small body of determined spirits fired by an unquenchable faith in their mission can alter the course of history.",
|
||||
"Mahatma Gandhi",
|
||||
),
|
||||
("If two wrongs don't make a right, try three.", "Laurence J. Peter"),
|
||||
("Inspiration exists, but it has to find you working.", "Pablo Picasso"),
|
||||
("The world’s first speeding ticket was given to a man going 4 times the speed limit! Walter Arnold was traveling at a breakneck 8 miles an hour in a 2mph zone, and was caught by a policeman on bicycle and fined one shilling!"),
|
||||
(
|
||||
"The world’s first speeding ticket was given to a man going 4 times the speed limit! Walter Arnold was traveling at a breakneck 8 miles an hour in a 2mph zone, and was caught by a policeman on bicycle and fined one shilling!"
|
||||
),
|
||||
]
|
||||
|
||||
return random.choice(quotes)
|
||||
|
||||
@@ -5,5 +5,6 @@ import unittest
|
||||
|
||||
# test_records = frappe.get_test_records('Email Digest')
|
||||
|
||||
|
||||
class TestEmailDigest(unittest.TestCase):
|
||||
pass
|
||||
|
||||
@@ -11,35 +11,37 @@ from frappe.utils import cint
|
||||
keydict = {
|
||||
# "key in defaults": "key in Global Defaults"
|
||||
"fiscal_year": "current_fiscal_year",
|
||||
'company': 'default_company',
|
||||
'currency': 'default_currency',
|
||||
"company": "default_company",
|
||||
"currency": "default_currency",
|
||||
"country": "country",
|
||||
'hide_currency_symbol':'hide_currency_symbol',
|
||||
'account_url':'account_url',
|
||||
'disable_rounded_total': 'disable_rounded_total',
|
||||
'disable_in_words': 'disable_in_words',
|
||||
"hide_currency_symbol": "hide_currency_symbol",
|
||||
"account_url": "account_url",
|
||||
"disable_rounded_total": "disable_rounded_total",
|
||||
"disable_in_words": "disable_in_words",
|
||||
}
|
||||
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class GlobalDefaults(Document):
|
||||
|
||||
def on_update(self):
|
||||
"""update defaults"""
|
||||
for key in keydict:
|
||||
frappe.db.set_default(key, self.get(keydict[key], ''))
|
||||
frappe.db.set_default(key, self.get(keydict[key], ""))
|
||||
|
||||
# update year start date and year end date from fiscal_year
|
||||
year_start_end_date = frappe.db.sql("""select year_start_date, year_end_date
|
||||
from `tabFiscal Year` where name=%s""", self.current_fiscal_year)
|
||||
year_start_end_date = frappe.db.sql(
|
||||
"""select year_start_date, year_end_date
|
||||
from `tabFiscal Year` where name=%s""",
|
||||
self.current_fiscal_year,
|
||||
)
|
||||
if year_start_end_date:
|
||||
ysd = year_start_end_date[0][0] or ''
|
||||
yed = year_start_end_date[0][1] or ''
|
||||
ysd = year_start_end_date[0][0] or ""
|
||||
yed = year_start_end_date[0][1] or ""
|
||||
|
||||
if ysd and yed:
|
||||
frappe.db.set_default('year_start_date', ysd.strftime('%Y-%m-%d'))
|
||||
frappe.db.set_default('year_end_date', yed.strftime('%Y-%m-%d'))
|
||||
frappe.db.set_default("year_start_date", ysd.strftime("%Y-%m-%d"))
|
||||
frappe.db.set_default("year_end_date", yed.strftime("%Y-%m-%d"))
|
||||
|
||||
# enable default currency
|
||||
if self.default_currency:
|
||||
@@ -59,21 +61,81 @@ class GlobalDefaults(Document):
|
||||
self.disable_rounded_total = cint(self.disable_rounded_total)
|
||||
|
||||
# Make property setters to hide rounded total fields
|
||||
for doctype in ("Quotation", "Sales Order", "Sales Invoice", "Delivery Note",
|
||||
"Supplier Quotation", "Purchase Order", "Purchase Invoice", "Purchase Receipt"):
|
||||
make_property_setter(doctype, "base_rounded_total", "hidden", self.disable_rounded_total, "Check", validate_fields_for_doctype=False)
|
||||
make_property_setter(doctype, "base_rounded_total", "print_hide", 1, "Check", validate_fields_for_doctype=False)
|
||||
for doctype in (
|
||||
"Quotation",
|
||||
"Sales Order",
|
||||
"Sales Invoice",
|
||||
"Delivery Note",
|
||||
"Supplier Quotation",
|
||||
"Purchase Order",
|
||||
"Purchase Invoice",
|
||||
"Purchase Receipt",
|
||||
):
|
||||
make_property_setter(
|
||||
doctype,
|
||||
"base_rounded_total",
|
||||
"hidden",
|
||||
self.disable_rounded_total,
|
||||
"Check",
|
||||
validate_fields_for_doctype=False,
|
||||
)
|
||||
make_property_setter(
|
||||
doctype, "base_rounded_total", "print_hide", 1, "Check", validate_fields_for_doctype=False
|
||||
)
|
||||
|
||||
make_property_setter(doctype, "rounded_total", "hidden", self.disable_rounded_total, "Check", validate_fields_for_doctype=False)
|
||||
make_property_setter(doctype, "rounded_total", "print_hide", self.disable_rounded_total, "Check", validate_fields_for_doctype=False)
|
||||
make_property_setter(
|
||||
doctype,
|
||||
"rounded_total",
|
||||
"hidden",
|
||||
self.disable_rounded_total,
|
||||
"Check",
|
||||
validate_fields_for_doctype=False,
|
||||
)
|
||||
make_property_setter(
|
||||
doctype,
|
||||
"rounded_total",
|
||||
"print_hide",
|
||||
self.disable_rounded_total,
|
||||
"Check",
|
||||
validate_fields_for_doctype=False,
|
||||
)
|
||||
|
||||
make_property_setter(doctype, "disable_rounded_total", "default", cint(self.disable_rounded_total), "Text", validate_fields_for_doctype=False)
|
||||
make_property_setter(
|
||||
doctype,
|
||||
"disable_rounded_total",
|
||||
"default",
|
||||
cint(self.disable_rounded_total),
|
||||
"Text",
|
||||
validate_fields_for_doctype=False,
|
||||
)
|
||||
|
||||
def toggle_in_words(self):
|
||||
self.disable_in_words = cint(self.disable_in_words)
|
||||
|
||||
# Make property setters to hide in words fields
|
||||
for doctype in ("Quotation", "Sales Order", "Sales Invoice", "Delivery Note",
|
||||
"Supplier Quotation", "Purchase Order", "Purchase Invoice", "Purchase Receipt"):
|
||||
make_property_setter(doctype, "in_words", "hidden", self.disable_in_words, "Check", validate_fields_for_doctype=False)
|
||||
make_property_setter(doctype, "in_words", "print_hide", self.disable_in_words, "Check", validate_fields_for_doctype=False)
|
||||
for doctype in (
|
||||
"Quotation",
|
||||
"Sales Order",
|
||||
"Sales Invoice",
|
||||
"Delivery Note",
|
||||
"Supplier Quotation",
|
||||
"Purchase Order",
|
||||
"Purchase Invoice",
|
||||
"Purchase Receipt",
|
||||
):
|
||||
make_property_setter(
|
||||
doctype,
|
||||
"in_words",
|
||||
"hidden",
|
||||
self.disable_in_words,
|
||||
"Check",
|
||||
validate_fields_for_doctype=False,
|
||||
)
|
||||
make_property_setter(
|
||||
doctype,
|
||||
"in_words",
|
||||
"print_hide",
|
||||
self.disable_in_words,
|
||||
"Check",
|
||||
validate_fields_for_doctype=False,
|
||||
)
|
||||
|
||||
@@ -16,12 +16,12 @@ from erpnext.e_commerce.product_data_engine.filters import ProductFiltersBuilder
|
||||
|
||||
|
||||
class ItemGroup(NestedSet, WebsiteGenerator):
|
||||
nsm_parent_field = 'parent_item_group'
|
||||
nsm_parent_field = "parent_item_group"
|
||||
website = frappe._dict(
|
||||
condition_field = "show_in_website",
|
||||
template = "templates/generators/item_group.html",
|
||||
no_cache = 1,
|
||||
no_breadcrumbs = 1
|
||||
condition_field="show_in_website",
|
||||
template="templates/generators/item_group.html",
|
||||
no_cache=1,
|
||||
no_breadcrumbs=1,
|
||||
)
|
||||
|
||||
def autoname(self):
|
||||
@@ -31,8 +31,8 @@ class ItemGroup(NestedSet, WebsiteGenerator):
|
||||
super(ItemGroup, self).validate()
|
||||
|
||||
if not self.parent_item_group and not frappe.flags.in_test:
|
||||
if frappe.db.exists("Item Group", _('All Item Groups')):
|
||||
self.parent_item_group = _('All Item Groups')
|
||||
if frappe.db.exists("Item Group", _("All Item Groups")):
|
||||
self.parent_item_group = _("All Item Groups")
|
||||
|
||||
self.make_route()
|
||||
self.validate_item_group_defaults()
|
||||
@@ -44,15 +44,15 @@ class ItemGroup(NestedSet, WebsiteGenerator):
|
||||
self.delete_child_item_groups_key()
|
||||
|
||||
def make_route(self):
|
||||
'''Make website route'''
|
||||
"""Make website route"""
|
||||
if not self.route:
|
||||
self.route = ''
|
||||
self.route = ""
|
||||
if self.parent_item_group:
|
||||
parent_item_group = frappe.get_doc('Item Group', self.parent_item_group)
|
||||
parent_item_group = frappe.get_doc("Item Group", self.parent_item_group)
|
||||
|
||||
# make parent route only if not root
|
||||
if parent_item_group.parent_item_group and parent_item_group.route:
|
||||
self.route = parent_item_group.route + '/'
|
||||
self.route = parent_item_group.route + "/"
|
||||
|
||||
self.route += self.scrub(self.item_group_name)
|
||||
|
||||
@@ -66,28 +66,22 @@ class ItemGroup(NestedSet, WebsiteGenerator):
|
||||
def get_context(self, context):
|
||||
context.show_search = True
|
||||
context.body_class = "product-page"
|
||||
context.page_length = cint(frappe.db.get_single_value('E Commerce Settings', 'products_per_page')) or 6
|
||||
context.search_link = '/product_search'
|
||||
context.page_length = (
|
||||
cint(frappe.db.get_single_value("E Commerce Settings", "products_per_page")) or 6
|
||||
)
|
||||
context.search_link = "/product_search"
|
||||
|
||||
filter_engine = ProductFiltersBuilder(self.name)
|
||||
|
||||
context.field_filters = filter_engine.get_field_filters()
|
||||
context.attribute_filters = filter_engine.get_attribute_filters()
|
||||
|
||||
context.update({
|
||||
"parents": get_parent_item_groups(self.parent_item_group),
|
||||
"title": self.name
|
||||
})
|
||||
context.update({"parents": get_parent_item_groups(self.parent_item_group), "title": self.name})
|
||||
|
||||
if self.slideshow:
|
||||
values = {
|
||||
'show_indicators': 1,
|
||||
'show_controls': 0,
|
||||
'rounded': 1,
|
||||
'slider_name': self.slideshow
|
||||
}
|
||||
values = {"show_indicators": 1, "show_controls": 0, "rounded": 1, "slider_name": self.slideshow}
|
||||
slideshow = frappe.get_doc("Website Slideshow", self.slideshow)
|
||||
slides = slideshow.get({"doctype":"Website Slideshow Item"})
|
||||
slides = slideshow.get({"doctype": "Website Slideshow Item"})
|
||||
for index, slide in enumerate(slides):
|
||||
values[f"slide_{index + 1}_image"] = slide.image
|
||||
values[f"slide_{index + 1}_title"] = slide.heading
|
||||
@@ -110,68 +104,64 @@ class ItemGroup(NestedSet, WebsiteGenerator):
|
||||
|
||||
def validate_item_group_defaults(self):
|
||||
from erpnext.stock.doctype.item.item import validate_item_default_company_links
|
||||
|
||||
validate_item_default_company_links(self.item_group_defaults)
|
||||
|
||||
|
||||
def get_child_groups_for_website(item_group_name, immediate=False, include_self=False):
|
||||
"""Returns child item groups *excluding* passed group."""
|
||||
item_group = frappe.get_cached_value("Item Group", item_group_name, ["lft", "rgt"], as_dict=1)
|
||||
filters = {
|
||||
"lft": [">", item_group.lft],
|
||||
"rgt": ["<", item_group.rgt],
|
||||
"show_in_website": 1
|
||||
}
|
||||
filters = {"lft": [">", item_group.lft], "rgt": ["<", item_group.rgt], "show_in_website": 1}
|
||||
|
||||
if immediate:
|
||||
filters["parent_item_group"] = item_group_name
|
||||
|
||||
if include_self:
|
||||
filters.update({
|
||||
"lft": [">=", item_group.lft],
|
||||
"rgt": ["<=", item_group.rgt]
|
||||
})
|
||||
filters.update({"lft": [">=", item_group.lft], "rgt": ["<=", item_group.rgt]})
|
||||
|
||||
return frappe.get_all("Item Group", filters=filters, fields=["name", "route"], order_by="name")
|
||||
|
||||
return frappe.get_all(
|
||||
"Item Group",
|
||||
filters=filters,
|
||||
fields=["name", "route"],
|
||||
order_by="name"
|
||||
)
|
||||
|
||||
def get_child_item_groups(item_group_name):
|
||||
item_group = frappe.get_cached_value("Item Group",
|
||||
item_group_name, ["lft", "rgt"], as_dict=1)
|
||||
item_group = frappe.get_cached_value("Item Group", item_group_name, ["lft", "rgt"], as_dict=1)
|
||||
|
||||
child_item_groups = [d.name for d in frappe.get_all('Item Group',
|
||||
filters= {'lft': ('>=', item_group.lft),'rgt': ('<=', item_group.rgt)})]
|
||||
child_item_groups = [
|
||||
d.name
|
||||
for d in frappe.get_all(
|
||||
"Item Group", filters={"lft": (">=", item_group.lft), "rgt": ("<=", item_group.rgt)}
|
||||
)
|
||||
]
|
||||
|
||||
return child_item_groups or {}
|
||||
|
||||
|
||||
def get_item_for_list_in_html(context):
|
||||
# add missing absolute link in files
|
||||
# user may forget it during upload
|
||||
if (context.get("website_image") or "").startswith("files/"):
|
||||
context["website_image"] = "/" + quote(context["website_image"])
|
||||
|
||||
context["show_availability_status"] = cint(frappe.db.get_single_value('E Commerce Settings',
|
||||
'show_availability_status'))
|
||||
context["show_availability_status"] = cint(
|
||||
frappe.db.get_single_value("E Commerce Settings", "show_availability_status")
|
||||
)
|
||||
|
||||
products_template = 'templates/includes/products_as_list.html'
|
||||
products_template = "templates/includes/products_as_list.html"
|
||||
|
||||
return frappe.get_template(products_template).render(context)
|
||||
|
||||
|
||||
def get_parent_item_groups(item_group_name, from_item=False):
|
||||
base_nav_page = {"name": _("Shop by Category"), "route":"/shop-by-category"}
|
||||
base_nav_page = {"name": _("Shop by Category"), "route": "/shop-by-category"}
|
||||
|
||||
if from_item and frappe.request.environ.get("HTTP_REFERER"):
|
||||
# base page after 'Home' will vary on Item page
|
||||
last_page = frappe.request.environ["HTTP_REFERER"].split('/')[-1]
|
||||
last_page = frappe.request.environ["HTTP_REFERER"].split("/")[-1]
|
||||
if last_page and last_page in ("shop-by-category", "all-products"):
|
||||
base_nav_page_title = " ".join(last_page.split("-")).title()
|
||||
base_nav_page = {"name": _(base_nav_page_title), "route":"/"+last_page}
|
||||
base_nav_page = {"name": _(base_nav_page_title), "route": "/" + last_page}
|
||||
|
||||
base_parents = [
|
||||
{"name": _("Home"), "route":"/"},
|
||||
{"name": _("Home"), "route": "/"},
|
||||
base_nav_page,
|
||||
]
|
||||
|
||||
@@ -179,21 +169,27 @@ def get_parent_item_groups(item_group_name, from_item=False):
|
||||
return base_parents
|
||||
|
||||
item_group = frappe.db.get_value("Item Group", item_group_name, ["lft", "rgt"], as_dict=1)
|
||||
parent_groups = frappe.db.sql("""select name, route from `tabItem Group`
|
||||
parent_groups = frappe.db.sql(
|
||||
"""select name, route from `tabItem Group`
|
||||
where lft <= %s and rgt >= %s
|
||||
and show_in_website=1
|
||||
order by lft asc""", (item_group.lft, item_group.rgt), as_dict=True)
|
||||
order by lft asc""",
|
||||
(item_group.lft, item_group.rgt),
|
||||
as_dict=True,
|
||||
)
|
||||
|
||||
return base_parents + parent_groups
|
||||
|
||||
|
||||
def invalidate_cache_for(doc, item_group=None):
|
||||
if not item_group:
|
||||
item_group = doc.name
|
||||
|
||||
for d in get_parent_item_groups(item_group):
|
||||
item_group_name = frappe.db.get_value("Item Group", d.get('name'))
|
||||
item_group_name = frappe.db.get_value("Item Group", d.get("name"))
|
||||
if item_group_name:
|
||||
clear_cache(frappe.db.get_value('Item Group', item_group_name, 'route'))
|
||||
clear_cache(frappe.db.get_value("Item Group", item_group_name, "route"))
|
||||
|
||||
|
||||
def get_item_group_defaults(item, company):
|
||||
item = frappe.get_cached_doc("Item", item)
|
||||
|
||||
@@ -14,7 +14,8 @@ from frappe.utils.nestedset import (
|
||||
rebuild_tree,
|
||||
)
|
||||
|
||||
test_records = frappe.get_test_records('Item Group')
|
||||
test_records = frappe.get_test_records("Item Group")
|
||||
|
||||
|
||||
class TestItem(unittest.TestCase):
|
||||
def test_basic_tree(self, records=None):
|
||||
@@ -25,12 +26,12 @@ class TestItem(unittest.TestCase):
|
||||
records = test_records[2:]
|
||||
|
||||
for item_group in records:
|
||||
lft, rgt, parent_item_group = frappe.db.get_value("Item Group", item_group["item_group_name"],
|
||||
["lft", "rgt", "parent_item_group"])
|
||||
lft, rgt, parent_item_group = frappe.db.get_value(
|
||||
"Item Group", item_group["item_group_name"], ["lft", "rgt", "parent_item_group"]
|
||||
)
|
||||
|
||||
if parent_item_group:
|
||||
parent_lft, parent_rgt = frappe.db.get_value("Item Group", parent_item_group,
|
||||
["lft", "rgt"])
|
||||
parent_lft, parent_rgt = frappe.db.get_value("Item Group", parent_item_group, ["lft", "rgt"])
|
||||
else:
|
||||
# root
|
||||
parent_lft = min_lft - 1
|
||||
@@ -55,8 +56,11 @@ class TestItem(unittest.TestCase):
|
||||
def get_no_of_children(item_groups, no_of_children):
|
||||
children = []
|
||||
for ig in item_groups:
|
||||
children += frappe.db.sql_list("""select name from `tabItem Group`
|
||||
where ifnull(parent_item_group, '')=%s""", ig or '')
|
||||
children += frappe.db.sql_list(
|
||||
"""select name from `tabItem Group`
|
||||
where ifnull(parent_item_group, '')=%s""",
|
||||
ig or "",
|
||||
)
|
||||
|
||||
if len(children):
|
||||
return get_no_of_children(children, no_of_children + len(children))
|
||||
@@ -119,7 +123,10 @@ class TestItem(unittest.TestCase):
|
||||
|
||||
def print_tree(self):
|
||||
import json
|
||||
print(json.dumps(frappe.db.sql("select name, lft, rgt from `tabItem Group` order by lft"), indent=1))
|
||||
|
||||
print(
|
||||
json.dumps(frappe.db.sql("select name, lft, rgt from `tabItem Group` order by lft"), indent=1)
|
||||
)
|
||||
|
||||
def test_move_leaf_into_another_group(self):
|
||||
# before move
|
||||
@@ -149,12 +156,20 @@ class TestItem(unittest.TestCase):
|
||||
|
||||
def test_delete_leaf(self):
|
||||
# for checking later
|
||||
parent_item_group = frappe.db.get_value("Item Group", "_Test Item Group B - 3", "parent_item_group")
|
||||
parent_item_group = frappe.db.get_value(
|
||||
"Item Group", "_Test Item Group B - 3", "parent_item_group"
|
||||
)
|
||||
rgt = frappe.db.get_value("Item Group", parent_item_group, "rgt")
|
||||
|
||||
ancestors = get_ancestors_of("Item Group", "_Test Item Group B - 3")
|
||||
ancestors = frappe.db.sql("""select name, rgt from `tabItem Group`
|
||||
where name in ({})""".format(", ".join(["%s"]*len(ancestors))), tuple(ancestors), as_dict=True)
|
||||
ancestors = frappe.db.sql(
|
||||
"""select name, rgt from `tabItem Group`
|
||||
where name in ({})""".format(
|
||||
", ".join(["%s"] * len(ancestors))
|
||||
),
|
||||
tuple(ancestors),
|
||||
as_dict=True,
|
||||
)
|
||||
|
||||
frappe.delete_doc("Item Group", "_Test Item Group B - 3")
|
||||
records_to_test = test_records[2:]
|
||||
@@ -173,7 +188,9 @@ class TestItem(unittest.TestCase):
|
||||
|
||||
def test_delete_group(self):
|
||||
# cannot delete group with child, but can delete leaf
|
||||
self.assertRaises(NestedSetChildExistsError, frappe.delete_doc, "Item Group", "_Test Item Group B")
|
||||
self.assertRaises(
|
||||
NestedSetChildExistsError, frappe.delete_doc, "Item Group", "_Test Item Group B"
|
||||
)
|
||||
|
||||
def test_merge_groups(self):
|
||||
frappe.rename_doc("Item Group", "_Test Item Group B", "_Test Item Group C", merge=True)
|
||||
@@ -186,8 +203,10 @@ class TestItem(unittest.TestCase):
|
||||
self.test_basic_tree()
|
||||
|
||||
# move its children back
|
||||
for name in frappe.db.sql_list("""select name from `tabItem Group`
|
||||
where parent_item_group='_Test Item Group C'"""):
|
||||
for name in frappe.db.sql_list(
|
||||
"""select name from `tabItem Group`
|
||||
where parent_item_group='_Test Item Group C'"""
|
||||
):
|
||||
|
||||
doc = frappe.get_doc("Item Group", name)
|
||||
doc.parent_item_group = "_Test Item Group B"
|
||||
@@ -206,9 +225,21 @@ class TestItem(unittest.TestCase):
|
||||
self.test_basic_tree()
|
||||
|
||||
def test_merge_leaf_into_group(self):
|
||||
self.assertRaises(NestedSetInvalidMergeError, frappe.rename_doc, "Item Group", "_Test Item Group B - 3",
|
||||
"_Test Item Group B", merge=True)
|
||||
self.assertRaises(
|
||||
NestedSetInvalidMergeError,
|
||||
frappe.rename_doc,
|
||||
"Item Group",
|
||||
"_Test Item Group B - 3",
|
||||
"_Test Item Group B",
|
||||
merge=True,
|
||||
)
|
||||
|
||||
def test_merge_group_into_leaf(self):
|
||||
self.assertRaises(NestedSetInvalidMergeError, frappe.rename_doc, "Item Group", "_Test Item Group B",
|
||||
"_Test Item Group B - 3", merge=True)
|
||||
self.assertRaises(
|
||||
NestedSetInvalidMergeError,
|
||||
frappe.rename_doc,
|
||||
"Item Group",
|
||||
"_Test Item Group B",
|
||||
"_Test Item Group B - 3",
|
||||
merge=True,
|
||||
)
|
||||
|
||||
@@ -11,15 +11,25 @@ from frappe.permissions import get_doctypes_with_read
|
||||
from frappe.utils import cint, cstr
|
||||
|
||||
|
||||
class NamingSeriesNotSetError(frappe.ValidationError): pass
|
||||
class NamingSeriesNotSetError(frappe.ValidationError):
|
||||
pass
|
||||
|
||||
|
||||
class NamingSeries(Document):
|
||||
@frappe.whitelist()
|
||||
def get_transactions(self, arg=None):
|
||||
doctypes = list(set(frappe.db.sql_list("""select parent
|
||||
from `tabDocField` df where fieldname='naming_series'""")
|
||||
+ frappe.db.sql_list("""select dt from `tabCustom Field`
|
||||
where fieldname='naming_series'""")))
|
||||
doctypes = list(
|
||||
set(
|
||||
frappe.db.sql_list(
|
||||
"""select parent
|
||||
from `tabDocField` df where fieldname='naming_series'"""
|
||||
)
|
||||
+ frappe.db.sql_list(
|
||||
"""select dt from `tabCustom Field`
|
||||
where fieldname='naming_series'"""
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
doctypes = list(set(get_doctypes_with_read()).intersection(set(doctypes)))
|
||||
prefixes = ""
|
||||
@@ -28,8 +38,8 @@ class NamingSeries(Document):
|
||||
try:
|
||||
options = self.get_options(d)
|
||||
except frappe.DoesNotExistError:
|
||||
frappe.msgprint(_('Unable to find DocType {0}').format(d))
|
||||
#frappe.pass_does_not_exist_error()
|
||||
frappe.msgprint(_("Unable to find DocType {0}").format(d))
|
||||
# frappe.pass_does_not_exist_error()
|
||||
continue
|
||||
|
||||
if options:
|
||||
@@ -37,17 +47,21 @@ class NamingSeries(Document):
|
||||
prefixes.replace("\n\n", "\n")
|
||||
prefixes = prefixes.split("\n")
|
||||
|
||||
custom_prefixes = frappe.get_all('DocType', fields=["autoname"],
|
||||
filters={"name": ('not in', doctypes), "autoname":('like', '%.#%'), 'module': ('not in', ['Core'])})
|
||||
custom_prefixes = frappe.get_all(
|
||||
"DocType",
|
||||
fields=["autoname"],
|
||||
filters={
|
||||
"name": ("not in", doctypes),
|
||||
"autoname": ("like", "%.#%"),
|
||||
"module": ("not in", ["Core"]),
|
||||
},
|
||||
)
|
||||
if custom_prefixes:
|
||||
prefixes = prefixes + [d.autoname.rsplit('.', 1)[0] for d in custom_prefixes]
|
||||
prefixes = prefixes + [d.autoname.rsplit(".", 1)[0] for d in custom_prefixes]
|
||||
|
||||
prefixes = "\n".join(sorted(prefixes))
|
||||
|
||||
return {
|
||||
"transactions": "\n".join([''] + sorted(doctypes)),
|
||||
"prefixes": prefixes
|
||||
}
|
||||
return {"transactions": "\n".join([""] + sorted(doctypes)), "prefixes": prefixes}
|
||||
|
||||
def scrub_options_list(self, ol):
|
||||
options = list(filter(lambda x: x, [cstr(n).strip() for n in ol]))
|
||||
@@ -64,7 +78,7 @@ class NamingSeries(Document):
|
||||
self.set_series_for(self.select_doc_for_series, series_list)
|
||||
|
||||
# create series
|
||||
map(self.insert_series, [d.split('.')[0] for d in series_list if d.strip()])
|
||||
map(self.insert_series, [d.split(".")[0] for d in series_list if d.strip()])
|
||||
|
||||
msgprint(_("Series Updated"))
|
||||
|
||||
@@ -82,32 +96,35 @@ class NamingSeries(Document):
|
||||
self.validate_series_name(i)
|
||||
|
||||
if options and self.user_must_always_select:
|
||||
options = [''] + options
|
||||
options = [""] + options
|
||||
|
||||
default = options[0] if options else ''
|
||||
default = options[0] if options else ""
|
||||
|
||||
# update in property setter
|
||||
prop_dict = {'options': "\n".join(options), 'default': default}
|
||||
prop_dict = {"options": "\n".join(options), "default": default}
|
||||
|
||||
for prop in prop_dict:
|
||||
ps_exists = frappe.db.get_value("Property Setter",
|
||||
{"field_name": 'naming_series', 'doc_type': doctype, 'property': prop})
|
||||
ps_exists = frappe.db.get_value(
|
||||
"Property Setter", {"field_name": "naming_series", "doc_type": doctype, "property": prop}
|
||||
)
|
||||
|
||||
if ps_exists:
|
||||
ps = frappe.get_doc('Property Setter', ps_exists)
|
||||
ps = frappe.get_doc("Property Setter", ps_exists)
|
||||
ps.value = prop_dict[prop]
|
||||
ps.save()
|
||||
else:
|
||||
ps = frappe.get_doc({
|
||||
'doctype': 'Property Setter',
|
||||
'doctype_or_field': 'DocField',
|
||||
'doc_type': doctype,
|
||||
'field_name': 'naming_series',
|
||||
'property': prop,
|
||||
'value': prop_dict[prop],
|
||||
'property_type': 'Text',
|
||||
'__islocal': 1
|
||||
})
|
||||
ps = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Property Setter",
|
||||
"doctype_or_field": "DocField",
|
||||
"doc_type": doctype,
|
||||
"field_name": "naming_series",
|
||||
"property": prop,
|
||||
"value": prop_dict[prop],
|
||||
"property_type": "Text",
|
||||
"__islocal": 1,
|
||||
}
|
||||
)
|
||||
ps.save()
|
||||
|
||||
self.set_options = "\n".join(options)
|
||||
@@ -115,16 +132,22 @@ class NamingSeries(Document):
|
||||
frappe.clear_cache(doctype=doctype)
|
||||
|
||||
def check_duplicate(self):
|
||||
parent = list(set(
|
||||
frappe.db.sql_list("""select dt.name
|
||||
parent = list(
|
||||
set(
|
||||
frappe.db.sql_list(
|
||||
"""select dt.name
|
||||
from `tabDocField` df, `tabDocType` dt
|
||||
where dt.name = df.parent and df.fieldname='naming_series' and dt.name != %s""",
|
||||
self.select_doc_for_series)
|
||||
+ frappe.db.sql_list("""select dt.name
|
||||
self.select_doc_for_series,
|
||||
)
|
||||
+ frappe.db.sql_list(
|
||||
"""select dt.name
|
||||
from `tabCustom Field` df, `tabDocType` dt
|
||||
where dt.name = df.dt and df.fieldname='naming_series' and dt.name != %s""",
|
||||
self.select_doc_for_series)
|
||||
))
|
||||
self.select_doc_for_series,
|
||||
)
|
||||
)
|
||||
)
|
||||
sr = [[frappe.get_meta(p).get_field("naming_series").options, p] for p in parent]
|
||||
dt = frappe.get_doc("DocType", self.select_doc_for_series)
|
||||
options = self.scrub_options_list(self.set_options.split("\n"))
|
||||
@@ -132,14 +155,17 @@ class NamingSeries(Document):
|
||||
validate_series(dt, series)
|
||||
for i in sr:
|
||||
if i[0]:
|
||||
existing_series = [d.split('.')[0] for d in i[0].split("\n")]
|
||||
existing_series = [d.split(".")[0] for d in i[0].split("\n")]
|
||||
if series.split(".")[0] in existing_series:
|
||||
frappe.throw(_("Series {0} already used in {1}").format(series,i[1]))
|
||||
frappe.throw(_("Series {0} already used in {1}").format(series, i[1]))
|
||||
|
||||
def validate_series_name(self, n):
|
||||
import re
|
||||
|
||||
if not re.match(r"^[\w\- \/.#{}]+$", n, re.UNICODE):
|
||||
throw(_('Special Characters except "-", "#", ".", "/", "{" and "}" not allowed in naming series'))
|
||||
throw(
|
||||
_('Special Characters except "-", "#", ".", "/", "{" and "}" not allowed in naming series')
|
||||
)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_options(self, arg=None):
|
||||
@@ -151,12 +177,11 @@ class NamingSeries(Document):
|
||||
"""get series current"""
|
||||
if self.prefix:
|
||||
prefix = self.parse_naming_series()
|
||||
self.current_value = frappe.db.get_value("Series",
|
||||
prefix, "current", order_by = "name")
|
||||
self.current_value = frappe.db.get_value("Series", prefix, "current", order_by="name")
|
||||
|
||||
def insert_series(self, series):
|
||||
"""insert series if missing"""
|
||||
if frappe.db.get_value('Series', series, 'name', order_by="name") == None:
|
||||
if frappe.db.get_value("Series", series, "name", order_by="name") == None:
|
||||
frappe.db.sql("insert into tabSeries (name, current) values (%s, 0)", (series))
|
||||
|
||||
@frappe.whitelist()
|
||||
@@ -164,14 +189,15 @@ class NamingSeries(Document):
|
||||
if self.prefix:
|
||||
prefix = self.parse_naming_series()
|
||||
self.insert_series(prefix)
|
||||
frappe.db.sql("update `tabSeries` set current = %s where name = %s",
|
||||
(cint(self.current_value), prefix))
|
||||
frappe.db.sql(
|
||||
"update `tabSeries` set current = %s where name = %s", (cint(self.current_value), prefix)
|
||||
)
|
||||
msgprint(_("Series Updated Successfully"))
|
||||
else:
|
||||
msgprint(_("Please select prefix first"))
|
||||
|
||||
def parse_naming_series(self):
|
||||
parts = self.prefix.split('.')
|
||||
parts = self.prefix.split(".")
|
||||
|
||||
# Remove ### from the end of series
|
||||
if parts[-1] == "#" * len(parts[-1]):
|
||||
@@ -180,34 +206,59 @@ class NamingSeries(Document):
|
||||
prefix = parse_naming_series(parts)
|
||||
return prefix
|
||||
|
||||
def set_by_naming_series(doctype, fieldname, naming_series, hide_name_field=True, make_mandatory=1):
|
||||
|
||||
def set_by_naming_series(
|
||||
doctype, fieldname, naming_series, hide_name_field=True, make_mandatory=1
|
||||
):
|
||||
from frappe.custom.doctype.property_setter.property_setter import make_property_setter
|
||||
|
||||
if naming_series:
|
||||
make_property_setter(doctype, "naming_series", "hidden", 0, "Check", validate_fields_for_doctype=False)
|
||||
make_property_setter(doctype, "naming_series", "reqd", make_mandatory, "Check", validate_fields_for_doctype=False)
|
||||
make_property_setter(
|
||||
doctype, "naming_series", "hidden", 0, "Check", validate_fields_for_doctype=False
|
||||
)
|
||||
make_property_setter(
|
||||
doctype, "naming_series", "reqd", make_mandatory, "Check", validate_fields_for_doctype=False
|
||||
)
|
||||
|
||||
# set values for mandatory
|
||||
try:
|
||||
frappe.db.sql("""update `tab{doctype}` set naming_series={s} where
|
||||
ifnull(naming_series, '')=''""".format(doctype=doctype, s="%s"),
|
||||
get_default_naming_series(doctype))
|
||||
frappe.db.sql(
|
||||
"""update `tab{doctype}` set naming_series={s} where
|
||||
ifnull(naming_series, '')=''""".format(
|
||||
doctype=doctype, s="%s"
|
||||
),
|
||||
get_default_naming_series(doctype),
|
||||
)
|
||||
except NamingSeriesNotSetError:
|
||||
pass
|
||||
|
||||
if hide_name_field:
|
||||
make_property_setter(doctype, fieldname, "reqd", 0, "Check", validate_fields_for_doctype=False)
|
||||
make_property_setter(doctype, fieldname, "hidden", 1, "Check", validate_fields_for_doctype=False)
|
||||
make_property_setter(
|
||||
doctype, fieldname, "hidden", 1, "Check", validate_fields_for_doctype=False
|
||||
)
|
||||
else:
|
||||
make_property_setter(doctype, "naming_series", "reqd", 0, "Check", validate_fields_for_doctype=False)
|
||||
make_property_setter(doctype, "naming_series", "hidden", 1, "Check", validate_fields_for_doctype=False)
|
||||
make_property_setter(
|
||||
doctype, "naming_series", "reqd", 0, "Check", validate_fields_for_doctype=False
|
||||
)
|
||||
make_property_setter(
|
||||
doctype, "naming_series", "hidden", 1, "Check", validate_fields_for_doctype=False
|
||||
)
|
||||
|
||||
if hide_name_field:
|
||||
make_property_setter(doctype, fieldname, "hidden", 0, "Check", validate_fields_for_doctype=False)
|
||||
make_property_setter(
|
||||
doctype, fieldname, "hidden", 0, "Check", validate_fields_for_doctype=False
|
||||
)
|
||||
make_property_setter(doctype, fieldname, "reqd", 1, "Check", validate_fields_for_doctype=False)
|
||||
|
||||
# set values for mandatory
|
||||
frappe.db.sql("""update `tab{doctype}` set `{fieldname}`=`name` where
|
||||
ifnull({fieldname}, '')=''""".format(doctype=doctype, fieldname=fieldname))
|
||||
frappe.db.sql(
|
||||
"""update `tab{doctype}` set `{fieldname}`=`name` where
|
||||
ifnull({fieldname}, '')=''""".format(
|
||||
doctype=doctype, fieldname=fieldname
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def get_default_naming_series(doctype):
|
||||
naming_series = frappe.get_meta(doctype).get_field("naming_series").options or ""
|
||||
@@ -215,7 +266,9 @@ def get_default_naming_series(doctype):
|
||||
out = naming_series[0] or (naming_series[1] if len(naming_series) > 1 else None)
|
||||
|
||||
if not out:
|
||||
frappe.throw(_("Please set Naming Series for {0} via Setup > Settings > Naming Series").format(doctype),
|
||||
NamingSeriesNotSetError)
|
||||
frappe.throw(
|
||||
_("Please set Naming Series for {0} via Setup > Settings > Naming Series").format(doctype),
|
||||
NamingSeriesNotSetError,
|
||||
)
|
||||
else:
|
||||
return out
|
||||
|
||||
@@ -9,18 +9,20 @@ from frappe.model.document import Document
|
||||
class PartyType(Document):
|
||||
pass
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_party_type(doctype, txt, searchfield, start, page_len, filters):
|
||||
cond = ''
|
||||
if filters and filters.get('account'):
|
||||
account_type = frappe.db.get_value('Account', filters.get('account'), 'account_type')
|
||||
cond = ""
|
||||
if filters and filters.get("account"):
|
||||
account_type = frappe.db.get_value("Account", filters.get("account"), "account_type")
|
||||
cond = "and account_type = '%s'" % account_type
|
||||
|
||||
return frappe.db.sql("""select name from `tabParty Type`
|
||||
return frappe.db.sql(
|
||||
"""select name from `tabParty Type`
|
||||
where `{key}` LIKE %(txt)s {cond}
|
||||
order by name limit %(start)s, %(page_len)s"""
|
||||
.format(key=searchfield, cond=cond), {
|
||||
'txt': '%' + txt + '%',
|
||||
'start': start, 'page_len': page_len
|
||||
})
|
||||
order by name limit %(start)s, %(page_len)s""".format(
|
||||
key=searchfield, cond=cond
|
||||
),
|
||||
{"txt": "%" + txt + "%", "start": start, "page_len": page_len},
|
||||
)
|
||||
|
||||
@@ -5,5 +5,6 @@ import unittest
|
||||
|
||||
# test_records = frappe.get_test_records('Party Type')
|
||||
|
||||
|
||||
class TestPartyType(unittest.TestCase):
|
||||
pass
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
import frappe
|
||||
|
||||
test_records = frappe.get_test_records('Print Heading')
|
||||
test_records = frappe.get_test_records("Print Heading")
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
import frappe
|
||||
|
||||
test_records = frappe.get_test_records('Quotation Lost Reason')
|
||||
test_records = frappe.get_test_records("Quotation Lost Reason")
|
||||
|
||||
@@ -10,9 +10,9 @@ from frappe.website.website_generator import WebsiteGenerator
|
||||
|
||||
class SalesPartner(WebsiteGenerator):
|
||||
website = frappe._dict(
|
||||
page_title_field = "partner_name",
|
||||
condition_field = "show_in_website",
|
||||
template = "templates/generators/sales_partner.html"
|
||||
page_title_field="partner_name",
|
||||
condition_field="show_in_website",
|
||||
template="templates/generators/sales_partner.html",
|
||||
)
|
||||
|
||||
def onload(self):
|
||||
@@ -30,18 +30,25 @@ class SalesPartner(WebsiteGenerator):
|
||||
self.partner_website = "http://" + self.partner_website
|
||||
|
||||
def get_context(self, context):
|
||||
address = frappe.db.get_value("Address",
|
||||
{"sales_partner": self.name, "is_primary_address": 1},
|
||||
"*", as_dict=True)
|
||||
address = frappe.db.get_value(
|
||||
"Address", {"sales_partner": self.name, "is_primary_address": 1}, "*", as_dict=True
|
||||
)
|
||||
if address:
|
||||
city_state = ", ".join(filter(None, [address.city, address.state]))
|
||||
address_rows = [address.address_line1, address.address_line2,
|
||||
city_state, address.pincode, address.country]
|
||||
address_rows = [
|
||||
address.address_line1,
|
||||
address.address_line2,
|
||||
city_state,
|
||||
address.pincode,
|
||||
address.country,
|
||||
]
|
||||
|
||||
context.update({
|
||||
"email": address.email_id,
|
||||
"partner_address": filter_strip_join(address_rows, "\n<br>"),
|
||||
"phone": filter_strip_join(cstr(address.phone).split(","), "\n<br>")
|
||||
})
|
||||
context.update(
|
||||
{
|
||||
"email": address.email_id,
|
||||
"partner_address": filter_strip_join(address_rows, "\n<br>"),
|
||||
"phone": filter_strip_join(cstr(address.phone).split(","), "\n<br>"),
|
||||
}
|
||||
)
|
||||
|
||||
return context
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
|
||||
import frappe
|
||||
|
||||
test_records = frappe.get_test_records('Sales Partner')
|
||||
test_records = frappe.get_test_records("Sales Partner")
|
||||
|
||||
test_ignore = ["Item Group"]
|
||||
|
||||
@@ -11,13 +11,13 @@ from erpnext import get_default_currency
|
||||
|
||||
|
||||
class SalesPerson(NestedSet):
|
||||
nsm_parent_field = 'parent_sales_person'
|
||||
nsm_parent_field = "parent_sales_person"
|
||||
|
||||
def validate(self):
|
||||
if not self.parent_sales_person:
|
||||
self.parent_sales_person = get_root_of("Sales Person")
|
||||
|
||||
for d in self.get('targets') or []:
|
||||
for d in self.get("targets") or []:
|
||||
if not flt(d.target_qty) and not flt(d.target_amount):
|
||||
frappe.throw(_("Either target qty or target amount is mandatory."))
|
||||
self.validate_employee_id()
|
||||
@@ -28,17 +28,20 @@ class SalesPerson(NestedSet):
|
||||
def load_dashboard_info(self):
|
||||
company_default_currency = get_default_currency()
|
||||
|
||||
allocated_amount = frappe.db.sql("""
|
||||
allocated_amount = frappe.db.sql(
|
||||
"""
|
||||
select sum(allocated_amount)
|
||||
from `tabSales Team`
|
||||
where sales_person = %s and docstatus=1 and parenttype = 'Sales Order'
|
||||
""",(self.sales_person_name))
|
||||
""",
|
||||
(self.sales_person_name),
|
||||
)
|
||||
|
||||
info = {}
|
||||
info["allocated_amount"] = flt(allocated_amount[0][0]) if allocated_amount else 0
|
||||
info["currency"] = company_default_currency
|
||||
|
||||
self.set_onload('dashboard_info', info)
|
||||
self.set_onload("dashboard_info", info)
|
||||
|
||||
def on_update(self):
|
||||
super(SalesPerson, self).on_update()
|
||||
@@ -57,30 +60,46 @@ class SalesPerson(NestedSet):
|
||||
sales_person = frappe.db.get_value("Sales Person", {"employee": self.employee})
|
||||
|
||||
if sales_person and sales_person != self.name:
|
||||
frappe.throw(_("Another Sales Person {0} exists with the same Employee id").format(sales_person))
|
||||
frappe.throw(
|
||||
_("Another Sales Person {0} exists with the same Employee id").format(sales_person)
|
||||
)
|
||||
|
||||
|
||||
def on_doctype_update():
|
||||
frappe.db.add_index("Sales Person", ["lft", "rgt"])
|
||||
|
||||
|
||||
def get_timeline_data(doctype, name):
|
||||
|
||||
out = {}
|
||||
|
||||
out.update(dict(frappe.db.sql('''select
|
||||
out.update(
|
||||
dict(
|
||||
frappe.db.sql(
|
||||
"""select
|
||||
unix_timestamp(dt.transaction_date), count(st.parenttype)
|
||||
from
|
||||
`tabSales Order` dt, `tabSales Team` st
|
||||
where
|
||||
st.sales_person = %s and st.parent = dt.name and dt.transaction_date > date_sub(curdate(), interval 1 year)
|
||||
group by dt.transaction_date ''', name)))
|
||||
group by dt.transaction_date """,
|
||||
name,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
sales_invoice = dict(frappe.db.sql('''select
|
||||
sales_invoice = dict(
|
||||
frappe.db.sql(
|
||||
"""select
|
||||
unix_timestamp(dt.posting_date), count(st.parenttype)
|
||||
from
|
||||
`tabSales Invoice` dt, `tabSales Team` st
|
||||
where
|
||||
st.sales_person = %s and st.parent = dt.name and dt.posting_date > date_sub(curdate(), interval 1 year)
|
||||
group by dt.posting_date ''', name))
|
||||
group by dt.posting_date """,
|
||||
name,
|
||||
)
|
||||
)
|
||||
|
||||
for key in sales_invoice:
|
||||
if out.get(key):
|
||||
@@ -88,13 +107,18 @@ def get_timeline_data(doctype, name):
|
||||
else:
|
||||
out[key] = sales_invoice[key]
|
||||
|
||||
delivery_note = dict(frappe.db.sql('''select
|
||||
delivery_note = dict(
|
||||
frappe.db.sql(
|
||||
"""select
|
||||
unix_timestamp(dt.posting_date), count(st.parenttype)
|
||||
from
|
||||
`tabDelivery Note` dt, `tabSales Team` st
|
||||
where
|
||||
st.sales_person = %s and st.parent = dt.name and dt.posting_date > date_sub(curdate(), interval 1 year)
|
||||
group by dt.posting_date ''', name))
|
||||
group by dt.posting_date """,
|
||||
name,
|
||||
)
|
||||
)
|
||||
|
||||
for key in delivery_note:
|
||||
if out.get(key):
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
|
||||
from frappe import _
|
||||
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'heatmap': True,
|
||||
'heatmap_message': _('This is based on transactions against this Sales Person. See timeline below for details'),
|
||||
'fieldname': 'sales_person',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Sales'),
|
||||
'items': ['Sales Order', 'Delivery Note', 'Sales Invoice']
|
||||
},
|
||||
]
|
||||
"heatmap": True,
|
||||
"heatmap_message": _(
|
||||
"This is based on transactions against this Sales Person. See timeline below for details"
|
||||
),
|
||||
"fieldname": "sales_person",
|
||||
"transactions": [
|
||||
{"label": _("Sales"), "items": ["Sales Order", "Delivery Note", "Sales Invoice"]},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -5,6 +5,6 @@ test_dependencies = ["Employee"]
|
||||
|
||||
import frappe
|
||||
|
||||
test_records = frappe.get_test_records('Sales Person')
|
||||
test_records = frappe.get_test_records("Sales Person")
|
||||
|
||||
test_ignore = ["Item Group"]
|
||||
|
||||
@@ -7,7 +7,7 @@ from frappe.utils.nestedset import NestedSet, get_root_of
|
||||
|
||||
|
||||
class SupplierGroup(NestedSet):
|
||||
nsm_parent_field = 'parent_supplier_group'
|
||||
nsm_parent_field = "parent_supplier_group"
|
||||
|
||||
def validate(self):
|
||||
if not self.parent_supplier_group:
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
import frappe
|
||||
|
||||
test_records = frappe.get_test_records('Supplier Group')
|
||||
test_records = frappe.get_test_records("Supplier Group")
|
||||
|
||||
@@ -16,9 +16,15 @@ class TermsandConditions(Document):
|
||||
def validate(self):
|
||||
if self.terms:
|
||||
validate_template(self.terms)
|
||||
if not cint(self.buying) and not cint(self.selling) and not cint(self.hr) and not cint(self.disabled):
|
||||
if (
|
||||
not cint(self.buying)
|
||||
and not cint(self.selling)
|
||||
and not cint(self.hr)
|
||||
and not cint(self.disabled)
|
||||
):
|
||||
throw(_("At least one of the Applicable Modules should be selected"))
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_terms_and_conditions(template_name, doc):
|
||||
if isinstance(doc, string_types):
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
import frappe
|
||||
|
||||
test_records = frappe.get_test_records('Terms and Conditions')
|
||||
test_records = frappe.get_test_records("Terms and Conditions")
|
||||
|
||||
@@ -9,13 +9,13 @@ from frappe.utils.nestedset import NestedSet, get_root_of
|
||||
|
||||
|
||||
class Territory(NestedSet):
|
||||
nsm_parent_field = 'parent_territory'
|
||||
nsm_parent_field = "parent_territory"
|
||||
|
||||
def validate(self):
|
||||
if not self.parent_territory:
|
||||
self.parent_territory = get_root_of("Territory")
|
||||
|
||||
for d in self.get('targets') or []:
|
||||
for d in self.get("targets") or []:
|
||||
if not flt(d.target_qty) and not flt(d.target_amount):
|
||||
frappe.throw(_("Either target qty or target amount is mandatory"))
|
||||
|
||||
@@ -23,5 +23,6 @@ class Territory(NestedSet):
|
||||
super(Territory, self).on_update()
|
||||
self.validate_one_root()
|
||||
|
||||
|
||||
def on_doctype_update():
|
||||
frappe.db.add_index("Territory", ["lft", "rgt"])
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
|
||||
import frappe
|
||||
|
||||
test_records = frappe.get_test_records('Territory')
|
||||
test_records = frappe.get_test_records("Territory")
|
||||
|
||||
test_ignore = ["Item Group"]
|
||||
|
||||
@@ -8,61 +8,51 @@ import frappe
|
||||
|
||||
class TestTransactionDeletionRecord(unittest.TestCase):
|
||||
def setUp(self):
|
||||
create_company('Dunder Mifflin Paper Co')
|
||||
create_company("Dunder Mifflin Paper Co")
|
||||
|
||||
def tearDown(self):
|
||||
frappe.db.rollback()
|
||||
|
||||
def test_doctypes_contain_company_field(self):
|
||||
tdr = create_transaction_deletion_request('Dunder Mifflin Paper Co')
|
||||
tdr = create_transaction_deletion_request("Dunder Mifflin Paper Co")
|
||||
for doctype in tdr.doctypes:
|
||||
contains_company = False
|
||||
doctype_fields = frappe.get_meta(doctype.doctype_name).as_dict()['fields']
|
||||
doctype_fields = frappe.get_meta(doctype.doctype_name).as_dict()["fields"]
|
||||
for doctype_field in doctype_fields:
|
||||
if doctype_field['fieldtype'] == 'Link' and doctype_field['options'] == 'Company':
|
||||
if doctype_field["fieldtype"] == "Link" and doctype_field["options"] == "Company":
|
||||
contains_company = True
|
||||
break
|
||||
self.assertTrue(contains_company)
|
||||
|
||||
def test_no_of_docs_is_correct(self):
|
||||
for i in range(5):
|
||||
create_task('Dunder Mifflin Paper Co')
|
||||
tdr = create_transaction_deletion_request('Dunder Mifflin Paper Co')
|
||||
create_task("Dunder Mifflin Paper Co")
|
||||
tdr = create_transaction_deletion_request("Dunder Mifflin Paper Co")
|
||||
for doctype in tdr.doctypes:
|
||||
if doctype.doctype_name == 'Task':
|
||||
if doctype.doctype_name == "Task":
|
||||
self.assertEqual(doctype.no_of_docs, 5)
|
||||
|
||||
def test_deletion_is_successful(self):
|
||||
create_task('Dunder Mifflin Paper Co')
|
||||
create_transaction_deletion_request('Dunder Mifflin Paper Co')
|
||||
tasks_containing_company = frappe.get_all('Task',
|
||||
filters = {
|
||||
'company' : 'Dunder Mifflin Paper Co'
|
||||
})
|
||||
create_task("Dunder Mifflin Paper Co")
|
||||
create_transaction_deletion_request("Dunder Mifflin Paper Co")
|
||||
tasks_containing_company = frappe.get_all("Task", filters={"company": "Dunder Mifflin Paper Co"})
|
||||
self.assertEqual(tasks_containing_company, [])
|
||||
|
||||
|
||||
def create_company(company_name):
|
||||
company = frappe.get_doc({
|
||||
'doctype': 'Company',
|
||||
'company_name': company_name,
|
||||
'default_currency': 'INR'
|
||||
})
|
||||
company.insert(ignore_if_duplicate = True)
|
||||
company = frappe.get_doc(
|
||||
{"doctype": "Company", "company_name": company_name, "default_currency": "INR"}
|
||||
)
|
||||
company.insert(ignore_if_duplicate=True)
|
||||
|
||||
|
||||
def create_transaction_deletion_request(company):
|
||||
tdr = frappe.get_doc({
|
||||
'doctype': 'Transaction Deletion Record',
|
||||
'company': company
|
||||
})
|
||||
tdr = frappe.get_doc({"doctype": "Transaction Deletion Record", "company": company})
|
||||
tdr.insert()
|
||||
tdr.submit()
|
||||
return tdr
|
||||
|
||||
|
||||
def create_task(company):
|
||||
task = frappe.get_doc({
|
||||
'doctype': 'Task',
|
||||
'company': company,
|
||||
'subject': 'Delete'
|
||||
})
|
||||
task = frappe.get_doc({"doctype": "Task", "company": company, "subject": "Delete"})
|
||||
task.insert()
|
||||
|
||||
@@ -11,15 +11,19 @@ from frappe.utils import cint
|
||||
|
||||
class TransactionDeletionRecord(Document):
|
||||
def validate(self):
|
||||
frappe.only_for('System Manager')
|
||||
frappe.only_for("System Manager")
|
||||
self.validate_doctypes_to_be_ignored()
|
||||
|
||||
def validate_doctypes_to_be_ignored(self):
|
||||
doctypes_to_be_ignored_list = get_doctypes_to_be_ignored()
|
||||
for doctype in self.doctypes_to_be_ignored:
|
||||
if doctype.doctype_name not in doctypes_to_be_ignored_list:
|
||||
frappe.throw(_("DocTypes should not be added manually to the 'Excluded DocTypes' table. You are only allowed to remove entries from it."),
|
||||
title=_("Not Allowed"))
|
||||
frappe.throw(
|
||||
_(
|
||||
"DocTypes should not be added manually to the 'Excluded DocTypes' table. You are only allowed to remove entries from it."
|
||||
),
|
||||
title=_("Not Allowed"),
|
||||
)
|
||||
|
||||
def before_submit(self):
|
||||
if not self.doctypes_to_be_ignored:
|
||||
@@ -34,38 +38,55 @@ class TransactionDeletionRecord(Document):
|
||||
def populate_doctypes_to_be_ignored_table(self):
|
||||
doctypes_to_be_ignored_list = get_doctypes_to_be_ignored()
|
||||
for doctype in doctypes_to_be_ignored_list:
|
||||
self.append('doctypes_to_be_ignored', {
|
||||
'doctype_name' : doctype
|
||||
})
|
||||
self.append("doctypes_to_be_ignored", {"doctype_name": doctype})
|
||||
|
||||
def delete_bins(self):
|
||||
frappe.db.sql("""delete from tabBin where warehouse in
|
||||
(select name from tabWarehouse where company=%s)""", self.company)
|
||||
frappe.db.sql(
|
||||
"""delete from tabBin where warehouse in
|
||||
(select name from tabWarehouse where company=%s)""",
|
||||
self.company,
|
||||
)
|
||||
|
||||
def delete_lead_addresses(self):
|
||||
"""Delete addresses to which leads are linked"""
|
||||
leads = frappe.get_all('Lead', filters={'company': self.company})
|
||||
leads = frappe.get_all("Lead", filters={"company": self.company})
|
||||
leads = ["'%s'" % row.get("name") for row in leads]
|
||||
addresses = []
|
||||
if leads:
|
||||
addresses = frappe.db.sql_list("""select parent from `tabDynamic Link` where link_name
|
||||
in ({leads})""".format(leads=",".join(leads)))
|
||||
addresses = frappe.db.sql_list(
|
||||
"""select parent from `tabDynamic Link` where link_name
|
||||
in ({leads})""".format(
|
||||
leads=",".join(leads)
|
||||
)
|
||||
)
|
||||
|
||||
if addresses:
|
||||
addresses = ["%s" % frappe.db.escape(addr) for addr in addresses]
|
||||
|
||||
frappe.db.sql("""delete from tabAddress where name in ({addresses}) and
|
||||
frappe.db.sql(
|
||||
"""delete from tabAddress where name in ({addresses}) and
|
||||
name not in (select distinct dl1.parent from `tabDynamic Link` dl1
|
||||
inner join `tabDynamic Link` dl2 on dl1.parent=dl2.parent
|
||||
and dl1.link_doctype<>dl2.link_doctype)""".format(addresses=",".join(addresses)))
|
||||
and dl1.link_doctype<>dl2.link_doctype)""".format(
|
||||
addresses=",".join(addresses)
|
||||
)
|
||||
)
|
||||
|
||||
frappe.db.sql("""delete from `tabDynamic Link` where link_doctype='Lead'
|
||||
and parenttype='Address' and link_name in ({leads})""".format(leads=",".join(leads)))
|
||||
frappe.db.sql(
|
||||
"""delete from `tabDynamic Link` where link_doctype='Lead'
|
||||
and parenttype='Address' and link_name in ({leads})""".format(
|
||||
leads=",".join(leads)
|
||||
)
|
||||
)
|
||||
|
||||
frappe.db.sql("""update tabCustomer set lead_name=NULL where lead_name in ({leads})""".format(leads=",".join(leads)))
|
||||
frappe.db.sql(
|
||||
"""update tabCustomer set lead_name=NULL where lead_name in ({leads})""".format(
|
||||
leads=",".join(leads)
|
||||
)
|
||||
)
|
||||
|
||||
def reset_company_values(self):
|
||||
company_obj = frappe.get_doc('Company', self.company)
|
||||
company_obj = frappe.get_doc("Company", self.company)
|
||||
company_obj.total_monthly_sales = 0
|
||||
company_obj.sales_monthly_history = None
|
||||
company_obj.save()
|
||||
@@ -76,24 +97,26 @@ class TransactionDeletionRecord(Document):
|
||||
|
||||
tables = self.get_all_child_doctypes()
|
||||
for docfield in docfields:
|
||||
if docfield['parent'] != self.doctype:
|
||||
no_of_docs = self.get_number_of_docs_linked_with_specified_company(docfield['parent'], docfield['fieldname'])
|
||||
if docfield["parent"] != self.doctype:
|
||||
no_of_docs = self.get_number_of_docs_linked_with_specified_company(
|
||||
docfield["parent"], docfield["fieldname"]
|
||||
)
|
||||
|
||||
if no_of_docs > 0:
|
||||
self.delete_version_log(docfield['parent'], docfield['fieldname'])
|
||||
self.delete_communications(docfield['parent'], docfield['fieldname'])
|
||||
self.populate_doctypes_table(tables, docfield['parent'], no_of_docs)
|
||||
self.delete_version_log(docfield["parent"], docfield["fieldname"])
|
||||
self.delete_communications(docfield["parent"], docfield["fieldname"])
|
||||
self.populate_doctypes_table(tables, docfield["parent"], no_of_docs)
|
||||
|
||||
self.delete_child_tables(docfield['parent'], docfield['fieldname'])
|
||||
self.delete_docs_linked_with_specified_company(docfield['parent'], docfield['fieldname'])
|
||||
self.delete_child_tables(docfield["parent"], docfield["fieldname"])
|
||||
self.delete_docs_linked_with_specified_company(docfield["parent"], docfield["fieldname"])
|
||||
|
||||
naming_series = frappe.db.get_value('DocType', docfield['parent'], 'autoname')
|
||||
naming_series = frappe.db.get_value("DocType", docfield["parent"], "autoname")
|
||||
if naming_series:
|
||||
if '#' in naming_series:
|
||||
self.update_naming_series(naming_series, docfield['parent'])
|
||||
if "#" in naming_series:
|
||||
self.update_naming_series(naming_series, docfield["parent"])
|
||||
|
||||
def get_doctypes_to_be_ignored_list(self):
|
||||
singles = frappe.get_all('DocType', filters = {'issingle': 1}, pluck = 'name')
|
||||
singles = frappe.get_all("DocType", filters={"issingle": 1}, pluck="name")
|
||||
doctypes_to_be_ignored_list = singles
|
||||
for doctype in self.doctypes_to_be_ignored:
|
||||
doctypes_to_be_ignored_list.append(doctype.doctype_name)
|
||||
@@ -101,81 +124,104 @@ class TransactionDeletionRecord(Document):
|
||||
return doctypes_to_be_ignored_list
|
||||
|
||||
def get_doctypes_with_company_field(self, doctypes_to_be_ignored_list):
|
||||
docfields = frappe.get_all('DocField',
|
||||
filters = {
|
||||
'fieldtype': 'Link',
|
||||
'options': 'Company',
|
||||
'parent': ['not in', doctypes_to_be_ignored_list]},
|
||||
fields=['parent', 'fieldname'])
|
||||
docfields = frappe.get_all(
|
||||
"DocField",
|
||||
filters={
|
||||
"fieldtype": "Link",
|
||||
"options": "Company",
|
||||
"parent": ["not in", doctypes_to_be_ignored_list],
|
||||
},
|
||||
fields=["parent", "fieldname"],
|
||||
)
|
||||
|
||||
return docfields
|
||||
|
||||
def get_all_child_doctypes(self):
|
||||
return frappe.get_all('DocType', filters = {'istable': 1}, pluck = 'name')
|
||||
return frappe.get_all("DocType", filters={"istable": 1}, pluck="name")
|
||||
|
||||
def get_number_of_docs_linked_with_specified_company(self, doctype, company_fieldname):
|
||||
return frappe.db.count(doctype, {company_fieldname : self.company})
|
||||
return frappe.db.count(doctype, {company_fieldname: self.company})
|
||||
|
||||
def populate_doctypes_table(self, tables, doctype, no_of_docs):
|
||||
if doctype not in tables:
|
||||
self.append('doctypes', {
|
||||
'doctype_name' : doctype,
|
||||
'no_of_docs' : no_of_docs
|
||||
})
|
||||
self.append("doctypes", {"doctype_name": doctype, "no_of_docs": no_of_docs})
|
||||
|
||||
def delete_child_tables(self, doctype, company_fieldname):
|
||||
parent_docs_to_be_deleted = frappe.get_all(doctype, {
|
||||
company_fieldname : self.company
|
||||
}, pluck = 'name')
|
||||
parent_docs_to_be_deleted = frappe.get_all(
|
||||
doctype, {company_fieldname: self.company}, pluck="name"
|
||||
)
|
||||
|
||||
child_tables = frappe.get_all('DocField', filters = {
|
||||
'fieldtype': 'Table',
|
||||
'parent': doctype
|
||||
}, pluck = 'options')
|
||||
child_tables = frappe.get_all(
|
||||
"DocField", filters={"fieldtype": "Table", "parent": doctype}, pluck="options"
|
||||
)
|
||||
|
||||
for table in child_tables:
|
||||
frappe.db.delete(table, {
|
||||
'parent': ['in', parent_docs_to_be_deleted]
|
||||
})
|
||||
frappe.db.delete(table, {"parent": ["in", parent_docs_to_be_deleted]})
|
||||
|
||||
def delete_docs_linked_with_specified_company(self, doctype, company_fieldname):
|
||||
frappe.db.delete(doctype, {
|
||||
company_fieldname : self.company
|
||||
})
|
||||
frappe.db.delete(doctype, {company_fieldname: self.company})
|
||||
|
||||
def update_naming_series(self, naming_series, doctype_name):
|
||||
if '.' in naming_series:
|
||||
prefix, hashes = naming_series.rsplit('.', 1)
|
||||
if "." in naming_series:
|
||||
prefix, hashes = naming_series.rsplit(".", 1)
|
||||
else:
|
||||
prefix, hashes = naming_series.rsplit('{', 1)
|
||||
last = frappe.db.sql("""select max(name) from `tab{0}`
|
||||
where name like %s""".format(doctype_name), prefix + '%')
|
||||
prefix, hashes = naming_series.rsplit("{", 1)
|
||||
last = frappe.db.sql(
|
||||
"""select max(name) from `tab{0}`
|
||||
where name like %s""".format(
|
||||
doctype_name
|
||||
),
|
||||
prefix + "%",
|
||||
)
|
||||
if last and last[0][0]:
|
||||
last = cint(last[0][0].replace(prefix, ''))
|
||||
last = cint(last[0][0].replace(prefix, ""))
|
||||
else:
|
||||
last = 0
|
||||
|
||||
frappe.db.sql("""update tabSeries set current = %s where name=%s""", (last, prefix))
|
||||
|
||||
def delete_version_log(self, doctype, company_fieldname):
|
||||
frappe.db.sql("""delete from `tabVersion` where ref_doctype=%s and docname in
|
||||
(select name from `tab{0}` where `{1}`=%s)""".format(doctype,
|
||||
company_fieldname), (doctype, self.company))
|
||||
frappe.db.sql(
|
||||
"""delete from `tabVersion` where ref_doctype=%s and docname in
|
||||
(select name from `tab{0}` where `{1}`=%s)""".format(
|
||||
doctype, company_fieldname
|
||||
),
|
||||
(doctype, self.company),
|
||||
)
|
||||
|
||||
def delete_communications(self, doctype, company_fieldname):
|
||||
reference_docs = frappe.get_all(doctype, filters={company_fieldname:self.company})
|
||||
reference_docs = frappe.get_all(doctype, filters={company_fieldname: self.company})
|
||||
reference_doc_names = [r.name for r in reference_docs]
|
||||
|
||||
communications = frappe.get_all('Communication', filters={'reference_doctype':doctype,'reference_name':['in', reference_doc_names]})
|
||||
communications = frappe.get_all(
|
||||
"Communication",
|
||||
filters={"reference_doctype": doctype, "reference_name": ["in", reference_doc_names]},
|
||||
)
|
||||
communication_names = [c.name for c in communications]
|
||||
|
||||
frappe.delete_doc('Communication', communication_names, ignore_permissions=True)
|
||||
frappe.delete_doc("Communication", communication_names, ignore_permissions=True)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_doctypes_to_be_ignored():
|
||||
doctypes_to_be_ignored_list = ['Account', 'Cost Center', 'Warehouse', 'Budget',
|
||||
'Party Account', 'Employee', 'Sales Taxes and Charges Template',
|
||||
'Purchase Taxes and Charges Template', 'POS Profile', 'BOM',
|
||||
'Company', 'Bank Account', 'Item Tax Template', 'Mode of Payment',
|
||||
'Item Default', 'Customer', 'Supplier', 'GST Account']
|
||||
doctypes_to_be_ignored_list = [
|
||||
"Account",
|
||||
"Cost Center",
|
||||
"Warehouse",
|
||||
"Budget",
|
||||
"Party Account",
|
||||
"Employee",
|
||||
"Sales Taxes and Charges Template",
|
||||
"Purchase Taxes and Charges Template",
|
||||
"POS Profile",
|
||||
"BOM",
|
||||
"Company",
|
||||
"Bank Account",
|
||||
"Item Tax Template",
|
||||
"Mode of Payment",
|
||||
"Item Default",
|
||||
"Customer",
|
||||
"Supplier",
|
||||
"GST Account",
|
||||
]
|
||||
return doctypes_to_be_ignored_list
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
import frappe
|
||||
|
||||
test_records = frappe.get_test_records('UOM')
|
||||
test_records = frappe.get_test_records("UOM")
|
||||
|
||||
@@ -20,7 +20,7 @@ default_mail_footer = """<div style="padding: 7px; text-align: right; color: #88
|
||||
|
||||
|
||||
def after_install():
|
||||
frappe.get_doc({'doctype': "Role", "role_name": "Analytics"}).insert()
|
||||
frappe.get_doc({"doctype": "Role", "role_name": "Analytics"}).insert()
|
||||
set_single_defaults()
|
||||
create_compact_item_print_custom_field()
|
||||
create_print_uom_after_qty_custom_field()
|
||||
@@ -37,17 +37,26 @@ def after_install():
|
||||
|
||||
|
||||
def check_setup_wizard_not_completed():
|
||||
if cint(frappe.db.get_single_value('System Settings', 'setup_complete') or 0):
|
||||
if cint(frappe.db.get_single_value("System Settings", "setup_complete") or 0):
|
||||
message = """ERPNext can only be installed on a fresh site where the setup wizard is not completed.
|
||||
You can reinstall this site (after saving your data) using: bench --site [sitename] reinstall"""
|
||||
frappe.throw(message) # nosemgrep
|
||||
frappe.throw(message) # nosemgrep
|
||||
|
||||
|
||||
def set_single_defaults():
|
||||
for dt in ('Accounts Settings', 'Print Settings', 'HR Settings', 'Buying Settings',
|
||||
'Selling Settings', 'Stock Settings'):
|
||||
default_values = frappe.db.sql("""select fieldname, `default` from `tabDocField`
|
||||
where parent=%s""", dt)
|
||||
for dt in (
|
||||
"Accounts Settings",
|
||||
"Print Settings",
|
||||
"HR Settings",
|
||||
"Buying Settings",
|
||||
"Selling Settings",
|
||||
"Stock Settings",
|
||||
):
|
||||
default_values = frappe.db.sql(
|
||||
"""select fieldname, `default` from `tabDocField`
|
||||
where parent=%s""",
|
||||
dt,
|
||||
)
|
||||
if default_values:
|
||||
try:
|
||||
b = frappe.get_doc(dt, dt)
|
||||
@@ -63,111 +72,128 @@ def set_single_defaults():
|
||||
|
||||
|
||||
def create_compact_item_print_custom_field():
|
||||
create_custom_field('Print Settings', {
|
||||
'label': _('Compact Item Print'),
|
||||
'fieldname': 'compact_item_print',
|
||||
'fieldtype': 'Check',
|
||||
'default': 1,
|
||||
'insert_after': 'with_letterhead'
|
||||
})
|
||||
create_custom_field(
|
||||
"Print Settings",
|
||||
{
|
||||
"label": _("Compact Item Print"),
|
||||
"fieldname": "compact_item_print",
|
||||
"fieldtype": "Check",
|
||||
"default": 1,
|
||||
"insert_after": "with_letterhead",
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def create_print_uom_after_qty_custom_field():
|
||||
create_custom_field('Print Settings', {
|
||||
'label': _('Print UOM after Quantity'),
|
||||
'fieldname': 'print_uom_after_quantity',
|
||||
'fieldtype': 'Check',
|
||||
'default': 0,
|
||||
'insert_after': 'compact_item_print'
|
||||
})
|
||||
create_custom_field(
|
||||
"Print Settings",
|
||||
{
|
||||
"label": _("Print UOM after Quantity"),
|
||||
"fieldname": "print_uom_after_quantity",
|
||||
"fieldtype": "Check",
|
||||
"default": 0,
|
||||
"insert_after": "compact_item_print",
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def create_print_zero_amount_taxes_custom_field():
|
||||
create_custom_field('Print Settings', {
|
||||
'label': _('Print taxes with zero amount'),
|
||||
'fieldname': 'print_taxes_with_zero_amount',
|
||||
'fieldtype': 'Check',
|
||||
'default': 0,
|
||||
'insert_after': 'allow_print_for_cancelled'
|
||||
})
|
||||
create_custom_field(
|
||||
"Print Settings",
|
||||
{
|
||||
"label": _("Print taxes with zero amount"),
|
||||
"fieldname": "print_taxes_with_zero_amount",
|
||||
"fieldtype": "Check",
|
||||
"default": 0,
|
||||
"insert_after": "allow_print_for_cancelled",
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def create_default_cash_flow_mapper_templates():
|
||||
for mapper in DEFAULT_MAPPERS:
|
||||
if not frappe.db.exists('Cash Flow Mapper', mapper['section_name']):
|
||||
if not frappe.db.exists("Cash Flow Mapper", mapper["section_name"]):
|
||||
doc = frappe.get_doc(mapper)
|
||||
doc.insert(ignore_permissions=True)
|
||||
|
||||
|
||||
def create_default_success_action():
|
||||
for success_action in get_default_success_action():
|
||||
if not frappe.db.exists('Success Action', success_action.get("ref_doctype")):
|
||||
if not frappe.db.exists("Success Action", success_action.get("ref_doctype")):
|
||||
doc = frappe.get_doc(success_action)
|
||||
doc.insert(ignore_permissions=True)
|
||||
|
||||
|
||||
def create_default_energy_point_rules():
|
||||
|
||||
for rule in get_default_energy_point_rules():
|
||||
# check if any rule for ref. doctype exists
|
||||
rule_exists = frappe.db.exists('Energy Point Rule', {
|
||||
'reference_doctype': rule.get('reference_doctype')
|
||||
})
|
||||
if rule_exists: continue
|
||||
rule_exists = frappe.db.exists(
|
||||
"Energy Point Rule", {"reference_doctype": rule.get("reference_doctype")}
|
||||
)
|
||||
if rule_exists:
|
||||
continue
|
||||
doc = frappe.get_doc(rule)
|
||||
doc.insert(ignore_permissions=True)
|
||||
|
||||
|
||||
def add_company_to_session_defaults():
|
||||
settings = frappe.get_single("Session Default Settings")
|
||||
settings.append("session_defaults", {
|
||||
"ref_doctype": "Company"
|
||||
})
|
||||
settings.append("session_defaults", {"ref_doctype": "Company"})
|
||||
settings.save()
|
||||
|
||||
|
||||
def add_standard_navbar_items():
|
||||
navbar_settings = frappe.get_single("Navbar Settings")
|
||||
|
||||
erpnext_navbar_items = [
|
||||
{
|
||||
'item_label': 'Documentation',
|
||||
'item_type': 'Route',
|
||||
'route': 'https://erpnext.com/docs/user/manual',
|
||||
'is_standard': 1
|
||||
"item_label": "Documentation",
|
||||
"item_type": "Route",
|
||||
"route": "https://erpnext.com/docs/user/manual",
|
||||
"is_standard": 1,
|
||||
},
|
||||
{
|
||||
'item_label': 'User Forum',
|
||||
'item_type': 'Route',
|
||||
'route': 'https://discuss.erpnext.com',
|
||||
'is_standard': 1
|
||||
"item_label": "User Forum",
|
||||
"item_type": "Route",
|
||||
"route": "https://discuss.erpnext.com",
|
||||
"is_standard": 1,
|
||||
},
|
||||
{
|
||||
'item_label': 'Report an Issue',
|
||||
'item_type': 'Route',
|
||||
'route': 'https://github.com/frappe/erpnext/issues',
|
||||
'is_standard': 1
|
||||
}
|
||||
"item_label": "Report an Issue",
|
||||
"item_type": "Route",
|
||||
"route": "https://github.com/frappe/erpnext/issues",
|
||||
"is_standard": 1,
|
||||
},
|
||||
]
|
||||
|
||||
current_navbar_items = navbar_settings.help_dropdown
|
||||
navbar_settings.set('help_dropdown', [])
|
||||
navbar_settings.set("help_dropdown", [])
|
||||
|
||||
for item in erpnext_navbar_items:
|
||||
current_labels = [item.get('item_label') for item in current_navbar_items]
|
||||
if not item.get('item_label') in current_labels:
|
||||
navbar_settings.append('help_dropdown', item)
|
||||
current_labels = [item.get("item_label") for item in current_navbar_items]
|
||||
if not item.get("item_label") in current_labels:
|
||||
navbar_settings.append("help_dropdown", item)
|
||||
|
||||
for item in current_navbar_items:
|
||||
navbar_settings.append('help_dropdown', {
|
||||
'item_label': item.item_label,
|
||||
'item_type': item.item_type,
|
||||
'route': item.route,
|
||||
'action': item.action,
|
||||
'is_standard': item.is_standard,
|
||||
'hidden': item.hidden
|
||||
})
|
||||
navbar_settings.append(
|
||||
"help_dropdown",
|
||||
{
|
||||
"item_label": item.item_label,
|
||||
"item_type": item.item_type,
|
||||
"route": item.route,
|
||||
"action": item.action,
|
||||
"is_standard": item.is_standard,
|
||||
"hidden": item.hidden,
|
||||
},
|
||||
)
|
||||
|
||||
navbar_settings.save()
|
||||
|
||||
|
||||
def add_app_name():
|
||||
frappe.db.set_value('System Settings', None, 'app_name', 'ERPNext')
|
||||
frappe.db.set_value("System Settings", None, "app_name", "ERPNext")
|
||||
|
||||
|
||||
def add_non_standard_user_types():
|
||||
user_types = get_user_types_data()
|
||||
@@ -176,73 +202,77 @@ def add_non_standard_user_types():
|
||||
for user_type, data in iteritems(user_types):
|
||||
user_type_limit.setdefault(frappe.scrub(user_type), 10)
|
||||
|
||||
update_site_config('user_type_doctype_limit', user_type_limit)
|
||||
update_site_config("user_type_doctype_limit", user_type_limit)
|
||||
|
||||
for user_type, data in iteritems(user_types):
|
||||
create_custom_role(data)
|
||||
create_user_type(user_type, data)
|
||||
|
||||
|
||||
def get_user_types_data():
|
||||
return {
|
||||
'Employee Self Service': {
|
||||
'role': 'Employee Self Service',
|
||||
'apply_user_permission_on': 'Employee',
|
||||
'user_id_field': 'user_id',
|
||||
'doctypes': {
|
||||
'Salary Slip': ['read'],
|
||||
'Employee': ['read', 'write'],
|
||||
'Expense Claim': ['read', 'write', 'create', 'delete'],
|
||||
'Leave Application': ['read', 'write', 'create', 'delete'],
|
||||
'Attendance Request': ['read', 'write', 'create', 'delete'],
|
||||
'Compensatory Leave Request': ['read', 'write', 'create', 'delete'],
|
||||
'Employee Tax Exemption Declaration': ['read', 'write', 'create', 'delete'],
|
||||
'Employee Tax Exemption Proof Submission': ['read', 'write', 'create', 'delete'],
|
||||
'Timesheet': ['read', 'write', 'create', 'delete', 'submit', 'cancel', 'amend']
|
||||
}
|
||||
"Employee Self Service": {
|
||||
"role": "Employee Self Service",
|
||||
"apply_user_permission_on": "Employee",
|
||||
"user_id_field": "user_id",
|
||||
"doctypes": {
|
||||
"Salary Slip": ["read"],
|
||||
"Employee": ["read", "write"],
|
||||
"Expense Claim": ["read", "write", "create", "delete"],
|
||||
"Leave Application": ["read", "write", "create", "delete"],
|
||||
"Attendance Request": ["read", "write", "create", "delete"],
|
||||
"Compensatory Leave Request": ["read", "write", "create", "delete"],
|
||||
"Employee Tax Exemption Declaration": ["read", "write", "create", "delete"],
|
||||
"Employee Tax Exemption Proof Submission": ["read", "write", "create", "delete"],
|
||||
"Timesheet": ["read", "write", "create", "delete", "submit", "cancel", "amend"],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def create_custom_role(data):
|
||||
if data.get('role') and not frappe.db.exists('Role', data.get('role')):
|
||||
frappe.get_doc({
|
||||
'doctype': 'Role',
|
||||
'role_name': data.get('role'),
|
||||
'desk_access': 1,
|
||||
'is_custom': 1
|
||||
}).insert(ignore_permissions=True)
|
||||
if data.get("role") and not frappe.db.exists("Role", data.get("role")):
|
||||
frappe.get_doc(
|
||||
{"doctype": "Role", "role_name": data.get("role"), "desk_access": 1, "is_custom": 1}
|
||||
).insert(ignore_permissions=True)
|
||||
|
||||
|
||||
def create_user_type(user_type, data):
|
||||
if frappe.db.exists('User Type', user_type):
|
||||
doc = frappe.get_cached_doc('User Type', user_type)
|
||||
if frappe.db.exists("User Type", user_type):
|
||||
doc = frappe.get_cached_doc("User Type", user_type)
|
||||
doc.user_doctypes = []
|
||||
else:
|
||||
doc = frappe.new_doc('User Type')
|
||||
doc.update({
|
||||
'name': user_type,
|
||||
'role': data.get('role'),
|
||||
'user_id_field': data.get('user_id_field'),
|
||||
'apply_user_permission_on': data.get('apply_user_permission_on')
|
||||
})
|
||||
doc = frappe.new_doc("User Type")
|
||||
doc.update(
|
||||
{
|
||||
"name": user_type,
|
||||
"role": data.get("role"),
|
||||
"user_id_field": data.get("user_id_field"),
|
||||
"apply_user_permission_on": data.get("apply_user_permission_on"),
|
||||
}
|
||||
)
|
||||
|
||||
create_role_permissions_for_doctype(doc, data)
|
||||
doc.save(ignore_permissions=True)
|
||||
|
||||
|
||||
def create_role_permissions_for_doctype(doc, data):
|
||||
for doctype, perms in iteritems(data.get('doctypes')):
|
||||
args = {'document_type': doctype}
|
||||
for doctype, perms in iteritems(data.get("doctypes")):
|
||||
args = {"document_type": doctype}
|
||||
for perm in perms:
|
||||
args[perm] = 1
|
||||
|
||||
doc.append('user_doctypes', args)
|
||||
doc.append("user_doctypes", args)
|
||||
|
||||
|
||||
def update_select_perm_after_install():
|
||||
if not frappe.flags.update_select_perm_after_migrate:
|
||||
return
|
||||
|
||||
frappe.flags.ignore_select_perm = False
|
||||
for row in frappe.get_all('User Type', filters= {'is_standard': 0}):
|
||||
print('Updating user type :- ', row.name)
|
||||
doc = frappe.get_doc('User Type', row.name)
|
||||
for row in frappe.get_all("User Type", filters={"is_standard": 0}):
|
||||
print("Updating user type :- ", row.name)
|
||||
doc = frappe.get_doc("User Type", row.name)
|
||||
doc.save()
|
||||
|
||||
frappe.flags.update_select_perm_after_migrate = False
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
import json
|
||||
|
||||
import frappe
|
||||
@@ -14,6 +13,7 @@ def get_company_for_dashboards():
|
||||
return company_list[0].name
|
||||
return None
|
||||
|
||||
|
||||
def get_default_dashboards():
|
||||
company = frappe.get_doc("Company", get_company_for_dashboards())
|
||||
income_account = company.default_income_account or get_account("Income Account", company.name)
|
||||
@@ -26,20 +26,18 @@ def get_default_dashboards():
|
||||
"doctype": "Dashboard",
|
||||
"dashboard_name": "Accounts",
|
||||
"charts": [
|
||||
{ "chart": "Outgoing Bills (Sales Invoice)" },
|
||||
{ "chart": "Incoming Bills (Purchase Invoice)" },
|
||||
{ "chart": "Bank Balance" },
|
||||
{ "chart": "Income" },
|
||||
{ "chart": "Expenses" },
|
||||
{ "chart": "Patient Appointments" }
|
||||
]
|
||||
{"chart": "Outgoing Bills (Sales Invoice)"},
|
||||
{"chart": "Incoming Bills (Purchase Invoice)"},
|
||||
{"chart": "Bank Balance"},
|
||||
{"chart": "Income"},
|
||||
{"chart": "Expenses"},
|
||||
{"chart": "Patient Appointments"},
|
||||
],
|
||||
},
|
||||
{
|
||||
"doctype": "Dashboard",
|
||||
"dashboard_name": "Project",
|
||||
"charts": [
|
||||
{ "chart": "Project Summary", "width": "Full" }
|
||||
]
|
||||
"charts": [{"chart": "Project Summary", "width": "Full"}],
|
||||
},
|
||||
],
|
||||
"Charts": [
|
||||
@@ -55,7 +53,7 @@ def get_default_dashboards():
|
||||
"timeseries": 1,
|
||||
"owner": "Administrator",
|
||||
"type": "Line",
|
||||
"width": "Half"
|
||||
"width": "Half",
|
||||
},
|
||||
{
|
||||
"doctype": "Dashboard Chart",
|
||||
@@ -69,7 +67,7 @@ def get_default_dashboards():
|
||||
"timeseries": 1,
|
||||
"owner": "Administrator",
|
||||
"type": "Line",
|
||||
"width": "Half"
|
||||
"width": "Half",
|
||||
},
|
||||
{
|
||||
"doctype": "Dashboard Chart",
|
||||
@@ -83,7 +81,7 @@ def get_default_dashboards():
|
||||
"timeseries": 1,
|
||||
"owner": "Administrator",
|
||||
"type": "Line",
|
||||
"width": "Half"
|
||||
"width": "Half",
|
||||
},
|
||||
{
|
||||
"doctype": "Dashboard Chart",
|
||||
@@ -99,7 +97,7 @@ def get_default_dashboards():
|
||||
"owner": "Administrator",
|
||||
"document_type": "Purchase Invoice",
|
||||
"type": "Bar",
|
||||
"width": "Half"
|
||||
"width": "Half",
|
||||
},
|
||||
{
|
||||
"doctype": "Dashboard Chart",
|
||||
@@ -115,18 +113,18 @@ def get_default_dashboards():
|
||||
"owner": "Administrator",
|
||||
"document_type": "Sales Invoice",
|
||||
"type": "Bar",
|
||||
"width": "Half"
|
||||
"width": "Half",
|
||||
},
|
||||
{
|
||||
'doctype': 'Dashboard Chart',
|
||||
'name': 'Project Summary',
|
||||
'chart_name': 'Project Summary',
|
||||
'chart_type': 'Report',
|
||||
'report_name': 'Project Summary',
|
||||
'is_public': 1,
|
||||
'filters_json': json.dumps({"company": company.name, "status": "Open"}),
|
||||
'type': 'Bar',
|
||||
'custom_options': '{"type": "bar", "colors": ["#fc4f51", "#78d6ff", "#7575ff"], "axisOptions": { "shortenYAxisNumbers": 1}, "barOptions": { "stacked": 1 }}',
|
||||
"doctype": "Dashboard Chart",
|
||||
"name": "Project Summary",
|
||||
"chart_name": "Project Summary",
|
||||
"chart_type": "Report",
|
||||
"report_name": "Project Summary",
|
||||
"is_public": 1,
|
||||
"filters_json": json.dumps({"company": company.name, "status": "Open"}),
|
||||
"type": "Bar",
|
||||
"custom_options": '{"type": "bar", "colors": ["#fc4f51", "#78d6ff", "#7575ff"], "axisOptions": { "shortenYAxisNumbers": 1}, "barOptions": { "stacked": 1 }}',
|
||||
},
|
||||
{
|
||||
"doctype": "Dashboard Chart",
|
||||
@@ -141,11 +139,12 @@ def get_default_dashboards():
|
||||
"owner": "Administrator",
|
||||
"document_type": "Patient Appointment",
|
||||
"type": "Line",
|
||||
"width": "Half"
|
||||
}
|
||||
]
|
||||
"width": "Half",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def get_account(account_type, company):
|
||||
accounts = frappe.get_list("Account", filters={"account_type": account_type, "company": company})
|
||||
if accounts:
|
||||
|
||||
@@ -1,58 +1,57 @@
|
||||
|
||||
from frappe import _
|
||||
|
||||
|
||||
def get_industry_types():
|
||||
return [
|
||||
_('Accounting'),
|
||||
_('Advertising'),
|
||||
_('Aerospace'),
|
||||
_('Agriculture'),
|
||||
_('Airline'),
|
||||
_('Apparel & Accessories'),
|
||||
_('Automotive'),
|
||||
_('Banking'),
|
||||
_('Biotechnology'),
|
||||
_('Broadcasting'),
|
||||
_('Brokerage'),
|
||||
_('Chemical'),
|
||||
_('Computer'),
|
||||
_('Consulting'),
|
||||
_('Consumer Products'),
|
||||
_('Cosmetics'),
|
||||
_('Defense'),
|
||||
_('Department Stores'),
|
||||
_('Education'),
|
||||
_('Electronics'),
|
||||
_('Energy'),
|
||||
_('Entertainment & Leisure'),
|
||||
_('Executive Search'),
|
||||
_('Financial Services'),
|
||||
_('Food, Beverage & Tobacco'),
|
||||
_('Grocery'),
|
||||
_('Health Care'),
|
||||
_('Internet Publishing'),
|
||||
_('Investment Banking'),
|
||||
_('Legal'),
|
||||
_('Manufacturing'),
|
||||
_('Motion Picture & Video'),
|
||||
_('Music'),
|
||||
_('Newspaper Publishers'),
|
||||
_('Online Auctions'),
|
||||
_('Pension Funds'),
|
||||
_('Pharmaceuticals'),
|
||||
_('Private Equity'),
|
||||
_('Publishing'),
|
||||
_('Real Estate'),
|
||||
_('Retail & Wholesale'),
|
||||
_('Securities & Commodity Exchanges'),
|
||||
_('Service'),
|
||||
_('Soap & Detergent'),
|
||||
_('Software'),
|
||||
_('Sports'),
|
||||
_('Technology'),
|
||||
_('Telecommunications'),
|
||||
_('Television'),
|
||||
_('Transportation'),
|
||||
_('Venture Capital')
|
||||
_("Accounting"),
|
||||
_("Advertising"),
|
||||
_("Aerospace"),
|
||||
_("Agriculture"),
|
||||
_("Airline"),
|
||||
_("Apparel & Accessories"),
|
||||
_("Automotive"),
|
||||
_("Banking"),
|
||||
_("Biotechnology"),
|
||||
_("Broadcasting"),
|
||||
_("Brokerage"),
|
||||
_("Chemical"),
|
||||
_("Computer"),
|
||||
_("Consulting"),
|
||||
_("Consumer Products"),
|
||||
_("Cosmetics"),
|
||||
_("Defense"),
|
||||
_("Department Stores"),
|
||||
_("Education"),
|
||||
_("Electronics"),
|
||||
_("Energy"),
|
||||
_("Entertainment & Leisure"),
|
||||
_("Executive Search"),
|
||||
_("Financial Services"),
|
||||
_("Food, Beverage & Tobacco"),
|
||||
_("Grocery"),
|
||||
_("Health Care"),
|
||||
_("Internet Publishing"),
|
||||
_("Investment Banking"),
|
||||
_("Legal"),
|
||||
_("Manufacturing"),
|
||||
_("Motion Picture & Video"),
|
||||
_("Music"),
|
||||
_("Newspaper Publishers"),
|
||||
_("Online Auctions"),
|
||||
_("Pension Funds"),
|
||||
_("Pharmaceuticals"),
|
||||
_("Private Equity"),
|
||||
_("Publishing"),
|
||||
_("Real Estate"),
|
||||
_("Retail & Wholesale"),
|
||||
_("Securities & Commodity Exchanges"),
|
||||
_("Service"),
|
||||
_("Soap & Detergent"),
|
||||
_("Software"),
|
||||
_("Sports"),
|
||||
_("Technology"),
|
||||
_("Telecommunications"),
|
||||
_("Television"),
|
||||
_("Transportation"),
|
||||
_("Venture Capital"),
|
||||
]
|
||||
|
||||
@@ -10,41 +10,50 @@ from .default_website import website_maker
|
||||
|
||||
|
||||
def create_fiscal_year_and_company(args):
|
||||
if (args.get('fy_start_date')):
|
||||
curr_fiscal_year = get_fy_details(args.get('fy_start_date'), args.get('fy_end_date'))
|
||||
frappe.get_doc({
|
||||
"doctype":"Fiscal Year",
|
||||
'year': curr_fiscal_year,
|
||||
'year_start_date': args.get('fy_start_date'),
|
||||
'year_end_date': args.get('fy_end_date'),
|
||||
}).insert()
|
||||
if args.get("fy_start_date"):
|
||||
curr_fiscal_year = get_fy_details(args.get("fy_start_date"), args.get("fy_end_date"))
|
||||
frappe.get_doc(
|
||||
{
|
||||
"doctype": "Fiscal Year",
|
||||
"year": curr_fiscal_year,
|
||||
"year_start_date": args.get("fy_start_date"),
|
||||
"year_end_date": args.get("fy_end_date"),
|
||||
}
|
||||
).insert()
|
||||
|
||||
if args.get("company_name"):
|
||||
frappe.get_doc(
|
||||
{
|
||||
"doctype": "Company",
|
||||
"company_name": args.get("company_name"),
|
||||
"enable_perpetual_inventory": 1,
|
||||
"abbr": args.get("company_abbr"),
|
||||
"default_currency": args.get("currency"),
|
||||
"country": args.get("country"),
|
||||
"create_chart_of_accounts_based_on": "Standard Template",
|
||||
"chart_of_accounts": args.get("chart_of_accounts"),
|
||||
"domain": args.get("domains")[0],
|
||||
}
|
||||
).insert()
|
||||
|
||||
if (args.get('company_name')):
|
||||
frappe.get_doc({
|
||||
"doctype":"Company",
|
||||
'company_name':args.get('company_name'),
|
||||
'enable_perpetual_inventory': 1,
|
||||
'abbr':args.get('company_abbr'),
|
||||
'default_currency':args.get('currency'),
|
||||
'country': args.get('country'),
|
||||
'create_chart_of_accounts_based_on': 'Standard Template',
|
||||
'chart_of_accounts': args.get('chart_of_accounts'),
|
||||
'domain': args.get('domains')[0]
|
||||
}).insert()
|
||||
|
||||
def enable_shopping_cart(args):
|
||||
# Needs price_lists
|
||||
frappe.get_doc({
|
||||
"doctype": "E Commerce Settings",
|
||||
"enabled": 1,
|
||||
'company': args.get('company_name') ,
|
||||
'price_list': frappe.db.get_value("Price List", {"selling": 1}),
|
||||
'default_customer_group': _("Individual"),
|
||||
'quotation_series': "QTN-",
|
||||
}).insert()
|
||||
frappe.get_doc(
|
||||
{
|
||||
"doctype": "E Commerce Settings",
|
||||
"enabled": 1,
|
||||
"company": args.get("company_name"),
|
||||
"price_list": frappe.db.get_value("Price List", {"selling": 1}),
|
||||
"default_customer_group": _("Individual"),
|
||||
"quotation_series": "QTN-",
|
||||
}
|
||||
).insert()
|
||||
|
||||
|
||||
def create_email_digest():
|
||||
from frappe.utils.user import get_system_managers
|
||||
|
||||
system_managers = get_system_managers(only_name=True)
|
||||
|
||||
if not system_managers:
|
||||
@@ -52,20 +61,20 @@ def create_email_digest():
|
||||
|
||||
recipients = []
|
||||
for d in system_managers:
|
||||
recipients.append({
|
||||
'recipient': d
|
||||
})
|
||||
recipients.append({"recipient": d})
|
||||
|
||||
companies = frappe.db.sql_list("select name FROM `tabCompany`")
|
||||
for company in companies:
|
||||
if not frappe.db.exists("Email Digest", "Default Weekly Digest - " + company):
|
||||
edigest = frappe.get_doc({
|
||||
"doctype": "Email Digest",
|
||||
"name": "Default Weekly Digest - " + company,
|
||||
"company": company,
|
||||
"frequency": "Weekly",
|
||||
"recipients": recipients
|
||||
})
|
||||
edigest = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Email Digest",
|
||||
"name": "Default Weekly Digest - " + company,
|
||||
"company": company,
|
||||
"frequency": "Weekly",
|
||||
"recipients": recipients,
|
||||
}
|
||||
)
|
||||
|
||||
for df in edigest.meta.get("fields", {"fieldtype": "Check"}):
|
||||
if df.fieldname != "scheduler_errors":
|
||||
@@ -76,39 +85,53 @@ def create_email_digest():
|
||||
# scheduler errors digest
|
||||
if companies:
|
||||
edigest = frappe.new_doc("Email Digest")
|
||||
edigest.update({
|
||||
"name": "Scheduler Errors",
|
||||
"company": companies[0],
|
||||
"frequency": "Daily",
|
||||
"recipients": recipients,
|
||||
"scheduler_errors": 1,
|
||||
"enabled": 1
|
||||
})
|
||||
edigest.update(
|
||||
{
|
||||
"name": "Scheduler Errors",
|
||||
"company": companies[0],
|
||||
"frequency": "Daily",
|
||||
"recipients": recipients,
|
||||
"scheduler_errors": 1,
|
||||
"enabled": 1,
|
||||
}
|
||||
)
|
||||
edigest.insert()
|
||||
|
||||
|
||||
def create_logo(args):
|
||||
if args.get("attach_logo"):
|
||||
attach_logo = args.get("attach_logo").split(",")
|
||||
if len(attach_logo)==3:
|
||||
if len(attach_logo) == 3:
|
||||
filename, filetype, content = attach_logo
|
||||
_file = frappe.get_doc({
|
||||
"doctype": "File",
|
||||
"file_name": filename,
|
||||
"attached_to_doctype": "Website Settings",
|
||||
"attached_to_name": "Website Settings",
|
||||
"decode": True})
|
||||
_file = frappe.get_doc(
|
||||
{
|
||||
"doctype": "File",
|
||||
"file_name": filename,
|
||||
"attached_to_doctype": "Website Settings",
|
||||
"attached_to_name": "Website Settings",
|
||||
"decode": True,
|
||||
}
|
||||
)
|
||||
_file.save()
|
||||
fileurl = _file.file_url
|
||||
frappe.db.set_value("Website Settings", "Website Settings", "brand_html",
|
||||
"<img src='{0}' style='max-width: 40px; max-height: 25px;'> {1}".format(fileurl, args.get("company_name")))
|
||||
frappe.db.set_value(
|
||||
"Website Settings",
|
||||
"Website Settings",
|
||||
"brand_html",
|
||||
"<img src='{0}' style='max-width: 40px; max-height: 25px;'> {1}".format(
|
||||
fileurl, args.get("company_name")
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def create_website(args):
|
||||
website_maker(args)
|
||||
|
||||
|
||||
def get_fy_details(fy_start_date, fy_end_date):
|
||||
start_year = getdate(fy_start_date).year
|
||||
if start_year == getdate(fy_end_date).year:
|
||||
fy = cstr(start_year)
|
||||
else:
|
||||
fy = cstr(start_year) + '-' + cstr(start_year + 1)
|
||||
fy = cstr(start_year) + "-" + cstr(start_year + 1)
|
||||
return fy
|
||||
|
||||
@@ -12,14 +12,14 @@ class website_maker(object):
|
||||
self.args = args
|
||||
self.company = args.company_name
|
||||
self.tagline = args.company_tagline
|
||||
self.user = args.get('email')
|
||||
self.user = args.get("email")
|
||||
self.make_web_page()
|
||||
self.make_website_settings()
|
||||
self.make_blog()
|
||||
|
||||
def make_web_page(self):
|
||||
# home page
|
||||
homepage = frappe.get_doc('Homepage', 'Homepage')
|
||||
homepage = frappe.get_doc("Homepage", "Homepage")
|
||||
homepage.company = self.company
|
||||
homepage.tag_line = self.tagline
|
||||
homepage.setup_items()
|
||||
@@ -28,34 +28,25 @@ class website_maker(object):
|
||||
def make_website_settings(self):
|
||||
# update in home page in settings
|
||||
website_settings = frappe.get_doc("Website Settings", "Website Settings")
|
||||
website_settings.home_page = 'home'
|
||||
website_settings.home_page = "home"
|
||||
website_settings.brand_html = self.company
|
||||
website_settings.copyright = self.company
|
||||
website_settings.top_bar_items = []
|
||||
website_settings.append("top_bar_items", {
|
||||
"doctype": "Top Bar Item",
|
||||
"label":"Contact",
|
||||
"url": "/contact"
|
||||
})
|
||||
website_settings.append("top_bar_items", {
|
||||
"doctype": "Top Bar Item",
|
||||
"label":"Blog",
|
||||
"url": "/blog"
|
||||
})
|
||||
website_settings.append("top_bar_items", {
|
||||
"doctype": "Top Bar Item",
|
||||
"label": _("Products"),
|
||||
"url": "/all-products"
|
||||
})
|
||||
website_settings.append(
|
||||
"top_bar_items", {"doctype": "Top Bar Item", "label": "Contact", "url": "/contact"}
|
||||
)
|
||||
website_settings.append(
|
||||
"top_bar_items", {"doctype": "Top Bar Item", "label": "Blog", "url": "/blog"}
|
||||
)
|
||||
website_settings.append(
|
||||
"top_bar_items", {"doctype": "Top Bar Item", "label": _("Products"), "url": "/all-products"}
|
||||
)
|
||||
website_settings.save()
|
||||
|
||||
def make_blog(self):
|
||||
blog_category = frappe.get_doc({
|
||||
"doctype": "Blog Category",
|
||||
"category_name": "general",
|
||||
"published": 1,
|
||||
"title": _("General")
|
||||
}).insert()
|
||||
blog_category = frappe.get_doc(
|
||||
{"doctype": "Blog Category", "category_name": "general", "published": 1, "title": _("General")}
|
||||
).insert()
|
||||
|
||||
if not self.user:
|
||||
# Admin setup
|
||||
@@ -69,21 +60,30 @@ class website_maker(object):
|
||||
blogger.avatar = user.user_image
|
||||
blogger.insert()
|
||||
|
||||
frappe.get_doc({
|
||||
"doctype": "Blog Post",
|
||||
"title": "Welcome",
|
||||
"published": 1,
|
||||
"published_on": nowdate(),
|
||||
"blogger": blogger.name,
|
||||
"blog_category": blog_category.name,
|
||||
"blog_intro": "My First Blog",
|
||||
"content": frappe.get_template("setup/setup_wizard/data/sample_blog_post.html").render(),
|
||||
}).insert()
|
||||
frappe.get_doc(
|
||||
{
|
||||
"doctype": "Blog Post",
|
||||
"title": "Welcome",
|
||||
"published": 1,
|
||||
"published_on": nowdate(),
|
||||
"blogger": blogger.name,
|
||||
"blog_category": blog_category.name,
|
||||
"blog_intro": "My First Blog",
|
||||
"content": frappe.get_template("setup/setup_wizard/data/sample_blog_post.html").render(),
|
||||
}
|
||||
).insert()
|
||||
|
||||
|
||||
def test():
|
||||
frappe.delete_doc("Web Page", "test-company")
|
||||
frappe.delete_doc("Blog Post", "welcome")
|
||||
frappe.delete_doc("Blogger", "administrator")
|
||||
frappe.delete_doc("Blog Category", "general")
|
||||
website_maker({'company':"Test Company", 'company_tagline': "Better Tools for Everyone", 'name': "Administrator"})
|
||||
website_maker(
|
||||
{
|
||||
"company": "Test Company",
|
||||
"company_tagline": "Better Tools for Everyone",
|
||||
"name": "Administrator",
|
||||
}
|
||||
)
|
||||
frappe.db.commit()
|
||||
|
||||
@@ -12,12 +12,14 @@ def set_default_settings(args):
|
||||
frappe.db.set_value("Currency", args.get("currency"), "enabled", 1)
|
||||
|
||||
global_defaults = frappe.get_doc("Global Defaults", "Global Defaults")
|
||||
global_defaults.update({
|
||||
'current_fiscal_year': get_fy_details(args.get('fy_start_date'), args.get('fy_end_date')),
|
||||
'default_currency': args.get('currency'),
|
||||
'default_company':args.get('company_name') ,
|
||||
"country": args.get("country"),
|
||||
})
|
||||
global_defaults.update(
|
||||
{
|
||||
"current_fiscal_year": get_fy_details(args.get("fy_start_date"), args.get("fy_end_date")),
|
||||
"default_currency": args.get("currency"),
|
||||
"default_company": args.get("company_name"),
|
||||
"country": args.get("country"),
|
||||
}
|
||||
)
|
||||
|
||||
global_defaults.save()
|
||||
|
||||
@@ -25,13 +27,15 @@ def set_default_settings(args):
|
||||
system_settings.email_footer_address = args.get("company_name")
|
||||
system_settings.save()
|
||||
|
||||
domain_settings = frappe.get_single('Domain Settings')
|
||||
domain_settings.set_active_domains(args.get('domains'))
|
||||
domain_settings = frappe.get_single("Domain Settings")
|
||||
domain_settings.set_active_domains(args.get("domains"))
|
||||
|
||||
stock_settings = frappe.get_doc("Stock Settings")
|
||||
stock_settings.item_naming_by = "Item Code"
|
||||
stock_settings.valuation_method = "FIFO"
|
||||
stock_settings.default_warehouse = frappe.db.get_value('Warehouse', {'warehouse_name': _('Stores')})
|
||||
stock_settings.default_warehouse = frappe.db.get_value(
|
||||
"Warehouse", {"warehouse_name": _("Stores")}
|
||||
)
|
||||
stock_settings.stock_uom = _("Nos")
|
||||
stock_settings.auto_indent = 1
|
||||
stock_settings.auto_insert_price_list_rate_if_missing = 1
|
||||
@@ -72,61 +76,74 @@ def set_default_settings(args):
|
||||
hr_settings.feedback_reminder_notification_template = _("Interview Feedback Reminder")
|
||||
hr_settings.save()
|
||||
|
||||
|
||||
def set_no_copy_fields_in_variant_settings():
|
||||
# set no copy fields of an item doctype to item variant settings
|
||||
doc = frappe.get_doc('Item Variant Settings')
|
||||
doc = frappe.get_doc("Item Variant Settings")
|
||||
doc.set_default_fields()
|
||||
doc.save()
|
||||
|
||||
|
||||
def create_price_lists(args):
|
||||
for pl_type, pl_name in (("Selling", _("Standard Selling")), ("Buying", _("Standard Buying"))):
|
||||
frappe.get_doc({
|
||||
"doctype": "Price List",
|
||||
"price_list_name": pl_name,
|
||||
"enabled": 1,
|
||||
"buying": 1 if pl_type == "Buying" else 0,
|
||||
"selling": 1 if pl_type == "Selling" else 0,
|
||||
"currency": args["currency"]
|
||||
}).insert()
|
||||
frappe.get_doc(
|
||||
{
|
||||
"doctype": "Price List",
|
||||
"price_list_name": pl_name,
|
||||
"enabled": 1,
|
||||
"buying": 1 if pl_type == "Buying" else 0,
|
||||
"selling": 1 if pl_type == "Selling" else 0,
|
||||
"currency": args["currency"],
|
||||
}
|
||||
).insert()
|
||||
|
||||
|
||||
def create_employee_for_self(args):
|
||||
if frappe.session.user == 'Administrator':
|
||||
if frappe.session.user == "Administrator":
|
||||
return
|
||||
|
||||
# create employee for self
|
||||
emp = frappe.get_doc({
|
||||
"doctype": "Employee",
|
||||
"employee_name": " ".join(filter(None, [args.get("first_name"), args.get("last_name")])),
|
||||
"user_id": frappe.session.user,
|
||||
"status": "Active",
|
||||
"company": args.get("company_name")
|
||||
})
|
||||
emp = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Employee",
|
||||
"employee_name": " ".join(filter(None, [args.get("first_name"), args.get("last_name")])),
|
||||
"user_id": frappe.session.user,
|
||||
"status": "Active",
|
||||
"company": args.get("company_name"),
|
||||
}
|
||||
)
|
||||
emp.flags.ignore_mandatory = True
|
||||
emp.insert(ignore_permissions = True)
|
||||
emp.insert(ignore_permissions=True)
|
||||
|
||||
|
||||
def create_territories():
|
||||
"""create two default territories, one for home country and one named Rest of the World"""
|
||||
from frappe.utils.nestedset import get_root_of
|
||||
|
||||
country = frappe.db.get_default("country")
|
||||
root_territory = get_root_of("Territory")
|
||||
|
||||
for name in (country, _("Rest Of The World")):
|
||||
if name and not frappe.db.exists("Territory", name):
|
||||
frappe.get_doc({
|
||||
"doctype": "Territory",
|
||||
"territory_name": name.replace("'", ""),
|
||||
"parent_territory": root_territory,
|
||||
"is_group": "No"
|
||||
}).insert()
|
||||
frappe.get_doc(
|
||||
{
|
||||
"doctype": "Territory",
|
||||
"territory_name": name.replace("'", ""),
|
||||
"parent_territory": root_territory,
|
||||
"is_group": "No",
|
||||
}
|
||||
).insert()
|
||||
|
||||
|
||||
def create_feed_and_todo():
|
||||
"""update Activity feed and create todo for creation of item, customer, vendor"""
|
||||
return
|
||||
|
||||
|
||||
def get_fy_details(fy_start_date, fy_end_date):
|
||||
start_year = getdate(fy_start_date).year
|
||||
if start_year == getdate(fy_end_date).year:
|
||||
fy = cstr(start_year)
|
||||
else:
|
||||
fy = cstr(start_year) + '-' + cstr(start_year + 1)
|
||||
fy = cstr(start_year) + "-" + cstr(start_year + 1)
|
||||
return fy
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,12 +12,12 @@ from frappe import _
|
||||
from frappe.utils.make_random import add_random_children
|
||||
|
||||
|
||||
def make_sample_data(domains, make_dependent = False):
|
||||
def make_sample_data(domains, make_dependent=False):
|
||||
"""Create a few opportunities, quotes, material requests, issues, todos, projects
|
||||
to help the user get started"""
|
||||
|
||||
if make_dependent:
|
||||
items = frappe.get_all("Item", {'is_sales_item': 1})
|
||||
items = frappe.get_all("Item", {"is_sales_item": 1})
|
||||
customers = frappe.get_all("Customer")
|
||||
warehouses = frappe.get_all("Warehouse")
|
||||
|
||||
@@ -33,91 +33,109 @@ def make_sample_data(domains, make_dependent = False):
|
||||
make_projects(domains)
|
||||
import_notification()
|
||||
|
||||
def make_opportunity(items, customer):
|
||||
b = frappe.get_doc({
|
||||
"doctype": "Opportunity",
|
||||
"opportunity_from": "Customer",
|
||||
"customer": customer,
|
||||
"opportunity_type": _("Sales"),
|
||||
"with_items": 1
|
||||
})
|
||||
|
||||
add_random_children(b, "items", rows=len(items), randomize = {
|
||||
"qty": (1, 5),
|
||||
"item_code": ["Item"]
|
||||
}, unique="item_code")
|
||||
def make_opportunity(items, customer):
|
||||
b = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Opportunity",
|
||||
"opportunity_from": "Customer",
|
||||
"customer": customer,
|
||||
"opportunity_type": _("Sales"),
|
||||
"with_items": 1,
|
||||
}
|
||||
)
|
||||
|
||||
add_random_children(
|
||||
b, "items", rows=len(items), randomize={"qty": (1, 5), "item_code": ["Item"]}, unique="item_code"
|
||||
)
|
||||
|
||||
b.insert(ignore_permissions=True)
|
||||
|
||||
b.add_comment('Comment', text="This is a dummy record")
|
||||
b.add_comment("Comment", text="This is a dummy record")
|
||||
|
||||
|
||||
def make_quote(items, customer):
|
||||
qtn = frappe.get_doc({
|
||||
"doctype": "Quotation",
|
||||
"quotation_to": "Customer",
|
||||
"party_name": customer,
|
||||
"order_type": "Sales"
|
||||
})
|
||||
qtn = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Quotation",
|
||||
"quotation_to": "Customer",
|
||||
"party_name": customer,
|
||||
"order_type": "Sales",
|
||||
}
|
||||
)
|
||||
|
||||
add_random_children(qtn, "items", rows=len(items), randomize = {
|
||||
"qty": (1, 5),
|
||||
"item_code": ["Item"]
|
||||
}, unique="item_code")
|
||||
add_random_children(
|
||||
qtn,
|
||||
"items",
|
||||
rows=len(items),
|
||||
randomize={"qty": (1, 5), "item_code": ["Item"]},
|
||||
unique="item_code",
|
||||
)
|
||||
|
||||
qtn.insert(ignore_permissions=True)
|
||||
|
||||
qtn.add_comment('Comment', text="This is a dummy record")
|
||||
qtn.add_comment("Comment", text="This is a dummy record")
|
||||
|
||||
|
||||
def make_material_request(items):
|
||||
for i in items:
|
||||
mr = frappe.get_doc({
|
||||
"doctype": "Material Request",
|
||||
"material_request_type": "Purchase",
|
||||
"schedule_date": frappe.utils.add_days(frappe.utils.nowdate(), 7),
|
||||
"items": [{
|
||||
mr = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Material Request",
|
||||
"material_request_type": "Purchase",
|
||||
"schedule_date": frappe.utils.add_days(frappe.utils.nowdate(), 7),
|
||||
"item_code": i.name,
|
||||
"qty": 10
|
||||
}]
|
||||
})
|
||||
"items": [
|
||||
{
|
||||
"schedule_date": frappe.utils.add_days(frappe.utils.nowdate(), 7),
|
||||
"item_code": i.name,
|
||||
"qty": 10,
|
||||
}
|
||||
],
|
||||
}
|
||||
)
|
||||
mr.insert()
|
||||
mr.submit()
|
||||
|
||||
mr.add_comment('Comment', text="This is a dummy record")
|
||||
mr.add_comment("Comment", text="This is a dummy record")
|
||||
|
||||
|
||||
def make_issue():
|
||||
pass
|
||||
|
||||
|
||||
def make_projects(domains):
|
||||
current_date = frappe.utils.nowdate()
|
||||
project = frappe.get_doc({
|
||||
"doctype": "Project",
|
||||
"project_name": "ERPNext Implementation",
|
||||
})
|
||||
project = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Project",
|
||||
"project_name": "ERPNext Implementation",
|
||||
}
|
||||
)
|
||||
|
||||
tasks = [
|
||||
{
|
||||
"title": "Explore ERPNext",
|
||||
"start_date": current_date,
|
||||
"end_date": current_date,
|
||||
"file": "explore.md"
|
||||
}]
|
||||
"file": "explore.md",
|
||||
}
|
||||
]
|
||||
|
||||
if 'Education' in domains:
|
||||
if "Education" in domains:
|
||||
tasks += [
|
||||
{
|
||||
"title": _("Setup your Institute in ERPNext"),
|
||||
"start_date": current_date,
|
||||
"end_date": frappe.utils.add_days(current_date, 1),
|
||||
"file": "education_masters.md"
|
||||
"file": "education_masters.md",
|
||||
},
|
||||
{
|
||||
"title": "Setup Master Data",
|
||||
"start_date": current_date,
|
||||
"end_date": frappe.utils.add_days(current_date, 1),
|
||||
"file": "education_masters.md"
|
||||
}]
|
||||
"file": "education_masters.md",
|
||||
},
|
||||
]
|
||||
|
||||
else:
|
||||
tasks += [
|
||||
@@ -125,55 +143,59 @@ def make_projects(domains):
|
||||
"title": "Setup Your Company",
|
||||
"start_date": current_date,
|
||||
"end_date": frappe.utils.add_days(current_date, 1),
|
||||
"file": "masters.md"
|
||||
"file": "masters.md",
|
||||
},
|
||||
{
|
||||
"title": "Start Tracking your Sales",
|
||||
"start_date": current_date,
|
||||
"end_date": frappe.utils.add_days(current_date, 2),
|
||||
"file": "sales.md"
|
||||
"file": "sales.md",
|
||||
},
|
||||
{
|
||||
"title": "Start Managing Purchases",
|
||||
"start_date": current_date,
|
||||
"end_date": frappe.utils.add_days(current_date, 3),
|
||||
"file": "purchase.md"
|
||||
"file": "purchase.md",
|
||||
},
|
||||
{
|
||||
"title": "Import Data",
|
||||
"start_date": current_date,
|
||||
"end_date": frappe.utils.add_days(current_date, 4),
|
||||
"file": "import_data.md"
|
||||
"file": "import_data.md",
|
||||
},
|
||||
{
|
||||
"title": "Go Live!",
|
||||
"start_date": current_date,
|
||||
"end_date": frappe.utils.add_days(current_date, 5),
|
||||
"file": "go_live.md"
|
||||
}]
|
||||
"file": "go_live.md",
|
||||
},
|
||||
]
|
||||
|
||||
for t in tasks:
|
||||
with open (os.path.join(os.path.dirname(__file__), "tasks", t['file'])) as f:
|
||||
t['description'] = frappe.utils.md_to_html(f.read())
|
||||
del t['file']
|
||||
with open(os.path.join(os.path.dirname(__file__), "tasks", t["file"])) as f:
|
||||
t["description"] = frappe.utils.md_to_html(f.read())
|
||||
del t["file"]
|
||||
|
||||
project.append('tasks', t)
|
||||
project.append("tasks", t)
|
||||
|
||||
project.insert(ignore_permissions=True)
|
||||
|
||||
|
||||
def import_notification():
|
||||
'''Import notification for task start'''
|
||||
with open (os.path.join(os.path.dirname(__file__), "tasks/task_alert.json")) as f:
|
||||
"""Import notification for task start"""
|
||||
with open(os.path.join(os.path.dirname(__file__), "tasks/task_alert.json")) as f:
|
||||
notification = frappe.get_doc(json.loads(f.read())[0])
|
||||
notification.insert()
|
||||
|
||||
# trigger the first message!
|
||||
from frappe.email.doctype.notification.notification import trigger_daily_alerts
|
||||
|
||||
trigger_daily_alerts()
|
||||
|
||||
|
||||
def test_sample():
|
||||
frappe.db.sql('delete from `tabNotification`')
|
||||
frappe.db.sql('delete from tabProject')
|
||||
frappe.db.sql('delete from tabTask')
|
||||
make_projects('Education')
|
||||
frappe.db.sql("delete from `tabNotification`")
|
||||
frappe.db.sql("delete from tabProject")
|
||||
frappe.db.sql("delete from tabTask")
|
||||
make_projects("Education")
|
||||
import_notification()
|
||||
|
||||
@@ -10,11 +10,11 @@ from frappe import _
|
||||
|
||||
|
||||
def setup_taxes_and_charges(company_name: str, country: str):
|
||||
if not frappe.db.exists('Company', company_name):
|
||||
frappe.throw(_('Company {} does not exist yet. Taxes setup aborted.').format(company_name))
|
||||
if not frappe.db.exists("Company", company_name):
|
||||
frappe.throw(_("Company {} does not exist yet. Taxes setup aborted.").format(company_name))
|
||||
|
||||
file_path = os.path.join(os.path.dirname(__file__), '..', 'data', 'country_wise_tax.json')
|
||||
with open(file_path, 'r') as json_file:
|
||||
file_path = os.path.join(os.path.dirname(__file__), "..", "data", "country_wise_tax.json")
|
||||
with open(file_path, "r") as json_file:
|
||||
tax_data = json.load(json_file)
|
||||
|
||||
country_wise_tax = tax_data.get(country)
|
||||
@@ -22,7 +22,7 @@ def setup_taxes_and_charges(company_name: str, country: str):
|
||||
if not country_wise_tax:
|
||||
return
|
||||
|
||||
if 'chart_of_accounts' not in country_wise_tax:
|
||||
if "chart_of_accounts" not in country_wise_tax:
|
||||
country_wise_tax = simple_to_detailed(country_wise_tax)
|
||||
|
||||
from_detailed_data(company_name, country_wise_tax)
|
||||
@@ -36,39 +36,44 @@ def simple_to_detailed(templates):
|
||||
Example input:
|
||||
|
||||
{
|
||||
"France VAT 20%": {
|
||||
"account_name": "VAT 20%",
|
||||
"tax_rate": 20,
|
||||
"default": 1
|
||||
},
|
||||
"France VAT 10%": {
|
||||
"account_name": "VAT 10%",
|
||||
"tax_rate": 10
|
||||
}
|
||||
"France VAT 20%": {
|
||||
"account_name": "VAT 20%",
|
||||
"tax_rate": 20,
|
||||
"default": 1
|
||||
},
|
||||
"France VAT 10%": {
|
||||
"account_name": "VAT 10%",
|
||||
"tax_rate": 10
|
||||
}
|
||||
}
|
||||
"""
|
||||
return {
|
||||
'chart_of_accounts': {
|
||||
'*': {
|
||||
'item_tax_templates': [{
|
||||
'title': title,
|
||||
'taxes': [{
|
||||
'tax_type': {
|
||||
'account_name': data.get('account_name'),
|
||||
'tax_rate': data.get('tax_rate')
|
||||
}
|
||||
}]
|
||||
} for title, data in templates.items()],
|
||||
'*': [{
|
||||
'title': title,
|
||||
'is_default': data.get('default', 0),
|
||||
'taxes': [{
|
||||
'account_head': {
|
||||
'account_name': data.get('account_name'),
|
||||
'tax_rate': data.get('tax_rate')
|
||||
}
|
||||
}]
|
||||
} for title, data in templates.items()]
|
||||
"chart_of_accounts": {
|
||||
"*": {
|
||||
"item_tax_templates": [
|
||||
{
|
||||
"title": title,
|
||||
"taxes": [
|
||||
{"tax_type": {"account_name": data.get("account_name"), "tax_rate": data.get("tax_rate")}}
|
||||
],
|
||||
}
|
||||
for title, data in templates.items()
|
||||
],
|
||||
"*": [
|
||||
{
|
||||
"title": title,
|
||||
"is_default": data.get("default", 0),
|
||||
"taxes": [
|
||||
{
|
||||
"account_head": {
|
||||
"account_name": data.get("account_name"),
|
||||
"tax_rate": data.get("tax_rate"),
|
||||
}
|
||||
}
|
||||
],
|
||||
}
|
||||
for title, data in templates.items()
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,13 +81,13 @@ def simple_to_detailed(templates):
|
||||
|
||||
def from_detailed_data(company_name, data):
|
||||
"""Create Taxes and Charges Templates from detailed data."""
|
||||
coa_name = frappe.db.get_value('Company', company_name, 'chart_of_accounts')
|
||||
coa_data = data.get('chart_of_accounts', {})
|
||||
tax_templates = coa_data.get(coa_name) or coa_data.get('*', {})
|
||||
tax_categories = data.get('tax_categories')
|
||||
sales_tax_templates = tax_templates.get('sales_tax_templates') or tax_templates.get('*', {})
|
||||
purchase_tax_templates = tax_templates.get('purchase_tax_templates') or tax_templates.get('*', {})
|
||||
item_tax_templates = tax_templates.get('item_tax_templates') or tax_templates.get('*', {})
|
||||
coa_name = frappe.db.get_value("Company", company_name, "chart_of_accounts")
|
||||
coa_data = data.get("chart_of_accounts", {})
|
||||
tax_templates = coa_data.get(coa_name) or coa_data.get("*", {})
|
||||
tax_categories = data.get("tax_categories")
|
||||
sales_tax_templates = tax_templates.get("sales_tax_templates") or tax_templates.get("*", {})
|
||||
purchase_tax_templates = tax_templates.get("purchase_tax_templates") or tax_templates.get("*", {})
|
||||
item_tax_templates = tax_templates.get("item_tax_templates") or tax_templates.get("*", {})
|
||||
|
||||
if tax_categories:
|
||||
for tax_category in tax_categories:
|
||||
@@ -90,11 +95,11 @@ def from_detailed_data(company_name, data):
|
||||
|
||||
if sales_tax_templates:
|
||||
for template in sales_tax_templates:
|
||||
make_taxes_and_charges_template(company_name, 'Sales Taxes and Charges Template', template)
|
||||
make_taxes_and_charges_template(company_name, "Sales Taxes and Charges Template", template)
|
||||
|
||||
if purchase_tax_templates:
|
||||
for template in purchase_tax_templates:
|
||||
make_taxes_and_charges_template(company_name, 'Purchase Taxes and Charges Template', template)
|
||||
make_taxes_and_charges_template(company_name, "Purchase Taxes and Charges Template", template)
|
||||
|
||||
if item_tax_templates:
|
||||
for template in item_tax_templates:
|
||||
@@ -102,40 +107,45 @@ def from_detailed_data(company_name, data):
|
||||
|
||||
|
||||
def update_regional_tax_settings(country, company):
|
||||
path = frappe.get_app_path('erpnext', 'regional', frappe.scrub(country))
|
||||
path = frappe.get_app_path("erpnext", "regional", frappe.scrub(country))
|
||||
if os.path.exists(path.encode("utf-8")):
|
||||
try:
|
||||
module_name = "erpnext.regional.{0}.setup.update_regional_tax_settings".format(frappe.scrub(country))
|
||||
module_name = "erpnext.regional.{0}.setup.update_regional_tax_settings".format(
|
||||
frappe.scrub(country)
|
||||
)
|
||||
frappe.get_attr(module_name)(country, company)
|
||||
except Exception as e:
|
||||
# Log error and ignore if failed to setup regional tax settings
|
||||
frappe.log_error()
|
||||
pass
|
||||
|
||||
def make_taxes_and_charges_template(company_name, doctype, template):
|
||||
template['company'] = company_name
|
||||
template['doctype'] = doctype
|
||||
|
||||
if frappe.db.exists(doctype, {'title': template.get('title'), 'company': company_name}):
|
||||
def make_taxes_and_charges_template(company_name, doctype, template):
|
||||
template["company"] = company_name
|
||||
template["doctype"] = doctype
|
||||
|
||||
if frappe.db.exists(doctype, {"title": template.get("title"), "company": company_name}):
|
||||
return
|
||||
|
||||
for tax_row in template.get('taxes'):
|
||||
account_data = tax_row.get('account_head')
|
||||
for tax_row in template.get("taxes"):
|
||||
account_data = tax_row.get("account_head")
|
||||
tax_row_defaults = {
|
||||
'category': 'Total',
|
||||
'charge_type': 'On Net Total',
|
||||
'cost_center': frappe.db.get_value('Company', company_name, 'cost_center')
|
||||
"category": "Total",
|
||||
"charge_type": "On Net Total",
|
||||
"cost_center": frappe.db.get_value("Company", company_name, "cost_center"),
|
||||
}
|
||||
|
||||
if doctype == 'Purchase Taxes and Charges Template':
|
||||
tax_row_defaults['add_deduct_tax'] = 'Add'
|
||||
if doctype == "Purchase Taxes and Charges Template":
|
||||
tax_row_defaults["add_deduct_tax"] = "Add"
|
||||
|
||||
# if account_head is a dict, search or create the account and get it's name
|
||||
if isinstance(account_data, dict):
|
||||
tax_row_defaults['description'] = '{0} @ {1}'.format(account_data.get('account_name'), account_data.get('tax_rate'))
|
||||
tax_row_defaults['rate'] = account_data.get('tax_rate')
|
||||
tax_row_defaults["description"] = "{0} @ {1}".format(
|
||||
account_data.get("account_name"), account_data.get("tax_rate")
|
||||
)
|
||||
tax_row_defaults["rate"] = account_data.get("tax_rate")
|
||||
account = get_or_create_account(company_name, account_data)
|
||||
tax_row['account_head'] = account.name
|
||||
tax_row["account_head"] = account.name
|
||||
|
||||
# use the default value if nothing other is specified
|
||||
for fieldname, default_value in tax_row_defaults.items():
|
||||
@@ -151,28 +161,29 @@ def make_taxes_and_charges_template(company_name, doctype, template):
|
||||
doc.insert(ignore_permissions=True)
|
||||
return doc
|
||||
|
||||
|
||||
def make_item_tax_template(company_name, template):
|
||||
"""Create an Item Tax Template.
|
||||
|
||||
This requires a separate method because Item Tax Template is structured
|
||||
differently from Sales and Purchase Tax Templates.
|
||||
"""
|
||||
doctype = 'Item Tax Template'
|
||||
template['company'] = company_name
|
||||
template['doctype'] = doctype
|
||||
doctype = "Item Tax Template"
|
||||
template["company"] = company_name
|
||||
template["doctype"] = doctype
|
||||
|
||||
if frappe.db.exists(doctype, {'title': template.get('title'), 'company': company_name}):
|
||||
if frappe.db.exists(doctype, {"title": template.get("title"), "company": company_name}):
|
||||
return
|
||||
|
||||
for tax_row in template.get('taxes'):
|
||||
account_data = tax_row.get('tax_type')
|
||||
for tax_row in template.get("taxes"):
|
||||
account_data = tax_row.get("tax_type")
|
||||
|
||||
# if tax_type is a dict, search or create the account and get it's name
|
||||
if isinstance(account_data, dict):
|
||||
account = get_or_create_account(company_name, account_data)
|
||||
tax_row['tax_type'] = account.name
|
||||
if 'tax_rate' not in tax_row:
|
||||
tax_row['tax_rate'] = account_data.get('tax_rate')
|
||||
tax_row["tax_type"] = account.name
|
||||
if "tax_rate" not in tax_row:
|
||||
tax_row["tax_rate"] = account_data.get("tax_rate")
|
||||
|
||||
doc = frappe.get_doc(template)
|
||||
|
||||
@@ -183,46 +194,47 @@ def make_item_tax_template(company_name, template):
|
||||
doc.insert(ignore_permissions=True)
|
||||
return doc
|
||||
|
||||
|
||||
def make_tax_category(tax_category):
|
||||
""" Make tax category based on title if not already created """
|
||||
doctype = 'Tax Category'
|
||||
if not frappe.db.exists(doctype, tax_category['title']):
|
||||
tax_category['doctype'] = doctype
|
||||
"""Make tax category based on title if not already created"""
|
||||
doctype = "Tax Category"
|
||||
if not frappe.db.exists(doctype, tax_category["title"]):
|
||||
tax_category["doctype"] = doctype
|
||||
doc = frappe.get_doc(tax_category)
|
||||
doc.flags.ignore_links = True
|
||||
doc.flags.ignore_validate = True
|
||||
doc.insert(ignore_permissions=True)
|
||||
|
||||
|
||||
def get_or_create_account(company_name, account):
|
||||
"""
|
||||
Check if account already exists. If not, create it.
|
||||
Return a tax account or None.
|
||||
"""
|
||||
default_root_type = 'Liability'
|
||||
root_type = account.get('root_type', default_root_type)
|
||||
default_root_type = "Liability"
|
||||
root_type = account.get("root_type", default_root_type)
|
||||
|
||||
existing_accounts = frappe.get_all('Account',
|
||||
filters={
|
||||
'company': company_name,
|
||||
'root_type': root_type
|
||||
},
|
||||
existing_accounts = frappe.get_all(
|
||||
"Account",
|
||||
filters={"company": company_name, "root_type": root_type},
|
||||
or_filters={
|
||||
'account_name': account.get('account_name'),
|
||||
'account_number': account.get('account_number')
|
||||
})
|
||||
"account_name": account.get("account_name"),
|
||||
"account_number": account.get("account_number"),
|
||||
},
|
||||
)
|
||||
|
||||
if existing_accounts:
|
||||
return frappe.get_doc('Account', existing_accounts[0].name)
|
||||
return frappe.get_doc("Account", existing_accounts[0].name)
|
||||
|
||||
tax_group = get_or_create_tax_group(company_name, root_type)
|
||||
|
||||
account['doctype'] = 'Account'
|
||||
account['company'] = company_name
|
||||
account['parent_account'] = tax_group
|
||||
account['report_type'] = 'Balance Sheet'
|
||||
account['account_type'] = 'Tax'
|
||||
account['root_type'] = root_type
|
||||
account['is_group'] = 0
|
||||
account["doctype"] = "Account"
|
||||
account["company"] = company_name
|
||||
account["parent_account"] = tax_group
|
||||
account["report_type"] = "Balance Sheet"
|
||||
account["account_type"] = "Tax"
|
||||
account["root_type"] = root_type
|
||||
account["is_group"] = 0
|
||||
|
||||
doc = frappe.get_doc(account)
|
||||
doc.flags.ignore_links = True
|
||||
@@ -230,50 +242,53 @@ def get_or_create_account(company_name, account):
|
||||
doc.insert(ignore_permissions=True, ignore_mandatory=True)
|
||||
return doc
|
||||
|
||||
|
||||
def get_or_create_tax_group(company_name, root_type):
|
||||
# Look for a group account of type 'Tax'
|
||||
tax_group_name = frappe.db.get_value('Account', {
|
||||
'is_group': 1,
|
||||
'root_type': root_type,
|
||||
'account_type': 'Tax',
|
||||
'company': company_name
|
||||
})
|
||||
tax_group_name = frappe.db.get_value(
|
||||
"Account",
|
||||
{"is_group": 1, "root_type": root_type, "account_type": "Tax", "company": company_name},
|
||||
)
|
||||
|
||||
if tax_group_name:
|
||||
return tax_group_name
|
||||
|
||||
# Look for a group account named 'Duties and Taxes' or 'Tax Assets'
|
||||
account_name = _('Duties and Taxes') if root_type == 'Liability' else _('Tax Assets')
|
||||
tax_group_name = frappe.db.get_value('Account', {
|
||||
'is_group': 1,
|
||||
'root_type': root_type,
|
||||
'account_name': account_name,
|
||||
'company': company_name
|
||||
})
|
||||
account_name = _("Duties and Taxes") if root_type == "Liability" else _("Tax Assets")
|
||||
tax_group_name = frappe.db.get_value(
|
||||
"Account",
|
||||
{"is_group": 1, "root_type": root_type, "account_name": account_name, "company": company_name},
|
||||
)
|
||||
|
||||
if tax_group_name:
|
||||
return tax_group_name
|
||||
|
||||
# Create a new group account named 'Duties and Taxes' or 'Tax Assets' just
|
||||
# below the root account
|
||||
root_account = frappe.get_all('Account', {
|
||||
'is_group': 1,
|
||||
'root_type': root_type,
|
||||
'company': company_name,
|
||||
'report_type': 'Balance Sheet',
|
||||
'parent_account': ('is', 'not set')
|
||||
}, limit=1)[0]
|
||||
root_account = frappe.get_all(
|
||||
"Account",
|
||||
{
|
||||
"is_group": 1,
|
||||
"root_type": root_type,
|
||||
"company": company_name,
|
||||
"report_type": "Balance Sheet",
|
||||
"parent_account": ("is", "not set"),
|
||||
},
|
||||
limit=1,
|
||||
)[0]
|
||||
|
||||
tax_group_account = frappe.get_doc({
|
||||
'doctype': 'Account',
|
||||
'company': company_name,
|
||||
'is_group': 1,
|
||||
'report_type': 'Balance Sheet',
|
||||
'root_type': root_type,
|
||||
'account_type': 'Tax',
|
||||
'account_name': account_name,
|
||||
'parent_account': root_account.name
|
||||
})
|
||||
tax_group_account = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Account",
|
||||
"company": company_name,
|
||||
"is_group": 1,
|
||||
"report_type": "Balance Sheet",
|
||||
"root_type": root_type,
|
||||
"account_type": "Tax",
|
||||
"account_name": account_name,
|
||||
"parent_account": root_account.name,
|
||||
}
|
||||
)
|
||||
|
||||
tax_group_account.flags.ignore_links = True
|
||||
tax_group_account.flags.ignore_validate = True
|
||||
@@ -285,11 +300,11 @@ def get_or_create_tax_group(company_name, root_type):
|
||||
|
||||
|
||||
def make_tax_catgory(tax_category):
|
||||
doctype = 'Tax Category'
|
||||
doctype = "Tax Category"
|
||||
if isinstance(tax_category, str):
|
||||
tax_category = {'title': tax_category}
|
||||
tax_category = {"title": tax_category}
|
||||
|
||||
tax_category['doctype'] = doctype
|
||||
if not frappe.db.exists(doctype, tax_category['title']):
|
||||
tax_category["doctype"] = doctype
|
||||
if not frappe.db.exists(doctype, tax_category["title"]):
|
||||
doc = frappe.get_doc(tax_category)
|
||||
doc.insert(ignore_permissions=True)
|
||||
|
||||
@@ -14,96 +14,66 @@ def get_setup_stages(args=None):
|
||||
if frappe.db.sql("select name from tabCompany"):
|
||||
stages = [
|
||||
{
|
||||
'status': _('Wrapping up'),
|
||||
'fail_msg': _('Failed to login'),
|
||||
'tasks': [
|
||||
{
|
||||
'fn': fin,
|
||||
'args': args,
|
||||
'fail_msg': _("Failed to login")
|
||||
}
|
||||
]
|
||||
"status": _("Wrapping up"),
|
||||
"fail_msg": _("Failed to login"),
|
||||
"tasks": [{"fn": fin, "args": args, "fail_msg": _("Failed to login")}],
|
||||
}
|
||||
]
|
||||
else:
|
||||
stages = [
|
||||
{
|
||||
'status': _('Installing presets'),
|
||||
'fail_msg': _('Failed to install presets'),
|
||||
'tasks': [
|
||||
{
|
||||
'fn': stage_fixtures,
|
||||
'args': args,
|
||||
'fail_msg': _("Failed to install presets")
|
||||
}
|
||||
]
|
||||
"status": _("Installing presets"),
|
||||
"fail_msg": _("Failed to install presets"),
|
||||
"tasks": [{"fn": stage_fixtures, "args": args, "fail_msg": _("Failed to install presets")}],
|
||||
},
|
||||
{
|
||||
'status': _('Setting up company'),
|
||||
'fail_msg': _('Failed to setup company'),
|
||||
'tasks': [
|
||||
{
|
||||
'fn': setup_company,
|
||||
'args': args,
|
||||
'fail_msg': _("Failed to setup company")
|
||||
}
|
||||
]
|
||||
"status": _("Setting up company"),
|
||||
"fail_msg": _("Failed to setup company"),
|
||||
"tasks": [{"fn": setup_company, "args": args, "fail_msg": _("Failed to setup company")}],
|
||||
},
|
||||
{
|
||||
'status': _('Setting defaults'),
|
||||
'fail_msg': 'Failed to set defaults',
|
||||
'tasks': [
|
||||
{
|
||||
'fn': setup_defaults,
|
||||
'args': args,
|
||||
'fail_msg': _("Failed to setup defaults")
|
||||
},
|
||||
{
|
||||
'fn': stage_four,
|
||||
'args': args,
|
||||
'fail_msg': _("Failed to create website")
|
||||
},
|
||||
{
|
||||
'fn': set_active_domains,
|
||||
'args': args,
|
||||
'fail_msg': _("Failed to add Domain")
|
||||
},
|
||||
]
|
||||
"status": _("Setting defaults"),
|
||||
"fail_msg": "Failed to set defaults",
|
||||
"tasks": [
|
||||
{"fn": setup_defaults, "args": args, "fail_msg": _("Failed to setup defaults")},
|
||||
{"fn": stage_four, "args": args, "fail_msg": _("Failed to create website")},
|
||||
{"fn": set_active_domains, "args": args, "fail_msg": _("Failed to add Domain")},
|
||||
],
|
||||
},
|
||||
{
|
||||
'status': _('Wrapping up'),
|
||||
'fail_msg': _('Failed to login'),
|
||||
'tasks': [
|
||||
{
|
||||
'fn': fin,
|
||||
'args': args,
|
||||
'fail_msg': _("Failed to login")
|
||||
}
|
||||
]
|
||||
}
|
||||
"status": _("Wrapping up"),
|
||||
"fail_msg": _("Failed to login"),
|
||||
"tasks": [{"fn": fin, "args": args, "fail_msg": _("Failed to login")}],
|
||||
},
|
||||
]
|
||||
|
||||
return stages
|
||||
|
||||
|
||||
def stage_fixtures(args):
|
||||
fixtures.install(args.get('country'))
|
||||
fixtures.install(args.get("country"))
|
||||
|
||||
|
||||
def setup_company(args):
|
||||
fixtures.install_company(args)
|
||||
|
||||
|
||||
def setup_defaults(args):
|
||||
fixtures.install_defaults(frappe._dict(args))
|
||||
|
||||
|
||||
def stage_four(args):
|
||||
company_setup.create_website(args)
|
||||
company_setup.create_email_digest()
|
||||
company_setup.create_logo(args)
|
||||
|
||||
|
||||
def fin(args):
|
||||
frappe.local.message_log = []
|
||||
login_as_first_user(args)
|
||||
|
||||
make_sample_data(args.get('domains'))
|
||||
make_sample_data(args.get("domains"))
|
||||
|
||||
|
||||
def make_sample_data(domains):
|
||||
try:
|
||||
@@ -114,6 +84,7 @@ def make_sample_data(domains):
|
||||
frappe.message_log.pop()
|
||||
pass
|
||||
|
||||
|
||||
def login_as_first_user(args):
|
||||
if args.get("email") and hasattr(frappe.local, "login_manager"):
|
||||
frappe.local.login_manager.login_as(args.get("email"))
|
||||
@@ -127,6 +98,7 @@ def setup_complete(args=None):
|
||||
stage_four(args)
|
||||
fin(args)
|
||||
|
||||
|
||||
def set_active_domains(args):
|
||||
domain_settings = frappe.get_single('Domain Settings')
|
||||
domain_settings.set_active_domains(args.get('domains'))
|
||||
domain_settings = frappe.get_single("Domain Settings")
|
||||
domain_settings.set_active_domains(args.get("domains"))
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
import json
|
||||
import os
|
||||
|
||||
@@ -6,8 +5,7 @@ from frappe.desk.page.setup_wizard.setup_wizard import setup_complete
|
||||
|
||||
|
||||
def complete():
|
||||
with open(os.path.join(os.path.dirname(__file__),
|
||||
'data', 'test_mfg.json'), 'r') as f:
|
||||
with open(os.path.join(os.path.dirname(__file__), "data", "test_mfg.json"), "r") as f:
|
||||
data = json.loads(f.read())
|
||||
|
||||
setup_complete(data)
|
||||
|
||||
@@ -11,40 +11,51 @@ from erpnext import get_default_company
|
||||
|
||||
def get_root_of(doctype):
|
||||
"""Get root element of a DocType with a tree structure"""
|
||||
result = frappe.db.sql_list("""select name from `tab%s`
|
||||
where lft=1 and rgt=(select max(rgt) from `tab%s` where docstatus < 2)""" %
|
||||
(doctype, doctype))
|
||||
result = frappe.db.sql_list(
|
||||
"""select name from `tab%s`
|
||||
where lft=1 and rgt=(select max(rgt) from `tab%s` where docstatus < 2)"""
|
||||
% (doctype, doctype)
|
||||
)
|
||||
return result[0] if result else None
|
||||
|
||||
|
||||
def get_ancestors_of(doctype, name):
|
||||
"""Get ancestor elements of a DocType with a tree structure"""
|
||||
lft, rgt = frappe.db.get_value(doctype, name, ["lft", "rgt"])
|
||||
result = frappe.db.sql_list("""select name from `tab%s`
|
||||
where lft<%s and rgt>%s order by lft desc""" % (doctype, "%s", "%s"), (lft, rgt))
|
||||
result = frappe.db.sql_list(
|
||||
"""select name from `tab%s`
|
||||
where lft<%s and rgt>%s order by lft desc"""
|
||||
% (doctype, "%s", "%s"),
|
||||
(lft, rgt),
|
||||
)
|
||||
return result or []
|
||||
|
||||
|
||||
def before_tests():
|
||||
frappe.clear_cache()
|
||||
# complete setup if missing
|
||||
from frappe.desk.page.setup_wizard.setup_wizard import setup_complete
|
||||
|
||||
if not frappe.get_list("Company"):
|
||||
setup_complete({
|
||||
"currency" :"USD",
|
||||
"full_name" :"Test User",
|
||||
"company_name" :"Wind Power LLC",
|
||||
"timezone" :"America/New_York",
|
||||
"company_abbr" :"WP",
|
||||
"industry" :"Manufacturing",
|
||||
"country" :"United States",
|
||||
"fy_start_date" :"2011-01-01",
|
||||
"fy_end_date" :"2011-12-31",
|
||||
"language" :"english",
|
||||
"company_tagline" :"Testing",
|
||||
"email" :"test@erpnext.com",
|
||||
"password" :"test",
|
||||
"chart_of_accounts" : "Standard",
|
||||
"domains" : ["Manufacturing"],
|
||||
})
|
||||
setup_complete(
|
||||
{
|
||||
"currency": "USD",
|
||||
"full_name": "Test User",
|
||||
"company_name": "Wind Power LLC",
|
||||
"timezone": "America/New_York",
|
||||
"company_abbr": "WP",
|
||||
"industry": "Manufacturing",
|
||||
"country": "United States",
|
||||
"fy_start_date": "2011-01-01",
|
||||
"fy_end_date": "2011-12-31",
|
||||
"language": "english",
|
||||
"company_tagline": "Testing",
|
||||
"email": "test@erpnext.com",
|
||||
"password": "test",
|
||||
"chart_of_accounts": "Standard",
|
||||
"domains": ["Manufacturing"],
|
||||
}
|
||||
)
|
||||
|
||||
frappe.db.sql("delete from `tabLeave Allocation`")
|
||||
frappe.db.sql("delete from `tabLeave Application`")
|
||||
@@ -57,6 +68,7 @@ def before_tests():
|
||||
|
||||
frappe.db.commit()
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_exchange_rate(from_currency, to_currency, transaction_date=None, args=None):
|
||||
if not (from_currency and to_currency):
|
||||
@@ -73,7 +85,7 @@ def get_exchange_rate(from_currency, to_currency, transaction_date=None, args=No
|
||||
filters = [
|
||||
["date", "<=", get_datetime_str(transaction_date)],
|
||||
["from_currency", "=", from_currency],
|
||||
["to_currency", "=", to_currency]
|
||||
["to_currency", "=", to_currency],
|
||||
]
|
||||
|
||||
if args == "for_buying":
|
||||
@@ -88,8 +100,8 @@ def get_exchange_rate(from_currency, to_currency, transaction_date=None, args=No
|
||||
|
||||
# cksgb 19/09/2016: get last entry in Currency Exchange with from_currency and to_currency.
|
||||
entries = frappe.get_all(
|
||||
"Currency Exchange", fields=["exchange_rate"], filters=filters, order_by="date desc",
|
||||
limit=1)
|
||||
"Currency Exchange", fields=["exchange_rate"], filters=filters, order_by="date desc", limit=1
|
||||
)
|
||||
if entries:
|
||||
return flt(entries[0].exchange_rate)
|
||||
|
||||
@@ -100,12 +112,11 @@ def get_exchange_rate(from_currency, to_currency, transaction_date=None, args=No
|
||||
|
||||
if not value:
|
||||
import requests
|
||||
|
||||
api_url = "https://api.exchangerate.host/convert"
|
||||
response = requests.get(api_url, params={
|
||||
"date": transaction_date,
|
||||
"from": from_currency,
|
||||
"to": to_currency
|
||||
})
|
||||
response = requests.get(
|
||||
api_url, params={"date": transaction_date, "from": from_currency, "to": to_currency}
|
||||
)
|
||||
# expire in 6 hours
|
||||
response.raise_for_status()
|
||||
value = response.json()["result"]
|
||||
@@ -113,20 +124,26 @@ def get_exchange_rate(from_currency, to_currency, transaction_date=None, args=No
|
||||
return flt(value)
|
||||
except Exception:
|
||||
frappe.log_error(title="Get Exchange Rate")
|
||||
frappe.msgprint(_("Unable to find exchange rate for {0} to {1} for key date {2}. Please create a Currency Exchange record manually").format(from_currency, to_currency, transaction_date))
|
||||
frappe.msgprint(
|
||||
_(
|
||||
"Unable to find exchange rate for {0} to {1} for key date {2}. Please create a Currency Exchange record manually"
|
||||
).format(from_currency, to_currency, transaction_date)
|
||||
)
|
||||
return 0.0
|
||||
|
||||
|
||||
def enable_all_roles_and_domains():
|
||||
""" enable all roles and domain for testing """
|
||||
"""enable all roles and domain for testing"""
|
||||
# add all roles to users
|
||||
domains = frappe.get_all("Domain")
|
||||
if not domains:
|
||||
return
|
||||
|
||||
from frappe.desk.page.setup_wizard.setup_wizard import add_all_roles_to
|
||||
frappe.get_single('Domain Settings').set_active_domains(\
|
||||
[d.name for d in domains])
|
||||
add_all_roles_to('Administrator')
|
||||
|
||||
frappe.get_single("Domain Settings").set_active_domains([d.name for d in domains])
|
||||
add_all_roles_to("Administrator")
|
||||
|
||||
|
||||
def set_defaults_for_tests():
|
||||
from frappe.utils.nestedset import get_root_of
|
||||
@@ -145,12 +162,13 @@ def insert_record(records):
|
||||
doc.insert(ignore_permissions=True)
|
||||
except frappe.DuplicateEntryError as e:
|
||||
# pass DuplicateEntryError and continue
|
||||
if e.args and e.args[0]==doc.doctype and e.args[1]==doc.name:
|
||||
if e.args and e.args[0] == doc.doctype and e.args[1] == doc.name:
|
||||
# make sure DuplicateEntryError is for the exact same doc and not a related doc
|
||||
pass
|
||||
else:
|
||||
raise
|
||||
|
||||
|
||||
def welcome_email():
|
||||
site_name = get_default_company() or "ERPNext"
|
||||
title = _("Welcome to {0}").format(site_name)
|
||||
|
||||
Reference in New Issue
Block a user