def remove_against_link_from_jv(ref_type, ref_no): linked_jv = frappe.db.sql_list( """select parent from `tabJournal Entry Account` where reference_type=%s and reference_name=%s and docstatus < 2""", (ref_type, ref_no), ) if linked_jv: frappe.db.sql( """update `tabJournal Entry Account` set reference_type=null, reference_name = null, modified=%s, modified_by=%s where reference_type=%s and reference_name=%s and docstatus < 2""", (now(), frappe.session.user, ref_type, ref_no), ) frappe.db.sql( """update `tabGL Entry` set against_voucher_type=null, against_voucher=null, modified=%s, modified_by=%s where against_voucher_type=%s and against_voucher=%s and voucher_no != ifnull(against_voucher, '')""", (now(), frappe.session.user, ref_type, ref_no), ) frappe.msgprint(_("Journal Entries {0} are un-linked".format("\n".join(linked_jv))))
def backup( context, with_files=False, backup_path_db=None, backup_path_files=None, backup_path_private_files=None, quiet=False ): "Backup" from frappe.utils.backups import scheduled_backup verbose = context.verbose for site in context.sites: frappe.init(site=site) frappe.connect() odb = scheduled_backup( ignore_files=not with_files, backup_path_db=backup_path_db, backup_path_files=backup_path_files, backup_path_private_files=backup_path_private_files, force=True, ) if verbose: from frappe.utils import now print "database backup taken -", odb.backup_path_db, "- on", now() if with_files: print "files backup taken -", odb.backup_path_files, "- on", now() print "private files backup taken -", odb.backup_path_private_files, "- on", now() frappe.destroy()
def remove_against_link_from_jv(ref_type, ref_no, against_field): linked_jv = frappe.db.sql_list( """select parent from `tabJournal Voucher Detail` where `%s`=%s and docstatus < 2""" % (against_field, "%s"), (ref_no), ) if linked_jv: frappe.db.sql( """update `tabJournal Voucher Detail` set `%s`=null, modified=%s, modified_by=%s where `%s`=%s and docstatus < 2""" % (against_field, "%s", "%s", against_field, "%s"), (now(), frappe.session.user, ref_no), ) frappe.db.sql( """update `tabGL Entry` set against_voucher_type=null, against_voucher=null, modified=%s, modified_by=%s where against_voucher_type=%s and against_voucher=%s and voucher_no != ifnull(against_voucher, '')""", (now(), frappe.session.user, ref_type, ref_no), ) frappe.msgprint(_("Journal Vouchers {0} are un-linked".format("\n".join(linked_jv))))
def __init__(self, content): """Parses headers, content, attachments from given raw message. :param content: Raw message.""" if six.PY2: self.mail = email.message_from_string(safe_encode(content)) else: if isinstance(content, bytes): self.mail = email.message_from_bytes(content) else: self.mail = email.message_from_string(content) self.text_content = '' self.html_content = '' self.attachments = [] self.cid_map = {} self.parse() self.set_content_and_type() self.set_subject() self.set_from() self.message_id = (self.mail.get('Message-ID') or "").strip(" <>") if self.mail["Date"]: try: utc = email.utils.mktime_tz(email.utils.parsedate_tz(self.mail["Date"])) utc_dt = datetime.datetime.utcfromtimestamp(utc) self.date = convert_utc_to_user_timezone(utc_dt).strftime('%Y-%m-%d %H:%M:%S') except: self.date = now() else: self.date = now() if self.date > now(): self.date = now()
def update_status(self): status = frappe.db.get_value("Support Ticket", self.name, "status") if self.status!="Open" and status =="Open" and not self.first_responded_on: self.first_responded_on = now() if self.status=="Closed" and status !="Closed": self.resolution_date = now() if self.status=="Open" and status !="Open": self.resolution_date = ""
def update_status(self): status = frappe.db.get_value("Issue", self.name, "status") if self.status!="Open" and status =="Open" and not self.first_responded_on: self.first_responded_on = now() if self.status=="Closed" and status !="Closed": self.resolution_date = now() if self.status=="Open" and status !="Open": # if no date, it should be set as None and not a blank string "", as per mysql strict config self.resolution_date = None
def backup(with_files=False, backup_path_db=None, backup_path_files=None, quiet=False): from frappe.utils.backups import scheduled_backup verbose = not quiet frappe.connect() odb = scheduled_backup(ignore_files=not with_files, backup_path_db=backup_path_db, backup_path_files=backup_path_files) if verbose: from frappe.utils import now print "database backup taken -", odb.backup_path_db, "- on", now() if with_files: print "files backup taken -", odb.backup_path_files, "- on", now() frappe.destroy()
def on_update(self): # if status is closed then set closing date if self.status == "Open": # if status is open then set opening date # check if start_date is already set if not then set the value odt = frappe.db.get_value("Client Support Ticket","start_date","start_date") if not odt: self.start_date = datetime.datetime.strptime(now(),'%Y-%m-%d %H:%M:%S.%f').strftime('%Y-%m-%d %H:%M:%S') else: self.start_date = odt elif self.status == "Close": self.closing_date = datetime.datetime.strptime(now(),'%Y-%m-%d %H:%M:%S.%f').strftime('%Y-%m-%d %H:%M:%S')
def create_snapshot(): snapshot_repo = frappe.get_hooks("snapshot_repo", app_name="propshikari")[0] snapshot_name = get_datetime().strftime("%Y%m%d_%H%M%S") es = ElasticSearchController() print now() try: response = es.create_snapshot(snapshot_repo, snapshot_name) if not response.get("state") == "SUCCESS": send_email(["*****@*****.**"], "Propshikari Elastic Backup Operation Error", "/templates/elastic_backup_notification.html", {"error_log":response}) return response except Exception,e: print "Elastic Backup Operation Failed" print frappe.get_traceback() print "Error Occured : ",e send_email(["*****@*****.**", "*****@*****.**"], "Propshikari Elastic Backup Operation Error", "/templates/elastic_backup_notification.html", {"error_log":frappe.get_traceback()})
def get_html_table(self, columns=None, data=None): date_time = global_date_format(now()) + ' ' + format_time(now()) report_doctype = frappe.db.get_value('Report', self.report, 'ref_doctype') return frappe.render_template('frappe/templates/emails/auto_email_report.html', { 'title': self.name, 'description': self.description, 'date_time': date_time, 'columns': columns, 'data': data, 'report_url': get_url_to_report(self.report, self.report_type, report_doctype), 'report_name': self.report, 'edit_report_settings': get_link_to_form('Auto Email Report', self.name) })
def update_ip_download_approval_status(): sub_query = """ select name from `tabIP Download Approval` where docstatus=1 and validity_end_date <= '{0}' """.format( now() ) response = frappe.db.sql(sub_query, as_list=1) ipd_name = ",".join('"{0}"'.format(record[0]) for record in response if record) if ipd_name: query = """ update `tabIP Download Approval` set validity_end_date = null , approval_status = 'Expired', modified = '{0}' where name in ({1}) """.format( now(), ipd_name ) frappe.db.sql(query)
def generate_project_aginst_si(doc, method): if not frappe.db.get_value('Project', doc.name, 'name'): pt = frappe.new_doc('Project') pt.project_name = doc.name pt.project_start_date = now() pt.save(ignore_permissions=True) generate_task(doc, method, pt.name)
def rebuild_node(doctype, parent, left, parent_field): """ reset lft, rgt and recursive call for all children """ from frappe.utils import now n = now() # the right value of this node is the left value + 1 right = left + 1 # get all children of this node result = frappe.db.sql("SELECT name FROM `tab%s` WHERE `%s`=%s" % (doctype, parent_field, "%s"), (parent)) for r in result: right = rebuild_node(doctype, r[0], right, parent_field) # we've got the left value, and now that we've processed # the children of this node we also know the right value frappe.db.sql( """UPDATE `tab{0}` SET lft=%s, rgt=%s, modified=%s WHERE name=%s""".format( doctype ), (left, right, n, parent), ) # return the right value of this node + 1 return right + 1
def validate(self): self._prev = frappe._dict({ "contact_date": frappe.db.get_value("Lead", self.name, "contact_date") if \ (not cint(self.get("__islocal"))) else None, "contact_by": frappe.db.get_value("Lead", self.name, "contact_by") if \ (not cint(self.get("__islocal"))) else None, }) self.set_status() self.check_email_id_is_unique() if self.email_id: if not self.flags.ignore_email_validation: validate_email_add(self.email_id, True) if self.email_id == self.lead_owner: frappe.throw(_("Lead Owner cannot be same as the Lead")) if self.email_id == self.contact_by: frappe.throw(_("Next Contact By cannot be same as the Lead Email Address")) self.image = has_gravatar(self.email_id) if self.contact_date and self.contact_date < now(): frappe.throw(_("Next Contact Date cannot be in the past"))
def backup(context, with_files=False, backup_path_db=None, backup_path_files=None, quiet=False): "Backup" from frappe.utils.backups import scheduled_backup verbose = context.verbose # for site in context.sites: # All sites bachup with sites - Gangadhar Sir for site in frappe.utils.get_sites(): frappe.init(site=site) frappe.connect() odb = scheduled_backup(ignore_files=not with_files, backup_path_db=backup_path_db, backup_path_files=backup_path_files, force=True) if verbose: from frappe.utils import now print "database backup taken -", odb.backup_path_db, "- on", now() if with_files: print "files backup taken -", odb.backup_path_files, "- on", now() frappe.destroy()
def __init__(self, content): """Parses headers, content, attachments from given raw message. :param content: Raw message.""" import email, email.utils import datetime self.raw = content self.mail = email.message_from_string(self.raw) self.text_content = '' self.html_content = '' self.attachments = [] self.cid_map = {} self.parse() self.set_content_and_type() self.set_subject() self.from_email = extract_email_id(self.mail["From"]) self.from_real_name = email.utils.parseaddr(self.mail["From"])[0] if self.mail["Date"]: utc = email.utils.mktime_tz(email.utils.parsedate_tz(self.mail["Date"])) utc_dt = datetime.datetime.utcfromtimestamp(utc) self.date = convert_utc_to_user_timezone(utc_dt).strftime('%Y-%m-%d %H:%M:%S') else: self.date = now()
def set_as_cancel(voucher_type, voucher_no): frappe.db.sql( """update `tabStock Ledger Entry` set is_cancelled='Yes', modified=%s, modified_by=%s where voucher_no=%s and voucher_type=%s""", (now(), frappe.session.user, voucher_type, voucher_no), )
def set_value(self, dt, dn, field, val, modified=None, modified_by=None, update_modified=True, debug=False): """Set a single value in the database, do not call the ORM triggers but update the modified timestamp (unless specified not to). **Warning:** this function will not call Document events and should be avoided in normal cases. :param dt: DocType name. :param dn: Document name. :param field: Property / field name or dictionary of values to be updated :param value: Value to be updated. :param modified: Use this as the `modified` timestamp. :param modified_by: Set this user as `modified_by`. :param update_modified: default True. Set as false, if you don't want to update the timestamp. :param debug: Print the query in the developer / js console. """ if not modified: modified = now() if not modified_by: modified_by = frappe.session.user to_update = {} if update_modified: to_update = {"modified": modified, "modified_by": modified_by} if isinstance(field, dict): to_update.update(field) else: to_update.update({field: val}) if dn and dt!=dn: # with table conditions, values = self.build_conditions(dn) values.update(to_update) set_values = [] for key in to_update: set_values.append('`{0}`=%({0})s'.format(key)) self.sql("""update `tab{0}` set {1} where {2}""".format(dt, ', '.join(set_values), conditions), values, debug=debug) else: # for singles keys = list(to_update) self.sql(''' delete from tabSingles where field in ({0}) and doctype=%s'''.format(', '.join(['%s']*len(keys))), list(keys) + [dt], debug=debug) for key, value in iteritems(to_update): self.sql('''insert into tabSingles(doctype, field, value) values (%s, %s, %s)''', (dt, key, value), debug=debug) if dt in self.value_cache: del self.value_cache[dt] frappe.clear_document_cache(dt, dn)
def update_add_node(doc, parent, parent_field): """ insert a new node """ n = now() doctype = doc.doctype name = doc.name # get the last sibling of the parent if parent: left, right = frappe.db.sql("select lft, rgt from `tab{0}` where name=%s" .format(doctype), parent)[0] validate_loop(doc.doctype, doc.name, left, right) else: # root right = frappe.db.sql("select ifnull(max(rgt),0)+1 from `tab%s` \ where ifnull(`%s`,'') =''" % (doctype, parent_field))[0][0] right = right or 1 # update all on the right frappe.db.sql("update `tab{0}` set rgt = rgt+2, modified=%s where rgt >= %s" .format(doctype), (n, right)) frappe.db.sql("update `tab{0}` set lft = lft+2, modified=%s where lft >= %s" .format(doctype), (n, right)) # update index of new node if frappe.db.sql("select * from `tab{0}` where lft=%s or rgt=%s".format(doctype), (right, right+1)): frappe.msgprint(_("Nested set error. Please contact the Administrator.")) raise Exception frappe.db.sql("update `tab{0}` set lft=%s, rgt=%s, modified=%s where name=%s".format(doctype), (right,right+1, n, name)) return right
def test_scrap_material_qty(self): prod_order = make_prod_order_test_record(planned_start_date=now(), qty=2) # add raw materials to stores test_stock_entry.make_stock_entry(item_code="_Test Item", target="Stores - _TC", qty=10, basic_rate=5000.0) test_stock_entry.make_stock_entry( item_code="_Test Item Home Desktop 100", target="Stores - _TC", qty=10, basic_rate=1000.0 ) s = frappe.get_doc(make_stock_entry(prod_order.name, "Material Transfer for Manufacture", 2)) for d in s.get("items"): d.s_warehouse = "Stores - _TC" s.insert() s.submit() s = frappe.get_doc(make_stock_entry(prod_order.name, "Manufacture", 2)) s.insert() s.submit() prod_order_details = frappe.db.get_value( "Production Order", prod_order.name, ["scrap_warehouse", "qty", "produced_qty", "bom_no"], as_dict=1 ) scrap_item_details = get_scrap_item_details(prod_order_details.bom_no) self.assertEqual(prod_order_details.produced_qty, 2) for item in s.items: if item.bom_no and item.item_code in scrap_item_details: self.assertEqual(prod_order_details.scrap_warehouse, item.t_warehouse) self.assertEqual(flt(prod_order_details.qty) * flt(scrap_item_details[item.item_code]), item.qty)
def send_message(subject="Website Query", message="", sender=""): if not message: frappe.response["message"] = 'Please write something' return if not sender: frappe.response["message"] = 'Email Address Required' return # guest method, cap max writes per hour if frappe.db.sql("""select count(*) from `tabCommunication` where `sent_or_received`="Received" and TIMEDIFF(%s, modified) < '01:00:00'""", now())[0][0] > max_communications_per_hour: frappe.response["message"] = "Sorry: we believe we have received an unreasonably high number of requests of this kind. Please try later" return # send email forward_to_email = frappe.db.get_value("Contact Us Settings", None, "forward_to_email") if forward_to_email: frappe.sendmail(recipients=forward_to_email, sender=sender, content=message, subject=subject) # add to to-do ? frappe.get_doc(dict( doctype = 'Communication', sender=sender, subject= _('New Message from Website Contact Page'), sent_or_received='Received', content=message, status='Open', )).insert(ignore_permissions=True) return "okay"
def db_set(self, fieldname, value=None, update_modified=True): '''Set a value in the document object, update the timestamp and update the database. WARNING: This method does not trigger controller validations and should be used very carefully. :param fieldname: fieldname of the property to be updated, or a {"field":"value"} dictionary :param value: value of the property to be updated :param update_modified: default True. updates the `modified` and `modified_by` properties ''' if isinstance(fieldname, dict): self.update(fieldname) else: self.set(fieldname, value) if update_modified and (self.doctype, self.name) not in frappe.flags.currently_saving: # don't update modified timestamp if called from post save methods # like on_update or on_submit self.set("modified", now()) self.set("modified_by", frappe.session.user) frappe.db.set_value(self.doctype, self.name, fieldname, value, self.modified, self.modified_by, update_modified=update_modified) self.run_method('on_change')
def __init__(self, content): """Parses headers, content, attachments from given raw message. :param content: Raw message.""" import email, email.utils import datetime self.raw = content self.mail = email.message_from_string(self.raw) self.text_content = '' self.html_content = '' self.attachments = [] self.cid_map = {} self.parse() self.set_content_and_type() self.set_subject() # gmail mailing-list compatibility # use X-Original-Sender if available, as gmail sometimes modifies the 'From' _from_email = self.mail.get("X-Original-From") or self.mail["From"] self.from_email = extract_email_id(_from_email) self.from_real_name = email.utils.parseaddr(_from_email)[0] if self.mail["Date"]: utc = email.utils.mktime_tz(email.utils.parsedate_tz(self.mail["Date"])) utc_dt = datetime.datetime.utcfromtimestamp(utc) self.date = convert_utc_to_user_timezone(utc_dt).strftime('%Y-%m-%d %H:%M:%S') else: self.date = now()
def make_course_schedule_test_record(**args): args = frappe._dict(args) course_schedule = frappe.new_doc("Course Schedule") course_schedule.student_group = args.student_group or "_Test Student Group" course_schedule.course = args.course or "_Test Course" course_schedule.instructor = args.instructor or "_T-Instructor-00001" course_schedule.room = args.room or "RM0001" course_schedule.from_time = args.from_time or (get_datetime(now()) + datetime.timedelta(minutes=10)) course_schedule.to_time = args.to_time or course_schedule.from_time + datetime.timedelta(hours= 1) if not args.do_not_save: if args.simulate: while True: try: course_schedule.save() break except OverlapError: course_schedule.from_time = course_schedule.from_time + datetime.timedelta(minutes=10) course_schedule.to_time = course_schedule.from_time + datetime.timedelta(hours= 1) else: course_schedule.save() return course_schedule
def change_modified_of_parent(self): if frappe.flags.in_import: return parent_list = frappe.db.sql("""SELECT parent from tabDocField where fieldtype="Table" and options=%s""", self.name) for p in parent_list: frappe.db.sql('UPDATE tabDocType SET modified=%s WHERE `name`=%s', (now(), p[0]))
def add_or_update_sitemap(self): page_name = self.get_page_name() existing_site_map = frappe.db.get_value("Website Route", {"ref_doctype": self.doctype, "docname": self.name}) if self.modified: lastmod = frappe.utils.get_datetime(self.modified).strftime("%Y-%m-%d") else: lastmod = now() opts = frappe._dict({ "page_or_generator": "Generator", "ref_doctype":self.doctype, "idx": self.idx, "docname": self.name, "page_name": page_name, "link_name": self.website_template.name, "lastmod": lastmod, "parent_website_route": self.get_parent_website_route(), "page_title": self.get_page_title(), "public_read": 1 if not self.website_template.no_sidebar else 0 }) self.update_permissions(opts) if existing_site_map: idx = update_sitemap(existing_site_map, opts) else: idx = add_to_sitemap(opts) if idx!=None and self.idx != idx: frappe.db.set(self, "idx", idx)
def create_ip_download_log(file_name, download_form, validity): start_download_validity_count_down(download_form, validity) idl = frappe.new_doc("IP Download Log") idl.user_id = frappe.session.user idl.file_name = file_name idl.downloaded_datetime = now() idl.save(ignore_permissions=True)
def touch(self, doctype, docname): """Update the modified timestamp of this document.""" from frappe.utils import now modified = now() frappe.db.sql("""update `tab{doctype}` set `modified`=%s where name=%s""".format(doctype=doctype), (modified, docname)) return modified
def create_asset_movement(**args): args = frappe._dict(args) if not args.transaction_date: args.transaction_date = now() movement = frappe.new_doc("Asset Movement") movement.update({ "asset": args.asset, "transaction_date": args.transaction_date, "target_location": args.target_location, "company": args.company, 'purpose': args.purpose or 'Receipt', 'serial_no': args.serial_no, 'quantity': len(get_serial_nos(args.serial_no)) if args.serial_no else 1, 'from_employee': "_T-Employee-00001" or args.from_employee, 'to_employee': args.to_employee }) if args.source_location: movement.update({ 'source_location': args.source_location }) movement.insert() movement.submit() return movement
def get_context(context): """generate rss feed""" host = get_request_site_address() blog_list = frappe.db.sql("""\ select page_name as name, published_on, modified, title, content from `tabBlog Post` where ifnull(published,0)=1 order by published_on desc limit 20""", as_dict=1) for blog in blog_list: blog_page = cstr(urllib.quote(blog.name.encode("utf-8"))) + ".html" blog.link = urllib.basejoin(host, blog_page) blog.content = escape_html(blog.content or "") if blog_list: modified = max((blog['modified'] for blog in blog_list)) else: modified = now() blog_settings = frappe.get_doc('Blog Settings', 'Blog Settings') context = { 'title': blog_settings.blog_title or "Blog", 'description': blog_settings.blog_introduction or "", 'modified': modified, 'items': blog_list, 'link': host + '/blog' } # print context return context
def update_add_node(doc, parent, parent_field): """ insert a new node """ n = now() doctype = doc.doctype name = doc.name # get the last sibling of the parent if parent: left, right = frappe.db.sql( "select lft, rgt from `tab{0}` where name=%s for update".format( doctype), parent)[0] validate_loop(doc.doctype, doc.name, left, right) else: # root right = frappe.db.sql(""" SELECT COALESCE(MAX(rgt), 0) + 1 FROM `tab{0}` WHERE COALESCE(`{1}`, '') = '' """.format(doctype, parent_field))[0][0] right = right or 1 # update all on the right frappe.db.sql( "update `tab{0}` set rgt = rgt+2, modified=%s where rgt >= %s".format( doctype), (n, right)) frappe.db.sql( "update `tab{0}` set lft = lft+2, modified=%s where lft >= %s".format( doctype), (n, right)) # update index of new node if frappe.db.sql( "select * from `tab{0}` where lft=%s or rgt=%s".format(doctype), (right, right + 1)): frappe.msgprint( _("Nested set error. Please contact the Administrator.")) raise Exception frappe.db.sql( "update `tab{0}` set lft=%s, rgt=%s, modified=%s where name=%s".format( doctype), (right, right + 1, n, name)) return right
def contact(email, full_name, country_code, subject, message, press=0): subject = "{0} ({1}): {2}".format( "EGD: PRESS CONTACT" if int(press) else "EGD: USER CONTACT", country_code, subject) email_to = None settings = frappe.get_single("Web Settings") for row in settings.contacts_x_country: if row.country_code == country_code: email_to = row.email if not email_to and settings.contact_default: email_to = settings.contact_default if site_env() == "local": email_to = settings.contact_default_local or None email = "{0} <{1}>".format(full_name, email) if email_to: from frappe.utils import now if frappe.db.sql( """SELECT COUNT(*) FROM `tabWeb Contact` WHERE TIMEDIFF(%s, modified) < '01:00:00'""", now())[0][0] > 500: return frappe.sendmail(recipients=email_to, sender=email, content=message, subject=subject, delayed=False) doc = frappe.get_doc({ "doctype": "Web Contact", "email": "-", "full_name": "-", "country_code": country_code, "forwarded_to": email_to, "subject": subject, "message": message, "language": frappe.local.lang, }) doc.insert(ignore_permissions=True) return "success"
def set_docstatus_user_and_timestamp(self): self._original_modified = self.modified self.modified = now() self.modified_by = frappe.session.user if not self.creation: self.creation = self.modified if not self.owner: self.owner = self.modified_by if self.docstatus == None: self.docstatus = 0 for d in self.get_all_children(): d.docstatus = self.docstatus d.modified = self.modified d.modified_by = self.modified_by if not d.owner: d.owner = self.owner if not d.creation: d.creation = self.creation
def test_scrap_material_qty(self): wo_order = make_wo_order_test_record(planned_start_date=now(), qty=2) # add raw materials to stores test_stock_entry.make_stock_entry(item_code="_Test Item", target="Stores - _TC", qty=10, basic_rate=5000.0) test_stock_entry.make_stock_entry( item_code="_Test Item Home Desktop 100", target="Stores - _TC", qty=10, basic_rate=1000.0) s = frappe.get_doc( make_stock_entry(wo_order.name, "Material Transfer for Manufacture", 2)) for d in s.get("items"): d.s_warehouse = "Stores - _TC" s.insert() s.submit() s = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 2)) s.insert() s.submit() wo_order_details = frappe.db.get_value( "Work Order", wo_order.name, ["scrap_warehouse", "qty", "produced_qty", "bom_no"], as_dict=1) scrap_item_details = get_scrap_item_details(wo_order_details.bom_no) self.assertEqual(wo_order_details.produced_qty, 2) for item in s.items: if item.bom_no and item.item_code in scrap_item_details: self.assertEqual(wo_order_details.scrap_warehouse, item.t_warehouse) self.assertEqual( flt(wo_order_details.qty) * flt(scrap_item_details[item.item_code]), item.qty)
def update_routes_of_descendants(self, old_route = None): if not self.is_new() and self.meta.get_field("parent_website_route"): if not old_route: old_route = frappe.get_doc(self.doctype, self.name).get_route() if old_route and old_route != self.get_route(): # clear cache of old routes old_routes = frappe.get_all(self.doctype, filters={"parent_website_route": ("like", old_route + "%")}) if old_routes: for like_old_route in old_routes: clear_cache(frappe.get_doc(self.doctype, like_old_route.name).get_route()) frappe.db.sql("""update `tab{0}` set parent_website_route = replace(parent_website_route, %s, %s), modified = %s, modified_by = %s where parent_website_route like %s""".format(self.doctype), (old_route, self.get_route(), now(), frappe.session.user, old_route + "%"))
def unlink_ref_doc_from_payment_entries(ref_doc): remove_ref_doc_link_from_jv(ref_doc.doctype, ref_doc.name) remove_ref_doc_link_from_pe(ref_doc.doctype, ref_doc.name) frappe.db.sql( """update `tabGL Entry` set against_voucher_type=null, against_voucher=null, modified=%s, modified_by=%s where against_voucher_type=%s and against_voucher=%s and voucher_no != ifnull(against_voucher, '')""", (now(), frappe.session.user, ref_doc.doctype, ref_doc.name), ) if ref_doc.doctype in ("Sales Invoice", "Purchase Invoice"): ref_doc.set("advances", []) frappe.db.sql( """delete from `tab{0} Advance` where parent = %s""".format(ref_doc.doctype), ref_doc.name )
def set_default_profile(pos_profile, company): modified = now() user = frappe.session.user company = frappe.db.escape(company) if pos_profile and company: frappe.db.sql(""" update `tabPOS Profile User` pfu, `tabPOS Profile` pf set pfu.default = 0, pf.modified = %s, pf.modified_by = %s where pfu.user = %s and pf.name = pfu.parent and pf.company = %s and pfu.default = 1""", (modified, user, user, company), auto_commit=1) frappe.db.sql(""" update `tabPOS Profile User` pfu, `tabPOS Profile` pf set pfu.default = 1, pf.modified = %s, pf.modified_by = %s where pfu.user = %s and pf.name = pfu.parent and pf.company = %s and pf.name = %s """, (modified, user, user, company, pos_profile), auto_commit=1)
def make_wo_order_test_record(**args): args = frappe._dict(args) if args.company and args.company != "_Test Company": warehouse_map = { "fg_warehouse": "_Test FG Warehouse", "wip_warehouse": "_Test WIP Warehouse" } for attr, wh_name in warehouse_map.items(): if not args.get(attr): args[attr] = create_warehouse(wh_name, company=args.company) wo_order = frappe.new_doc("Work Order") wo_order.production_item = args.production_item or args.item or args.item_code or "_Test FG Item" wo_order.bom_no = args.bom_no or frappe.db.get_value( "BOM", { "item": wo_order.production_item, "is_active": 1, "is_default": 1 }) wo_order.qty = args.qty or 10 wo_order.wip_warehouse = args.wip_warehouse or "_Test Warehouse - _TC" wo_order.fg_warehouse = args.fg_warehouse or "_Test Warehouse 1 - _TC" wo_order.scrap_warehouse = args.fg_warehouse or "_Test Scrap Warehouse - _TC" wo_order.company = args.company or "_Test Company" wo_order.stock_uom = args.stock_uom or "_Test UOM" wo_order.use_multi_level_bom = 0 wo_order.skip_transfer = args.skip_transfer or 0 wo_order.get_items_and_operations_from_bom() wo_order.sales_order = args.sales_order or None wo_order.planned_start_date = args.planned_start_date or now() wo_order.transfer_material_against = args.transfer_material_against or "Work Order" if args.source_warehouse: for item in wo_order.get("required_items"): item.source_warehouse = args.source_warehouse if not args.do_not_save: wo_order.insert() if not args.do_not_submit: wo_order.submit() return wo_order
def update_item_fields(self, args): items_with_fields_updates = json.loads( args["items_with_fields_updates"]) fields_to_update = json.loads(args["fields_to_update"]) print(fields_to_update) for item in items_with_fields_updates: item_code = frappe.db.get_value("Hub Item", { "hub_user_name": self.name, "item_code": item.get("item_code") }) hub_item = frappe.get_doc("Hub Item", item_code) for field in fields_to_update: hub_item.set(field, item.get(field)) hub_item.save(ignore_permissions=True) now_time = now() self.last_sync_datetime = now_time self.save(ignore_permissions=True) return {"total_items": len(items_with_fields_updates)}
def db_insert(self): """INSERT the document (with valid columns) in the database.""" if not self.name: # name will be set by document class in most cases set_new_name(self) if not self.creation: self.creation = self.modified = now() self.created_by = self.modifield_by = frappe.session.user d = self.get_valid_dict() columns = d.keys() try: frappe.db.sql( """insert into `tab{doctype}` ({columns}) values ({values})""".format( doctype=self.doctype, columns=", ".join(["`" + c + "`" for c in columns]), values=", ".join(["%s"] * len(columns))), d.values()) except Exception, e: if e.args[0] == 1062: if "PRIMARY" in cstr(e.args[1]): if self.meta.autoname == "hash": # hash collision? try again self.name = None self.db_insert() return type, value, traceback = sys.exc_info() frappe.msgprint( _("Duplicate name {0} {1}").format( self.doctype, self.name)) raise frappe.DuplicateEntryError, (self.doctype, self.name, e), traceback elif "Duplicate" in cstr(e.args[1]): # unique constraint self.show_unique_validation_message(e) else: raise else: raise
def get_new_messages(): last_update = frappe.cache().hget("notifications_last_update", frappe.session.user) now_timestamp = now() frappe.cache().hset("notifications_last_update", frappe.session.user, now_timestamp) if not last_update: return [] if last_update and time_diff_in_seconds(now_timestamp, last_update) > 1800: # no update for 30 mins, consider only the last 30 mins last_update = (now_datetime() - relativedelta(seconds=1800)).strftime(DATETIME_FORMAT) return frappe.db.sql("""select sender_full_name, content from `tabCommunication` where communication_type in ('Chat', 'Notification') and reference_doctype='user' and reference_name = %s and creation > %s order by creation desc""", (frappe.session.user, last_update), as_dict=1)
def set_value(self, dt, dn, field, val, modified=None, modified_by=None, update_modified=True, debug=False): """Set a single value in the database, do not call the ORM triggers but update the modified timestamp (unless specified not to). **Warning:** this function will not call Document events and should be avoided in normal cases. :param dt: DocType name. :param dn: Document name. :param field: Property / field name or dictionary of values to be updated :param value: Value to be updated. :param modified: Use this as the `modified` timestamp. :param modified_by: Set this user as `modified_by`. :param update_modified: default True. Set as false, if you don't want to update the timestamp. :param debug: Print the query in the developer / js console. """ if not modified: modified = now() if not modified_by:
def setUpClass(self): """Setting Up data for the tests defined under TestRenameDoc""" # set developer_mode to rename doc controllers self._original_developer_flag = frappe.conf.developer_mode frappe.conf.developer_mode = 1 # data generation: for base and merge tests self.available_documents = [] self.test_doctype = "ToDo" for num in range(1, 5): doc = frappe.get_doc({ "doctype": self.test_doctype, "date": add_to_date(now(), days=num), "description": "this is todo #{}".format(num), }).insert() self.available_documents.append(doc.name) # data generation: for controllers tests self.doctype = frappe._dict({ "old": "Test Rename Document Old", "new": "Test Rename Document New", }) frappe.get_doc({ "doctype": "DocType", "module": "Custom", "name": self.doctype.old, "custom": 0, "fields": [{ "label": "Some Field", "fieldname": "some_fieldname", "fieldtype": "Data" }], "permissions": [{ "role": "System Manager", "read": 1 }], }).insert()
def set_value(self, dt, dn, field, val, modified=None, modified_by=None, update_modified=True, debug=False): """Set a single value in the database, do not call the ORM triggers but update the modified timestamp (unless specified not to). **Warning:** this function will not call Document events and should be avoided in normal cases. :param dt: DocType name. :param dn: Document name. :param field: Property / field name. :param value: Value to be updated. :param modified: Use this as the `modified` timestamp. :param modified_by: Set this user as `modified_by`. :param update_modified: default True. Set as false, if you don't want to update the timestamp. :param debug: Print the query in the developer / js console. """ if not modified: modified = now() if not modified_by: modified_by = frappe.session.user if dn and dt!=dn: conditions, values = self.build_conditions(dn) values.update({"val": val, "modified": modified, "modified_by": modified_by}) if update_modified: self.sql("""update `tab{0}` set `{1}`=%(val)s, modified=%(modified)s, modified_by=%(modified_by)s where {2}""".format(dt, field, conditions), values, debug=debug) else: self.sql("""update `tab{0}` set `{1}`=%(val)s where {2}""".format(dt, field, conditions), values, debug=debug) else: self.sql("delete from tabSingles where field=%s and doctype=%s", (field, dt)) self.sql("insert into tabSingles(doctype, field, value) values (%s, %s, %s)", (dt, field, val), debug=debug) if update_modified and (field not in ("modified", "modified_by")): self.set_value(dt, dn, "modified", modified) self.set_value(dt, dn, "modified_by", modified_by)
def db_insert(self): """INSERT the document (with valid columns) in the database.""" if not self.name: # name will be set by document class in most cases set_new_name(self) if not self.creation: self.creation = self.modified = now() self.created_by = self.modified_by = frappe.session.user d = self.get_valid_dict(convert_dates_to_str=True) columns = list(d) try: frappe.db.sql( """INSERT INTO `tab{doctype}` ({columns}) VALUES ({values})""".format(doctype=self.doctype, columns=", ".join( ["`" + c + "`" for c in columns]), values=", ".join(["%s"] * len(columns))), list(d.values())) except Exception as e: if frappe.db.is_primary_key_violation(e): if self.meta.autoname == "hash": # hash collision? try again self.name = None self.db_insert() return frappe.msgprint( _("Duplicate name {0} {1}").format(self.doctype, self.name)) raise frappe.DuplicateEntryError(self.doctype, self.name, e) elif frappe.db.is_unique_key_violation(e): # unique constraint self.show_unique_validation_message(e) else: raise self.set("__islocal", False)
def send_message(subject="Website Query", message="", sender=""): if not message: frappe.response["message"] = "Please write something" return if not sender: frappe.response["message"] = "Email Address Required" return # guest method, cap max writes per hour if ( frappe.db.sql( """select count(*) from `tabCommunication` where `sent_or_received`="Received" and TIMEDIFF(%s, modified) < '01:00:00'""", now(), )[0][0] > max_communications_per_hour ): frappe.response[ "message" ] = "Sorry: we believe we have received an unreasonably high number of requests of this kind. Please try later" return # send email forward_to_email = frappe.db.get_value("Contact Us Settings", None, "forward_to_email") if forward_to_email: frappe.sendmail(recipients=forward_to_email, sender=sender, content=message, subject=subject) # add to to-do ? frappe.get_doc( dict( doctype="Communication", sender=sender, subject=_("New Message from Website Contact Page"), sent_or_received="Received", content=message, status="Open", ) ).insert(ignore_permissions=True) return "okay"
def remove_ref_doc_link_from_jv(ref_type, ref_no, multiple_orders, sales_order=None): linked_jv = frappe.db.sql_list( """select parent from `tabJournal Entry Account` where reference_type=%s and reference_name=%s and docstatus < 2""", (ref_type, ref_no)) if linked_jv: frappe.db.sql( """update `tabJournal Entry Account` set reference_type=null, reference_name = null, modified=%s, modified_by=%s where reference_type=%s and reference_name=%s and docstatus < 2""", (now(), frappe.session.user, ref_type, ref_no)) frappe.msgprint( _("Journal Entries {0} are un-linked".format( "\n".join(linked_jv))))
def check_publish_status(): web_pages = frappe.get_all( "Web Page", fields=["name", "published", "start_date", "end_date"]) now_date = get_datetime(now()) for page in web_pages: start_date = page.start_date if page.start_date else "" end_date = page.end_date if page.end_date else "" if page.published: # Unpublish pages that are outside the set date ranges if (start_date and now_date < start_date) or (end_date and now_date > end_date): frappe.db.set_value("Web Page", page.name, "published", 0) else: # Publish pages that are inside the set date ranges if start_date: if not end_date or (end_date and now_date < end_date): frappe.db.set_value("Web Page", page.name, "published", 1)
def set_user_and_timestamp(self): if not hasattr(self, '_original_modified' ) or not self._original_modified or not self.modified: self._original_modified = self.modified self.modified = now() self.modified_by = frappe.session.user if not self.creation: self.creation = self.modified if not self.owner: self.owner = self.modified_by for d in self.get_all_children(): d.modified = self.modified d.modified_by = self.modified_by if not d.owner: d.owner = self.owner if not d.creation: d.creation = self.creation frappe.flags.currently_saving.append((self.doctype, self.name))
def create_asset_movement(**args): args = frappe._dict(args) if not args.transaction_date: args.transaction_date = now() movement = frappe.new_doc("Asset Movement") movement.update({ "assets": args.assets, "transaction_date": args.transaction_date, "company": args.company, "purpose": args.purpose or "Receipt", "reference_doctype": args.reference_doctype, "reference_name": args.reference_name, }) movement.insert() movement.submit() return movement
def db_set(self, fieldname, value=None, update_modified=True, notify=False, commit=False): """Set a value in the document object, update the timestamp and update the database. WARNING: This method does not trigger controller validations and should be used very carefully. :param fieldname: fieldname of the property to be updated, or a {"field":"value"} dictionary :param value: value of the property to be updated :param update_modified: default True. updates the `modified` and `modified_by` properties :param notify: default False. run doc.notify_updated() to send updates via socketio :param commit: default False. run frappe.db.commit() """ if isinstance(fieldname, dict): self.update(fieldname) else: self.set(fieldname, value) if update_modified and (self.doctype, self.name) not in frappe.flags.currently_saving: # don't update modified timestamp if called from post save methods # like on_update or on_submit self.set("modified", now()) self.set("modified_by", frappe.session.user) # load but do not reload doc_before_save because before_change or on_change might expect it if not self.get_doc_before_save(): self.load_doc_before_save() # to trigger notification on value change self.run_method('before_change') frappe.db.set_value(self.doctype, self.name, fieldname, value, self.modified, self.modified_by, update_modified=update_modified) self.run_method('on_change') if notify: self.notify_update() self.clear_cache() if commit: frappe.db.commit()
def backup(context, with_files=False, backup_path_db=None, backup_path_files=None, backup_path_private_files=None, quiet=False, verbose=False): "Backup" from frappe.utils.backups import scheduled_backup verbose = verbose or context.verbose exit_code = 0 for site in context.sites: try: frappe.init(site=site) frappe.connect() odb = scheduled_backup( ignore_files=not with_files, backup_path_db=backup_path_db, backup_path_files=backup_path_files, backup_path_private_files=backup_path_private_files, force=True, verbose=verbose) except Exception as e: if verbose: print( "Backup failed for {0}. Database or site_config.json may be corrupted" .format(site)) exit_code = 1 continue if verbose: from frappe.utils import now summary_title = "Backup Summary at {0}".format(now()) print(summary_title + "\n" + "-" * len(summary_title)) print("Database backup:", odb.backup_path_db) if with_files: print("Public files: ", odb.backup_path_files) print("Private files: ", odb.backup_path_private_files) frappe.destroy() sys.exit(exit_code)
def on_cancel(self): frappe.db.sql( """update `tabGL Entry` set `is_cancelled` = 1, modified=%s, modified_by=%s where against_voucher=%s and voucher_number=%s and is_cancelled = 0""", (now(), frappe.session.user, "Sales Invoice", self.name)) gl_entry = frappe.get_doc({ "doctype": "GL Entry", "posting_date": self.posting_date, "transaction_date": self.posting_date, "account": self.credit_account, "party_type": "Customer", "party": self.customer, "debit": self.total_amount, "credit": 0, "against": self.debit_account, "against_voucher": "Sales Invoice", "voucher_number": self.name, "company": self.company, "fiscal_year": "2020-2021", "is_cancelled": 1 }) gl_entry.insert() gl_entry = frappe.get_doc({ "doctype": "GL Entry", "posting_date": self.posting_date, "transaction_date": self.posting_date, "account": self.debit_account, "party_type": "Customer", "party": self.customer, "debit": 0, "credit": self.total_amount, "against": self.credit_account, "against_voucher": "Sales Invoice", "voucher_number": self.name, "company": self.company, "fiscal_year": "2020-2021", "is_cancelled": 1 }) gl_entry.insert()
def sync_entity_from_magento(): """ check and decide which entity to sync """ conf = frappe.get_doc("API Configuration Page", "API Configuration Page") if get_datetime(now()) > get_datetime(conf.date): get_and_sync_entities(api_type=conf.api_type) elif conf.api_type != "Product": prev_type = { "Order": "Customer", "Customer": "Product" } get_and_sync_entities(api_type=prev_type[conf.api_type], update_config=False) start = now_datetime() total_entities_to_resync = get_sync_error_entities_count(entity_map[conf.api_type]) if not total_entities_to_resync: return sync_stat = missing_entity_methods[conf.api_type]() end = now_datetime() log_sync_status( entity_map[conf.api_type], count_response=total_entities_to_resync, entities_to_sync=total_entities_to_resync, pages_to_sync=1, entities_received=0, synced_entities=sync_stat, start=start, end=end, is_resync=True )
def update_job_card(job_card): job_card_doc = frappe.get_doc('Job Card', job_card) job_card_doc.set('scrap_items', [ { 'item_code': 'Test RM Item 1 for Scrap Item Test', 'stock_qty': 2 }, { 'item_code': 'Test RM Item 2 for Scrap Item Test', 'stock_qty': 2 }, ]) job_card_doc.append( 'time_logs', { 'from_time': now(), 'time_in_mins': 60, 'completed_qty': job_card_doc.for_quantity }) job_card_doc.submit()
def remove_ref_doc_link_from_jv(ref_type, ref_no): linked_jv = frappe.db.sql_list( """select parent from `tabJournal Entry Account` where reference_type=%s and reference_name=%s and docstatus < 2""", (ref_type, ref_no)) if linked_jv: frappe.db.sql( """update `tabJournal Entry Account` set reference_type=null, reference_name = null, modified=%s, modified_by=%s where reference_type=%s and reference_name=%s and docstatus < 2""", (now(), frappe.session.user, ref_type, ref_no)) msg_jv_list = [ "<a href='#Form/Journal Entry/{0}'>{0}</a>".format(jv) for jv in list(set(linked_jv)) ] frappe.msgprint( _("Journal Entries {0} are un-linked").format( ", ".join(msg_jv_list)))
def get_refresh_token(self): refresh_t = get_pw("Lazada Settings", "refresh_token") client = LazopClient("https://auth.lazada.com/rest", self.api_key, self.api_secret) request = LazopRequest('/auth/token/refresh') request.add_api_param("refresh_token", refresh_t) response = client.execute(request) # frappe.msgprint(str(response.body)) # frappe.msgprint(str(now())) if response.body['code'] == '0': frappe.db.set_value("Lazada Settings", None, "access_token", response.body["access_token"]) frappe.db.set_value("Lazada Settings", None, "refresh_token", response.body['refresh_token']) frappe.db.set_value("Lazada Settings", None, "last_sync_access_token", now()) frappe.msgprint( "Access Token has been refreshed successfully. Please Reload Page!" ) else: frappe.msgprint("Error Occured While Refreshing Acces token.")
def get_valuation_rate(self, args): """ Get average valuation rate of relevant warehouses as per valuation method (MAR/FIFO) as on costing date """ from erpnext.stock.utils import get_incoming_rate posting_date, posting_time = nowdate(), now().split()[1] warehouse = frappe.db.sql("select warehouse from `tabBin` where item_code = %s", args['item_code']) rate = [] for wh in warehouse: r = get_incoming_rate({ "item_code": args.get("item_code"), "warehouse": wh[0], "posting_date": posting_date, "posting_time": posting_time, "qty": args.get("qty") or 0 }) if r: rate.append(r) return rate and flt(sum(rate))/len(rate) or 0
def run_batch_script(self): task = frappe.get_doc("IOT Batch Task", self.parent) if self.status != 'New': return frappe.logger(__name__).info("Run batch script {0} on device {1}".format(task.name, self.device)) try: from iot.device_api import send_action id = send_action("sys", action="batch_script", device=self.device, data=task.batch_script) if not id: throw("Send action failed") self.__set_val("status", "Running") self.__set_val("action_id", id) self.__set_val("action_starttime", now()) except Exception as ex: frappe.logger(__name__).error(_("Run batch script {0} on {1} failed. {2}").format(task.name, self.device, repr(ex))) self.__set_val("status", 'Error') self.__set_val("info", repr(ex)) finally: frappe.db.commit()
def test_rename_doc(self): from random import choice, sample available_documents = [] doctype = "ToDo" # data generation: 4 todo documents for num in range(1, 5): doc = frappe.get_doc({ "doctype": doctype, "date": add_to_date(now(), days=num), "description": "this is todo #{}".format(num) }).insert() available_documents.append(doc.name) # test 1: document renaming old_name = choice(available_documents) new_name = old_name + '.new' self.assertEqual(new_name, frappe.rename_doc(doctype, old_name, new_name, force=True)) available_documents.remove(old_name) available_documents.append(new_name) # test 2: merge documents first_todo, second_todo = sample(available_documents, 2) second_todo_doc = frappe.get_doc(doctype, second_todo) second_todo_doc.priority = "High" second_todo_doc.save() merged_todo = frappe.rename_doc(doctype, first_todo, second_todo, merge=True, force=True) merged_todo_doc = frappe.get_doc(doctype, merged_todo) available_documents.remove(first_todo) with self.assertRaises(frappe.DoesNotExistError): frappe.get_doc(doctype, first_todo) self.assertEqual(merged_todo_doc.priority, second_todo_doc.priority) for docname in available_documents: frappe.delete_doc(doctype, docname)