def get_html_table(self, columns=None, data=None): date_time = global_date_format(now()) + ' ' + format_time(now()) report_doctype = dataent.db.get_value('Report', self.report, 'ref_doctype') return dataent.render_template( 'dataent/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 backup(context, with_files=False, backup_path_db=None, backup_path_files=None, backup_path_private_files=None, quiet=False): "Backup" from dataent.utils.backups import scheduled_backup verbose = context.verbose for site in context.sites: dataent.init(site=site) dataent.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 dataent.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()) dataent.destroy()
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 = dataent.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 send_message(subject="Website Query", message="", sender=""): if not message: dataent.response["message"] = 'Please write something' return if not sender: dataent.response["message"] = 'Email Address Required' return # guest method, cap max writes per hour if dataent.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: dataent.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 = dataent.db.get_value("Contact Us Settings", None, "forward_to_email") if forward_to_email: dataent.sendmail(recipients=forward_to_email, sender=sender, content=message, subject=subject) # add to to-do ? dataent.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 get_context(context): """generate rss feed""" host = get_request_site_address() blog_list = dataent.db.sql("""\ select route 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(quote(blog.name.encode("utf-8"))) blog.link = urljoin(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 = dataent.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 rebuild_node(doctype, parent, left, parent_field): """ reset lft, rgt and recursive call for all children """ from dataent.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 = dataent.db.sql( "SELECT name FROM `tab{0}` WHERE `{1}`=%s".format( doctype, parent_field), (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 dataent.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 create_asset_movement(**args): args = dataent._dict(args) if not args.transaction_date: args.transaction_date = now() movement = dataent.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 test_allow_overproduction(self): allow_overproduction("overproduction_percentage_for_work_order", 0) wo_order = make_wo_order_test_record(planned_start_date=now(), qty=2) test_stock_entry.make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=10, basic_rate=5000.0) test_stock_entry.make_stock_entry( item_code="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=10, basic_rate=1000.0) s = dataent.get_doc( make_stock_entry(wo_order.name, "Material Transfer for Manufacture", 3)) s.insert() self.assertRaises(StockOverProductionError, s.submit) allow_overproduction("overproduction_percentage_for_work_order", 50) s.load_from_db() s.submit() self.assertEqual(s.docstatus, 1) allow_overproduction("overproduction_percentage_for_work_order", 0)
def touch(self, doctype, docname): """Update the modified timestamp of this document.""" from dataent.utils import now modified = now() dataent.db.sql( """update `tab{doctype}` set `modified`=%s where name=%s""".format(doctype=doctype), (modified, docname)) return modified
def update_modified(self): '''Update modified timestamp''' self.set("modified", now()) dataent.db.set_value(self.doctype, self.name, 'modified', self.modified, update_modified=False)
def change_modified_of_parent(self): """Change the timestamp of parent DocType if the current one is a child to clear caches.""" if dataent.flags.in_import: return parent_list = dataent.db.sql( """SELECT parent from tabDocField where fieldtype="Table" and options=%s""", self.name) for p in parent_list: dataent.db.sql('UPDATE tabDocType SET modified=%s WHERE `name`=%s', (now(), p[0]))
def test_planned_operating_cost(self): wo_order = make_wo_order_test_record(item="_Test FG Item 2", planned_start_date=now(), qty=1, do_not_save=True) wo_order.set_work_order_operations() cost = wo_order.planned_operating_cost wo_order.qty = 2 wo_order.set_work_order_operations() self.assertEqual(wo_order.planned_operating_cost, cost * 2)
def test_over_production_for_sales_order(self): so = make_sales_order(item_code="_Test FG Item", qty=2) allow_overproduction("overproduction_percentage_for_sales_order", 0) wo_order = make_wo_order_test_record(planned_start_date=now(), sales_order=so.name, qty=3, do_not_save=True) self.assertRaises(OverProductionError, wo_order.save) allow_overproduction("overproduction_percentage_for_sales_order", 50) wo_order = make_wo_order_test_record(planned_start_date=now(), sales_order=so.name, qty=3) wo_order.submit() self.assertEqual(wo_order.docstatus, 1) allow_overproduction("overproduction_percentage_for_sales_order", 0)
def remove_ref_doc_link_from_jv(ref_type, ref_no): linked_jv = dataent.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: dataent.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(), dataent.session.user, ref_type, ref_no)) dataent.msgprint(_("Journal Entries {0} are un-linked".format("\n".join(linked_jv))))
def remove_ref_doc_link_from_pe(ref_type, ref_no): linked_pe = dataent.db.sql_list("""select parent from `tabPayment Entry Reference` where reference_doctype=%s and reference_name=%s and docstatus < 2""", (ref_type, ref_no)) if linked_pe: dataent.db.sql("""update `tabPayment Entry Reference` set allocated_amount=0, modified=%s, modified_by=%s where reference_doctype=%s and reference_name=%s and docstatus < 2""", (now(), dataent.session.user, ref_type, ref_no)) for pe in linked_pe: pe_doc = dataent.get_doc("Payment Entry", pe) pe_doc.set_total_allocated_amount() pe_doc.set_unallocated_amount() pe_doc.clear_unallocated_reference_document_rows() dataent.db.sql("""update `tabPayment Entry` set total_allocated_amount=%s, base_total_allocated_amount=%s, unallocated_amount=%s, modified=%s, modified_by=%s where name=%s""", (pe_doc.total_allocated_amount, pe_doc.base_total_allocated_amount, pe_doc.unallocated_amount, now(), dataent.session.user, pe)) dataent.msgprint(_("Payment Entries {0} are un-linked".format("\n".join(linked_pe))))
def validate_dates(self): if self.end_date: if self.start_date and get_datetime(self.end_date) < get_datetime( self.start_date): dataent.throw(_("End Date cannot be before Start Date!")) # If the current date is past end date, and # web page is published, empty the end date if self.published and now() > self.end_date: self.end_date = None dataent.msgprint( _("Clearing end date, as it cannot be in the past for published pages." ))
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 dataent.db.commit() ''' if isinstance(fieldname, dict): self.update(fieldname) else: self.set(fieldname, value) if update_modified and ( self.doctype, self.name) not in dataent.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", dataent.session.user) # to trigger notification on value change self.run_method('before_change') dataent.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: dataent.db.commit()
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) dataent.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(), dataent.session.user, ref_doc.doctype, ref_doc.name)) if ref_doc.doctype in ("Sales Invoice", "Purchase Invoice"): ref_doc.set("advances", []) dataent.db.sql("""delete from `tab{0} Advance` where parent = %s""" .format(ref_doc.doctype), ref_doc.name)
def set_user_and_timestamp(self): self._original_modified = self.modified self.modified = now() self.modified_by = dataent.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 dataent.flags.currently_saving.append((self.doctype, self.name))
def set_default_profile(pos_profile, company): modified = now() user = dataent.session.user company = dataent.db.escape(company) if pos_profile and company: dataent.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) dataent.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 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 = dataent.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 = dataent.get_doc(make_stock_entry(wo_order.name, "Manufacture", 2)) s.insert() s.submit() wo_order_details = dataent.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 check_publish_status(): web_pages = dataent.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): dataent.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): dataent.db.set_value("Web Page", page.name, "published", 1)
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 = dataent.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 = dataent.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 dataent.db.sql( "update `tab{0}` set rgt = rgt+2, modified=%s where rgt >= %s".format( doctype), (n, right)) dataent.db.sql( "update `tab{0}` set lft = lft+2, modified=%s where lft >= %s".format( doctype), (n, right)) # update index of new node if dataent.db.sql( "select * from `tab{0}` where lft=%s or rgt=%s".format(doctype), (right, right + 1)): dataent.msgprint( _("Nested set error. Please contact the Administrator.")) raise Exception dataent.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 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 = dataent.session.user d = self.get_valid_dict(convert_dates_to_str=True) columns = list(d) try: dataent.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 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 raise dataent.DuplicateEntryError(self.doctype, self.name, e) elif "Duplicate" in cstr(e.args[1]): # unique constraint self.show_unique_validation_message(e) else: raise else: raise self.set("__islocal", False)
def get_new_messages(): last_update = dataent.cache().hget("notifications_last_update", dataent.session.user) now_timestamp = now() dataent.cache().hset("notifications_last_update", dataent.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 dataent.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""", (dataent.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: modified_by = dataent.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] dataent.clear_document_cache(dt, dn)
def before_insert(self): self.full_name = get_fullname(self.user) self.date = now()
def set_as_cancel(voucher_type, voucher_no): dataent.db.sql( """update `tabStock Ledger Entry` set is_cancelled='Yes', modified=%s, modified_by=%s where voucher_no=%s and voucher_type=%s""", (now(), dataent.session.user, voucher_type, voucher_no))
def update_move_node(doc, parent_field): n = now() parent = doc.get(parent_field) if parent: new_parent = dataent.db.sql("""select lft, rgt from `tab{0}` where name = %s""".format(doc.doctype), parent, as_dict=1)[0] validate_loop(doc.doctype, doc.name, new_parent.lft, new_parent.rgt) # move to dark side dataent.db.sql( """update `tab{0}` set lft = -lft, rgt = -rgt, modified=%s where lft >= %s and rgt <= %s""".format(doc.doctype), (n, doc.lft, doc.rgt)) # shift left diff = doc.rgt - doc.lft + 1 dataent.db.sql( """update `tab{0}` set lft = lft -%s, rgt = rgt - %s, modified=%s where lft > %s""".format(doc.doctype), (diff, diff, n, doc.rgt)) # shift left rgts of ancestors whose only rgts must shift dataent.db.sql( """update `tab{0}` set rgt = rgt - %s, modified=%s where lft < %s and rgt > %s""".format(doc.doctype), (diff, n, doc.lft, doc.rgt)) if parent: new_parent = dataent.db.sql("""select lft, rgt from `tab%s` where name = %s""" % (doc.doctype, '%s'), parent, as_dict=1)[0] # set parent lft, rgt dataent.db.sql( """update `tab{0}` set rgt = rgt + %s, modified=%s where name = %s""".format(doc.doctype), (diff, n, parent)) # shift right at new parent dataent.db.sql( """update `tab{0}` set lft = lft + %s, rgt = rgt + %s, modified=%s where lft > %s""".format(doc.doctype), (diff, diff, n, new_parent.rgt)) # shift right rgts of ancestors whose only rgts must shift dataent.db.sql( """update `tab{0}` set rgt = rgt + %s, modified=%s where lft < %s and rgt > %s""".format(doc.doctype), (diff, n, new_parent.lft, new_parent.rgt)) new_diff = new_parent.rgt - doc.lft else: # new root max_rgt = dataent.db.sql("""select max(rgt) from `tab{0}`""".format( doc.doctype))[0][0] new_diff = max_rgt + 1 - doc.lft # bring back from dark side dataent.db.sql( """update `tab{0}` set lft = -lft + %s, rgt = -rgt + %s, modified=%s where lft < 0""".format(doc.doctype), (new_diff, new_diff, n))