def rename_field(doctype, old_fieldname, new_fieldname): """This functions assumes that doctype is already synced""" doctype_list = frappe.get_doctype(doctype) new_field = doctype_list.get_field(new_fieldname) if not new_field: print "rename_field: " + (new_fieldname) + " not found in " + doctype return if new_field.fieldtype == "Table": # change parentfield of table mentioned in options frappe.db.sql("""update `tab%s` set parentfield=%s where parentfield=%s""" % (new_field.options.split("\n")[0], "%s", "%s"), (new_fieldname, old_fieldname)) elif new_field.fieldtype not in no_value_fields: if doctype_list[0].issingle: frappe.db.sql("""update `tabSingles` set field=%s where doctype=%s and field=%s""", (new_fieldname, doctype, old_fieldname)) else: # copy field value frappe.db.sql("""update `tab%s` set `%s`=`%s`""" % \ (doctype, new_fieldname, old_fieldname)) # update in property setter frappe.db.sql("""update `tabProperty Setter` set field_name = %s where doc_type=%s and field_name=%s""", (new_fieldname, doctype, old_fieldname)) update_users_report_view_settings(doctype, old_fieldname)
def update_completed_qty(bean, method): if bean.doc.doctype == "Stock Entry": material_request_map = {} for d in bean.doclist.get({"parentfield": "mtn_details"}): if d.material_request: material_request_map.setdefault(d.material_request, []).append( d.material_request_item) for mr_name, mr_items in material_request_map.items(): mr_obj = frappe.get_obj("Material Request", mr_name, with_children=1) mr_doctype = frappe.get_doctype("Material Request") if mr_obj.doc.status in ["Stopped", "Cancelled"]: frappe.throw( _("Material Request") + ": %s, " % mr_obj.doc.name + _(mr_doctype.get_label("status")) + " = %s. " % _(mr_obj.doc.status) + _("Cannot continue."), exc=frappe.InvalidStatusError) _update_requested_qty(bean, mr_obj, mr_items) # update ordered percentage and qty mr_obj.update_completed_qty(mr_items)
def test_doclist(self): p_meta = frappe.get_doctype("Profile") self.assertEquals(len(p_meta.get({"doctype": "DocField", "parent": "Profile", "fieldname": "first_name"})), 1) self.assertEquals(len(p_meta.get({"doctype": "DocField", "parent": "Profile", "fieldname": "^first"})), 1) self.assertEquals(len(p_meta.get({"fieldname": ["!=", "first_name"]})), len(p_meta) - 1) self.assertEquals(len(p_meta.get({"fieldname": ["in", ["first_name", "last_name"]]})), 2) self.assertEquals(len(p_meta.get({"fieldname": ["not in", ["first_name", "last_name"]]})), len(p_meta) - 2)
def print_mandatory_fields(doctype): print "Please setup make_test_records for: " + doctype print "-" * 60 doctype_obj = frappe.get_doctype(doctype) print "Autoname: " + (doctype_obj[0].autoname or "") print "Mandatory Fields: " for d in doctype_obj.get({"reqd":1}): print d.parent + ":" + d.fieldname + " | " + d.fieldtype + " | " + (d.options or "") print
def get_company_default(company, fieldname): value = frappe.db.get_value("Company", company, fieldname) if not value: throw(_("Please mention default value for '") + _(frappe.get_doctype("company").get_label(fieldname) + _("' in Company: ") + company)) return value
def get_new_doc(doctype, parent_doc=None, parentfield=None): doc = frappe.doc({ "doctype": doctype, "__islocal": 1, "owner": frappe.session.user, "docstatus": 0 }) meta = frappe.get_doctype(doctype) restrictions = frappe.defaults.get_restrictions() if parent_doc: doc.parent = parent_doc.name doc.parenttype = parent_doc.doctype if parentfield: doc.parentfield = parentfield for d in meta.get({"doctype": "DocField", "parent": doctype}): default = frappe.defaults.get_user_default(d.fieldname) if (d.fieldtype=="Link") and d.ignore_restrictions != 1 and (d.options in restrictions)\ and len(restrictions[d.options])==1: doc.fields[d.fieldname] = restrictions[d.options][0] elif default: doc.fields[d.fieldname] = default elif d.fields.get("default"): if d.default == "__user": doc.fields[d.fieldname] = frappe.session.user elif d.default == "Today": doc.fields[d.fieldname] = nowdate() elif d.default.startswith(":"): ref_fieldname = d.default[1:].lower().replace(" ", "_") if parent_doc: ref_docname = parent_doc.fields[ref_fieldname] else: ref_docname = frappe.db.get_default(ref_fieldname) doc.fields[d.fieldname] = frappe.db.get_value( d.default[1:], ref_docname, d.fieldname) else: doc.fields[d.fieldname] = d.default # convert type of default if d.fieldtype in ("Int", "Check"): doc.fields[d.fieldname] = cint(doc.fields[d.fieldname]) elif d.fieldtype in ("Float", "Currency"): doc.fields[d.fieldname] = flt(doc.fields[d.fieldname]) elif d.fieldtype == "Time": doc.fields[d.fieldname] = nowtime() return doc
def copy_common_fields(from_doc, to_doc): from frappe.model import default_fields doctype_list = frappe.get_doctype(to_doc.doctype) for fieldname, value in from_doc.fields.items(): if fieldname in default_fields: continue if doctype_list.get_field( fieldname) and to_doc.fields[fieldname] != value: to_doc.fields[fieldname] = value
def get_linked_docs(doctype, name, metadata_loaded=None): if not metadata_loaded: metadata_loaded = [] meta = frappe.get_doctype(doctype, True) linkinfo = meta[0].get("__linked_with") results = {} for dt, link in linkinfo.items(): link["doctype"] = dt linkmeta = frappe.get_doctype(dt, True) if not linkmeta[0].get("issingle"): fields = [d.fieldname for d in linkmeta.get({"parent":dt, "in_list_view":1, "fieldtype": ["not in", ["Image", "HTML", "Button", "Table"]]})] \ + ["name", "modified", "docstatus"] fields = [ "`tab{dt}`.`{fn}`".format(dt=dt, fn=sf.strip()) for sf in fields if sf ] if link.get("child_doctype"): ret = frappe.get_list(doctype=dt, fields=fields, filters=[[ link.get('child_doctype'), link.get("fieldname"), '=', name ]]) else: ret = frappe.get_list( doctype=dt, fields=fields, filters=[[dt, link.get("fieldname"), '=', name]]) if ret: results[dt] = ret if not dt in metadata_loaded: if not "docs" in frappe.local.response: frappe.local.response.docs = [] frappe.local.response.docs += linkmeta return results
def validate_restrictions(self): if self.ignore_restrictions: return has_restricted_data = False for d in self.doclist: if not frappe.permissions.has_unrestricted_access( frappe.get_doctype(d.doctype), d): has_restricted_data = True if has_restricted_data: raise BeanPermissionError
def update_user_match(): import frappe.defaults doctype_matches = {} for doctype, match in frappe.db.sql( """select parent, `match` from `tabDocPerm` where `match` like %s and ifnull(`match`, '')!="leave_approver:user" """, "%:user"): doctype_matches.setdefault(doctype, []).append(match) for doctype, user_matches in doctype_matches.items(): meta = frappe.get_doctype(doctype) # for each user with roles of this doctype, check if match condition applies for profile in frappe.db.sql_list("""select name from `tabProfile` where enabled=1 and user_type='System User'"""): user_roles = frappe.get_roles(profile) perms = meta.get({ "doctype": "DocPerm", "permlevel": 0, "role": ["in", [["All"] + user_roles]], "read": 1 }) # user does not have required roles if not perms: continue # assume match user_match = True for perm in perms: if not perm.match: # aha! non match found user_match = False break if not user_match: continue # if match condition applies, restrict that user # add that doc's restriction to that user for match in user_matches: for name in frappe.db.sql_list( """select name from `tab{doctype}` where `{field}`=%s""".format(doctype=doctype, field=match.split(":")[0]), profile): frappe.defaults.add_default(doctype, name, profile, "Restriction")
def validate_end_of_life(item_code, end_of_life=None, verbose=1): if not end_of_life: end_of_life = frappe.db.get_value("Item", item_code, "end_of_life") if end_of_life and getdate(end_of_life) <= now_datetime().date(): msg = (_("Item") + " %(item_code)s: " + _("reached its end of life on") + \ " %(date)s. " + _("Please check") + ": %(end_of_life_label)s " + \ "in Item master") % { "item_code": item_code, "date": formatdate(end_of_life), "end_of_life_label": frappe.get_doctype("Item").get_label("end_of_life") } _msgprint(msg, verbose)
def get_address_display(address_dict): if not isinstance(address_dict, dict): address_dict = frappe.db.get_value( "Address", address_dict, "*", as_dict=True) or {} meta = frappe.get_doctype("Address") sequence = (("", "address_line1"), ("\n", "address_line2"), ("\n", "city"), ("\n", "state"), ("\n" + meta.get_label("pincode") + ": ", "pincode"), ("\n", "country"), ("\n" + meta.get_label("phone") + ": ", "phone"), ("\n" + meta.get_label("fax") + ": ", "fax")) display = "" for separator, fieldname in sequence: if address_dict.get(fieldname): display += separator + address_dict.get(fieldname) return display.strip()
def get_messages_from_doctype(name): messages = [] meta = frappe.get_doctype(name) messages = [meta[0].name, meta[0].description, meta[0].module] for d in meta.get({"doctype":"DocField"}): messages.extend([d.label, d.description]) if d.fieldtype=='Select' and d.options \ and not d.options.startswith("link:") \ and not d.options.startswith("attach_files:"): options = d.options.split('\n') if not "icon" in options[0]: messages.extend(options) # extract from js, py files doctype_file_path = frappe.get_module_path(meta[0].module, "doctype", meta[0].name, meta[0].name) messages.extend(get_messages_from_file(doctype_file_path + ".js")) return clean(messages)
def create_custom_field_for_workflow_state(self): frappe.clear_cache(doctype=self.doc.document_type) doctypeobj = frappe.get_doctype(self.doc.document_type) if not len(doctypeobj.get({"doctype":"DocField", "fieldname":self.doc.workflow_state_field})): # create custom field frappe.bean([{ "doctype":"Custom Field", "dt": self.doc.document_type, "__islocal": 1, "fieldname": self.doc.workflow_state_field, "label": self.doc.workflow_state_field.replace("_", " ").title(), "hidden": 1, "fieldtype": "Link", "options": "Workflow State", #"insert_after": doctypeobj.get({"doctype":"DocField"})[-1].fieldname }]).save() frappe.msgprint("Created Custom Field '%s' in '%s'" % (self.doc.workflow_state_field, self.doc.document_type))
def get_html(doc, doclist, print_format=None): from jinja2 import Environment if isinstance(doc, basestring) and isinstance(doclist, basestring): bean = frappe.bean(doc, doclist) doc = bean.doc doclist = bean.doclist template = Environment().from_string(get_print_format_name(doc.doctype, print_format or frappe.form_dict.format)) doctype = frappe.get_doctype(doc.doctype) args = { "doc": doc, "doclist": doclist, "doctype": doctype, "frappe": frappe, "utils": frappe.utils } html = template.render(args) return html
def get_price_list_rate(args, item_bean, out): meta = frappe.get_doctype(args.doctype) if meta.get_field("currency"): validate_price_list(args) validate_conversion_rate(args, meta) price_list_rate = frappe.db.get_value("Item Price", { "price_list": args.price_list, "item_code": args.item_code }, "price_list_rate") if not price_list_rate: return {} out.price_list_rate = flt(price_list_rate) * flt(args.plc_conversion_rate) \ / flt(args.conversion_rate) if not out.price_list_rate and args.transaction_type == "buying": from erpnext.stock.doctype.item.item import get_last_purchase_details out.update( get_last_purchase_details(item_bean.doc.name, args.docname, args.conversion_rate))
def meta(self): if not hasattr(self, "_meta"): self._meta = frappe.get_doctype(self.doc.doctype) return self._meta
def search_widget(doctype, txt, query=None, searchfield="name", start=0, page_len=50, filters=None): if isinstance(filters, basestring): import json filters = json.loads(filters) meta = frappe.get_doctype(doctype) standard_queries = frappe.get_hooks().standard_queries or [] if standard_queries: standard_queries = dict([v.split(":") for v in standard_queries]) if query and query.split()[0].lower() != "select": # by method frappe.response["values"] = frappe.get_attr(query)(doctype, txt, searchfield, start, page_len, filters) elif not query and doctype in standard_queries: # from standard queries search_widget(doctype, txt, standard_queries[doctype], searchfield, start, page_len, filters) else: if query: # custom query frappe.response["values"] = frappe.db.sql( scrub_custom_query(query, searchfield, txt)) else: if isinstance(filters, dict): filters_items = filters.items() filters = [] for f in filters_items: if isinstance(f[1], (list, tuple)): filters.append([doctype, f[0], f[1][0], f[1][1]]) else: filters.append([doctype, f[0], "=", f[1]]) if filters == None: filters = [] # build from doctype if txt: filters.append( [doctype, searchfield or "name", "like", txt + "%"]) if meta.get({ "parent": doctype, "fieldname": "enabled", "fieldtype": "Check" }): filters.append([doctype, "enabled", "=", 1]) if meta.get({ "parent": doctype, "fieldname": "disabled", "fieldtype": "Check" }): filters.append([doctype, "disabled", "!=", 1]) frappe.response["values"] = frappe.widgets.reportview.execute( doctype, filters=filters, fields=get_std_fields_list(meta, searchfield or "name"), limit_start=start, limit_page_length=page_len, as_list=True)
def get_mapped_doclist(from_doctype, from_docname, table_maps, target_doclist=None, postprocess=None, ignore_permissions=False): if target_doclist is None: target_doclist = [] if isinstance(target_doclist, basestring): target_doclist = json.loads(target_doclist) source = frappe.bean(from_doctype, from_docname) if not ignore_permissions and not frappe.has_permission(from_doctype, "read", source.doc): frappe.msgprint("No Permission", raise_exception=frappe.PermissionError) source_meta = frappe.get_doctype(from_doctype) target_meta = frappe.get_doctype(table_maps[from_doctype]["doctype"]) # main if target_doclist: if isinstance(target_doclist[0], dict): target_doc = frappe.doc(fielddata=target_doclist[0]) else: target_doc = target_doclist[0] else: target_doc = frappe.new_doc(table_maps[from_doctype]["doctype"]) map_doc(source.doc, target_doc, table_maps[source.doc.doctype], source_meta, target_meta) if target_doclist: target_doclist[0] = target_doc else: target_doclist = [target_doc] target_doclist = frappe.doclist(target_doclist) row_exists_for_parentfield = {} # children for source_d in source.doclist[1:]: table_map = table_maps.get(source_d.doctype) if table_map: if "condition" in table_map: if not table_map["condition"](source_d): continue target_doctype = table_map["doctype"] parentfield = target_meta.get({ "parent": target_doc.doctype, "doctype": "DocField", "fieldtype": "Table", "options": target_doctype })[0].fieldname # does row exist for a parentfield? if parentfield not in row_exists_for_parentfield: row_exists_for_parentfield[parentfield] = True if \ frappe.doclist(target_doclist).get({"parentfield": parentfield}) else False if table_map.get("add_if_empty") and row_exists_for_parentfield.get(parentfield): continue target_d = frappe.new_doc(target_doctype, target_doc, parentfield) map_doc(source_d, target_d, table_map, source_meta, target_meta, source.doclist[0]) target_d.idx = None target_doclist.append(target_d) target_doclist = frappe.doclist(target_doclist) if postprocess: new_target_doclist = postprocess(source, target_doclist) if new_target_doclist: target_doclist = new_target_doclist return target_doclist
def onload(self): self.doc.fields["__quotation_series"] = frappe.get_doctype("Quotation").get_options("naming_series")
def update_entries_after(args, verbose=1): """ update valution rate and qty after transaction from the current time-bucket onwards args = { "item_code": "ABC", "warehouse": "XYZ", "posting_date": "2012-12-12", "posting_time": "12:00" } """ if not _exceptions: frappe.local.stockledger_exceptions = [] previous_sle = get_sle_before_datetime(args) qty_after_transaction = flt(previous_sle.get("qty_after_transaction")) valuation_rate = flt(previous_sle.get("valuation_rate")) stock_queue = json.loads(previous_sle.get("stock_queue") or "[]") stock_value = flt(previous_sle.get("stock_value")) prev_stock_value = flt(previous_sle.get("stock_value")) entries_to_fix = get_sle_after_datetime(previous_sle or \ {"item_code": args["item_code"], "warehouse": args["warehouse"]}, for_update=True) valuation_method = get_valuation_method(args["item_code"]) stock_value_difference = 0.0 for sle in entries_to_fix: if sle.serial_no or not cint( frappe.db.get_default("allow_negative_stock")): # validate negative stock for serialized items, fifo valuation # or when negative stock is not allowed for moving average if not validate_negative_stock(qty_after_transaction, sle): qty_after_transaction += flt(sle.actual_qty) continue if sle.serial_no: valuation_rate = get_serialized_values(qty_after_transaction, sle, valuation_rate) elif valuation_method == "Moving Average": valuation_rate = get_moving_average_values(qty_after_transaction, sle, valuation_rate) else: valuation_rate = get_fifo_values(qty_after_transaction, sle, stock_queue) qty_after_transaction += flt(sle.actual_qty) # get stock value if sle.serial_no: stock_value = qty_after_transaction * valuation_rate elif valuation_method == "Moving Average": stock_value = (qty_after_transaction > 0) and \ (qty_after_transaction * valuation_rate) or 0 else: stock_value = sum( (flt(batch[0]) * flt(batch[1]) for batch in stock_queue)) # rounding as per precision from frappe.model.meta import get_field_precision meta = frappe.get_doctype("Stock Ledger Entry") stock_value = flt( stock_value, get_field_precision(meta.get_field("stock_value"), frappe._dict({"fields": sle}))) stock_value_difference = stock_value - prev_stock_value prev_stock_value = stock_value # update current sle frappe.db.sql( """update `tabStock Ledger Entry` set qty_after_transaction=%s, valuation_rate=%s, stock_queue=%s, stock_value=%s, stock_value_difference=%s where name=%s""", (qty_after_transaction, valuation_rate, json.dumps(stock_queue), stock_value, stock_value_difference, sle.name)) if _exceptions: _raise_exceptions(args, verbose) # update bin if not frappe.db.exists({ "doctype": "Bin", "item_code": args["item_code"], "warehouse": args["warehouse"] }): bin_wrapper = frappe.bean([{ "doctype": "Bin", "item_code": args["item_code"], "warehouse": args["warehouse"], }]) bin_wrapper.ignore_permissions = 1 bin_wrapper.insert() frappe.db.sql( """update `tabBin` set valuation_rate=%s, actual_qty=%s, stock_value=%s, projected_qty = (actual_qty + indented_qty + ordered_qty + planned_qty - reserved_qty) where item_code=%s and warehouse=%s""", (valuation_rate, qty_after_transaction, stock_value, args["item_code"], args["warehouse"]))
def get_field(doctype, fieldname, parent=None, parentfield=None): doclist = frappe.get_doctype(doctype) return doclist.get_field(fieldname, parent, parentfield)
def _get_fields(fieldnames): return [frappe._dict(zip(["label", "fieldname", "fieldtype", "options"], [df.label, df.fieldname, df.fieldtype, df.options])) for df in frappe.get_doctype("Address", processed=True).get({"fieldname": ["in", fieldnames]})]
def add_restriction_if_required(self, doctype, user): if frappe.permissions.has_only_non_restrict_role(frappe.get_doctype(doctype), user) \ and self.doc.name not in get_restrictions(user).get("Employee", []): frappe.defaults.add_default("Employee", self.doc.name, user, "Restriction")