def submit_salary_slips(self): self.check_permission('write') ss_list = self.get_sal_slip_list(ss_status=0) if len(ss_list) > 30: frappe.enqueue(submit_salary_slips_for_employees, timeout=600, payroll_entry=self, salary_slips=ss_list) else: submit_salary_slips_for_employees(self, ss_list, publish_progress=False)
def ipn_handler(): try: data = frappe.local.form_dict validate_ipn_request(data) data.update({ "payment_gateway": "PayPal" }) doc = frappe.get_doc({ "data": json.dumps(frappe.local.form_dict), "doctype": "Integration Request", "integration_type": "Subscription Notification", "status": "Queued" }).insert(ignore_permissions=True) frappe.db.commit() frappe.enqueue(method='frappe.integrations.doctype.paypal_settings.paypal_settings.handle_subscription_notification', queue='long', timeout=600, is_async=True, **{"doctype": "Integration Request", "docname": doc.name}) except frappe.InvalidStatusError: pass except Exception as e: frappe.log(frappe.log_error(title=e))
def history(room, fields = None, limit = 10, start = None, end = None): room = frappe.get_doc('Chat Room', room) mess = frappe.get_all('Chat Message', filters = [ ('Chat Message', 'room', '=', room.name), ('Chat Message', 'room_type', '=', room.type) ], fields = fields if fields else [ 'name', 'room_type', 'room', 'content', 'type', 'user', 'mentions', 'urls', 'creation', '_seen' ], order_by = 'creation' ) if not fields or 'seen' in fields: for m in mess: m['seen'] = json.loads(m._seen) if m._seen else [ ] del m['_seen'] if not fields or 'content' in fields: for m in mess: m['content'] = json.loads(m.content) if m.type in ["File"] else m.content frappe.enqueue('frappe.chat.doctype.chat_message.chat_message.mark_messages_as_seen', message_names=[m.name for m in mess], user=frappe.session.user) return mess
def automatic_synchronization(): settings = frappe.get_doc("Plaid Settings", "Plaid Settings") if settings.enabled == 1 and settings.automatic_sync == 1: plaid_accounts = frappe.get_all("Bank Account", filter={"integration_id": ["!=", ""]}, fields=["name", "bank"]) for plaid_account in plaid_accounts: frappe.enqueue("erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.sync_transactions", bank=plaid_account.bank, bank_account=plaid_account.name)
def make_auto_repeat_entry(date=None): enqueued_method = 'frappe.desk.doctype.auto_repeat.auto_repeat.create_repeated_entries' jobs = get_jobs() if not jobs or enqueued_method not in jobs[frappe.local.site]: date = date or today() for data in get_auto_repeat_entries(date): frappe.enqueue(enqueued_method, data=data)
def _webhook_request(webhook): if not webhook.name in frappe.flags.webhooks_executed.get(doc.name, []): frappe.enqueue("frappe.integrations.doctype.webhook.webhook.enqueue_webhook", enqueue_after_commit=True, doc=doc, webhook=webhook) # keep list of webhooks executed for this doc in this request # so that we don't run the same webhook for the same document multiple times # in one request frappe.flags.webhooks_executed.setdefault(doc.name, []).append(webhook.name)
def on_update(self): # clear new password self.validate_user_limit() self.share_with_self() clear_notifications(user=self.name) frappe.clear_cache(user=self.name) self.send_password_notification(self.__new_password) if self.name not in ('Administrator', 'Guest') and not self.user_image: frappe.enqueue('frappe.core.doctype.user.user.update_gravatar', name=self.name)
def setup(company=None, patch=True): make_custom_fields() add_permissions() add_custom_roles_for_reports() frappe.enqueue('erpnext.regional.india.setup.add_hsn_sac_codes', now=frappe.flags.in_test) add_print_formats() if not patch: update_address_template() make_fixtures()
def enqueue_global_search(): if frappe.flags.update_global_search: try: frappe.enqueue('frappe.utils.global_search.sync_global_search', now=frappe.flags.in_test or frappe.flags.in_install or frappe.flags.in_migrate, flags=frappe.flags.update_global_search, enqueue_after_commit=True) except redis.exceptions.ConnectionError: sync_global_search() frappe.flags.update_global_search = []
def send_reminder(): frappe.has_permission('GST Settings', throw=True) last_sent = frappe.db.get_single_value('GST Settings', 'gstin_email_sent_on') if last_sent and date_diff(nowdate(), last_sent) < 3: frappe.throw("Please wait 3 days before resending the reminder.") frappe.db.set_value('GST Settings', 'GST Settings', 'gstin_email_sent_on', nowdate()) # enqueue if large number of customers, suppliser frappe.enqueue('erpnext.regional.doctype.gst_settings.gst_settings.send_gstin_reminder_to_all_parties') frappe.msgprint('Email Reminders will be sent to all parties with email contacts')
def assign_salary_structure(self, grade=None, department=None, designation=None,employee=None, from_date=None, base=None,variable=None): employees = self.get_employees(grade= grade,department= department,designation= designation,name=employee) if employees: if len(employees) > 20: frappe.enqueue(assign_salary_structure_for_employees, timeout=600, employees=employees, salary_structure=self,from_date=from_date, base=base,variable=variable) else: assign_salary_structure_for_employees(employees, self,from_date=from_date, base=base,variable=variable) else: frappe.msgprint(_("No Employee Found"))
def enqueue_multiple_variant_creation(item, args): # There can be innumerable attribute combinations, enqueue if isinstance(args, basestring): variants = json.loads(args) total_variants = 1 for key in variants: total_variants *= len(variants[key]) if total_variants >= 600: frappe.msgprint("Please do not create more than 500 items at a time", raise_exception=1) return frappe.enqueue("erpnext.controllers.item_variant.create_multiple_variants", item=item, args=args, now=frappe.flags.in_test);
def update_variants(self): if self.flags.dont_update_variants or \ frappe.db.get_single_value('Item Variant Settings', 'do_not_update_variants'): return if self.has_variants: variants = frappe.db.get_all("Item", fields=["item_code"], filters={"variant_of": self.name}) if variants: if len(variants) <= 30: update_variants(variants, self, publish_progress=False) frappe.msgprint(_("Item Variants updated")) else: frappe.enqueue("erpnext.stock.doctype.item.item.update_variants", variants=variants, template=self, now=frappe.flags.in_test, timeout=600)
def sync(self): """Create and execute Data Migration Run for GCalendar Sync plan""" frappe.has_permission('GCalendar Settings', throw=True) accounts = frappe.get_all("GCalendar Account", filters={'enabled': 1}) queued_jobs = get_jobs(site=frappe.local.site, key='job_name')[frappe.local.site] for account in accounts: job_name = 'google_calendar_sync|{0}'.format(account.name) if job_name not in queued_jobs: frappe.enqueue('frappe.integrations.doctype.gcalendar_settings.gcalendar_settings.run_sync', queue='long', timeout=1500, job_name=job_name, account=account) time.sleep(5)
def dump_request_data(data, event="create/order"): event_mapper = { "orders/create": get_webhook_address(connector_name='shopify_connection', method="sync_sales_order", exclude_uri=True), "orders/paid" : get_webhook_address(connector_name='shopify_connection', method="prepare_sales_invoice", exclude_uri=True), "orders/fulfilled": get_webhook_address(connector_name='shopify_connection', method="prepare_delivery_note", exclude_uri=True) } log = frappe.get_doc({ "doctype": "Shopify Log", "request_data": json.dumps(data, indent=1), "method": event_mapper[event] }).insert(ignore_permissions=True) frappe.db.commit() frappe.enqueue(method=event_mapper[event], queue='short', timeout=300, is_async=True, **{"order": data, "request_id": log.name})
def sync_global_search(self): '''If global search settings are changed, rebuild search properties for this table''' global_search_fields_before_update = [d.fieldname for d in self.before_update.fields if d.in_global_search] if self.before_update.show_name_in_global_search: global_search_fields_before_update.append('name') global_search_fields_after_update = [d.fieldname for d in self.fields if d.in_global_search] if self.show_name_in_global_search: global_search_fields_after_update.append('name') if set(global_search_fields_before_update) != set(global_search_fields_after_update): now = (not frappe.request) or frappe.flags.in_test or frappe.flags.in_install frappe.enqueue('frappe.utils.global_search.rebuild_for_doctype', now=now, doctype=self.name)
def grant_leave_allocation(self, grade=None, department=None, designation=None, employee=None, carry_forward_leaves=0): employees = self.get_employees({ "grade": grade, "department": department, "designation": designation, "name": employee }) if employees: if len(employees) > 20: frappe.enqueue(grant_leave_alloc_for_employees, timeout=600, employees=employees, leave_period=self, carry_forward_leaves=carry_forward_leaves) else: grant_leave_alloc_for_employees(employees, self, carry_forward_leaves) else: frappe.msgprint(_("No Employee Found"))
def trigger_feedback_request(doc, method): """Trigger the feedback alert, or delete feedback requests on delete""" def _get(): triggers = {} if not (frappe.flags.in_migrate or frappe.flags.in_install): for d in frappe.get_all('Feedback Trigger', dict(enabled=1), ['name', 'document_type']): triggers[d.document_type] = d.name return triggers feedback_triggers = frappe.cache().get_value('feedback_triggers', _get) if doc.doctype in feedback_triggers: if doc.flags.in_delete: frappe.enqueue('frappe.core.doctype.feedback_trigger.feedback_trigger.delete_feedback_request_and_feedback', reference_doctype=doc.doctype, reference_name=doc.name, now=frappe.flags.in_test) else: frappe.enqueue('frappe.core.doctype.feedback_trigger.feedback_trigger.send_feedback_request', trigger=feedback_triggers[doc.doctype], reference_doctype=doc.doctype, reference_name=doc.name, now=frappe.flags.in_test)
def on_submit(self): self.validate_pos_paid_amount() if not self.recurring_id: frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype, self.company, self.base_grand_total, self) self.check_prev_docstatus() if self.is_return: # NOTE status updating bypassed for is_return self.status_updater = [] self.update_status_updater_args() self.update_prevdoc_status() self.update_billing_status_in_dn() self.clear_unallocated_mode_of_payments() # Updating stock ledger should always be called after updating prevdoc status, # because updating reserved qty in bin depends upon updated delivered qty in SO if self.update_stock == 1: self.update_stock_ledger() # this sequence because outstanding may get -ve self.make_gl_entries() if not self.is_return: self.update_billing_status_for_zero_amount_refdoc("Sales Order") self.check_credit_limit() self.update_serial_no() if not cint(self.is_pos) == 1 and not self.is_return: self.update_against_document_in_jv() self.update_time_sheet(self.name) frappe.enqueue('erpnext.setup.doctype.company.company.update_company_current_month_sales', company=self.company)
def create_salary_slips(self): """ Creates salary slip for selected employees if already not created """ self.check_permission('write') self.created = 1 emp_list = [d.employee for d in self.get_emp_list()] if emp_list: args = frappe._dict({ "salary_slip_based_on_timesheet": self.salary_slip_based_on_timesheet, "payroll_frequency": self.payroll_frequency, "start_date": self.start_date, "end_date": self.end_date, "company": self.company, "posting_date": self.posting_date, "deduct_tax_for_unclaimed_employee_benefits": self.deduct_tax_for_unclaimed_employee_benefits, "deduct_tax_for_unsubmitted_tax_exemption_proof": self.deduct_tax_for_unsubmitted_tax_exemption_proof, "payroll_entry": self.name }) if len(emp_list) > 30: frappe.enqueue(create_salary_slips_for_employees, timeout=600, employees=emp_list, args=args) else: create_salary_slips_for_employees(emp_list, args, publish_progress=False)
def bulk_rename(doctype, rows=None, via_console = False): """Bulk rename documents :param doctype: DocType to be renamed :param rows: list of documents as `((oldname, newname), ..)`""" if not rows: frappe.throw(_("Please select a valid csv file with data")) if not via_console: max_rows = 500 if len(rows) > max_rows: frappe.throw(_("Maximum {0} rows allowed").format(max_rows)) rename_log = [] for row in rows: # if row has some content if len(row) > 1 and row[0] and row[1]: try: if rename_doc(doctype, row[0], row[1]): msg = _("Successful: {0} to {1}").format(row[0], row[1]) frappe.db.commit() else: msg = _("Ignored: {0} to {1}").format(row[0], row[1]) except Exception as e: msg = _("** Failed: {0} to {1}: {2}").format(row[0], row[1], repr(e)) frappe.db.rollback() if via_console: print(msg) else: rename_log.append(msg) frappe.enqueue('frappe.utils.global_search.rebuild_for_doctype', doctype=doctype) if not via_console: return rename_log
def save_customization(self): if not self.doc_type: return self.flags.update_db = False self.flags.rebuild_doctype_for_global_search = False self.set_property_setters() self.update_custom_fields() self.set_name_translation() validate_fields_for_doctype(self.doc_type) if self.flags.update_db: from frappe.model.db_schema import updatedb updatedb(self.doc_type) if not hasattr(self, 'hide_success') or not self.hide_success: frappe.msgprint(_("{0} updated").format(_(self.doc_type))) frappe.clear_cache(doctype=self.doc_type) self.fetch_to_customize() if self.flags.rebuild_doctype_for_global_search: frappe.enqueue('frappe.utils.global_search.rebuild_for_doctype', now=True, doctype=self.doc_type)
def enqueue_multiple_variant_creation(item, args): # There can be innumerable attribute combinations, enqueue frappe.enqueue("erpnext.controllers.item_variant.create_multiple_variants", item=item, args=args, now=frappe.flags.in_test)
def rename_doc(doctype, old, new, force=False, merge=False, ignore_permissions=False, ignore_if_exists=False): """ Renames a doc(dt, old) to doc(dt, new) and updates all linked fields of type "Link" """ if not frappe.db.exists(doctype, old): return if ignore_if_exists and frappe.db.exists(doctype, new): return if old == new: frappe.msgprint(_('Please select a new name to rename')) return force = cint(force) merge = cint(merge) meta = frappe.get_meta(doctype) # call before_rename old_doc = frappe.get_doc(doctype, old) out = old_doc.run_method("before_rename", old, new, merge) or {} new = (out.get("new") or new) if isinstance(out, dict) else (out or new) if doctype != "DocType": new = validate_rename(doctype, new, meta, merge, force, ignore_permissions) if not merge: rename_parent_and_child(doctype, old, new, meta) # update link fields' values link_fields = get_link_fields(doctype) update_link_field_values(link_fields, old, new, doctype) rename_dynamic_links(doctype, old, new) # save the user settings in the db update_user_settings(old, new, link_fields) if doctype == 'DocType': rename_doctype(doctype, old, new, force) update_attachments(doctype, old, new) rename_versions(doctype, old, new) # call after_rename new_doc = frappe.get_doc(doctype, new) # copy any flags if required new_doc._local = getattr(old_doc, "_local", None) new_doc.run_method("after_rename", old, new, merge) if not merge: rename_password(doctype, old, new) # update user_permissions frappe.db.sql( """UPDATE `tabDefaultValue` SET `defvalue`=%s WHERE `parenttype`='User Permission' AND `defkey`=%s AND `defvalue`=%s""", (new, doctype, old)) if merge: new_doc.add_comment( 'Edit', _("merged {0} into {1}").format(frappe.bold(old), frappe.bold(new))) else: new_doc.add_comment( 'Edit', _("renamed from {0} to {1}").format(frappe.bold(old), frappe.bold(new))) if merge: frappe.delete_doc(doctype, old) frappe.clear_cache() frappe.enqueue('frappe.utils.global_search.rebuild_for_doctype', doctype=doctype) return new
def sync_all_items(): # sync erpnext items to WooCommerce product for d in frappe.db.get_all("Item"): #on_update_item(frappe.get_doc("Item", d)) frappe.enqueue(on_update_item, doc=frappe.get_doc("Item", d)) print("updated %s" % d)
def create_note_from_meeting_notice_board(doc, handler=None): # create Hse Meeting notice board print("CREATING NOTE") print(doc.minutes) newdoc = frappe.new_doc("Note") newdoc.title = doc.name newdoc.public = True newdoc.notify_on_login = True newdoc.notify_on_every_login = True newdoc.expire_notification_on = doc.meeting_date newdoc.content = "Date: <b>{0}</b><br>Time: <b>{1}</b>\ <br>Venue: <b>{2}</b><br>Link : <b><a style='color:red;' \ href='http://41.73.226.7/desk#Form/HSE%20Meeting%20Notice%20Board/{3}'> Click here to visit </a></b>\ ".format( datetime.strptime(str(doc.meeting_date), '%Y-%m-%d').strftime('%d-%m-%Y'), datetime.strptime(str(doc.meeting_time), '%H:%M:%S').strftime('%I:%M%p').lower(), doc.meeting_venue, doc.name) newdoc.insert() # get users email and send mail link = "<p>Attached is the minutes of the last HSE meeting.</p><br>Attachment : <b><a style='color:red;' href='http://41.73.226.7" + doc.minutes + "'> Click here to download </a></b><p></p>" if doc.minutes else "<hr>" emails = [ i[0] for i in frappe.db.sql( "SELECT email FROM tabUser WHERE email LIKE '%@%';", as_list=True) ] email_args = { "recipients": [], "message": "", "subject": '', "reference_doctype": doc.doctype, "reference_name": doc.name } email_args["recipients"] = emails # try: # email_args['attachments'] = [] #doc.attachments # except Exception as e: # pass email_args["message"] = "<h3>Notice of HSE Meeting</h3>\ \ <p>Dear All,</p>\ \ <p>This is to inform you that the HSE Meeting for {0} {1} will hold as follows:</p>\ \ <p><b>Date</b>: {2}</p>\ <p><b>Time</b>: {3}</p>\ <p><b>Venue</b>: {4} </p>\ \ <h5>Note:</h5>\ <p>In line with the Federal Ministry of Health and NCDC Guidelines, our meetings will hold in two segments:</p>\ \ <p>Engineers, Lab and Warehouse personnel: 1.30pm - 2.30pm</p>\ <p>Finance/Accounts, ICT and other support personnel - 2.30pm - 3.30pm</p>\ {5}\ \ <p>To access or view the full document details, kindly use the URL link below.</p>\ <br>Link : <b><a style='color:red;' href='http://41.73.226.7/desk#Form/HSE%20Meeting%20Notice%20Board/{6}'> Click here to visit </a></b>\ <p>Best Regards,</p>\ \ <p>Chinenye Chukwuemeka</p\ <p><b>QA/HSE Officer</b></p>".format( doc.month, doc.year, datetime.strptime(str(doc.meeting_date), '%Y-%m-%d').strftime('%d-%m-%Y'), datetime.strptime(str(doc.meeting_time), '%H:%M:%S').strftime('%I:%M%p').lower(), doc.meeting_venue, link, doc.name) email_args['subject'] = "HSE Meeting Notification" frappe.enqueue(method=frappe.sendmail, queue='short', timeout=300, **email_args) # redirect # frappe.local.flags.redirect_location = '/desk#Form/HSE%20Meeting%20Notice%20Board/{0}'.format(doc.name) # raise frappe.Redirect print("dONE CREATING NOTE")
def enqueue_update_cost(): frappe.enqueue("erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.update_cost") frappe.msgprint(_("Queued for updating latest price in all Bill of Materials. It may take a few minutes."))
def makeeq(): content = {'x': 'Hello', 'y': 'hi'} frappe.enqueue(method=makelog, queue='short', timeout=300, **content)
def after_insert(self): if frappe.flags.in_test: make_dimension_in_accounting_doctypes(doc=self) else: frappe.enqueue(make_dimension_in_accounting_doctypes, doc=self)
def on_trash(self): if frappe.flags.in_test: delete_accounting_dimension(doc=self) else: frappe.enqueue(delete_accounting_dimension, doc=self, queue="long")
def queueInitializeStock(company): frappe.enqueue( 'returnable.returnable.doctype.returnable.initialize_stock.process', company=company, is_async=True, timeout=240000) return "Enqueued"
def enqueue_build_cache(item_code): if frappe.cache().hget('item_cache_build_in_progress', item_code): return frappe.enqueue(build_cache, item_code=item_code, queue='long')
def post_serial(serialno, supplier, max_retry=1, sleep=None): if sleep: time.sleep(sleep) max_retry = max_retry - 1 send_data = {"sn_list": [serialno]} cloud_server = ThingsCloudSettings.get_thingscloud_server() authorization_code = ThingsCloudSettings.get_authorization_code() if not supplier: frappe.logger(__name__).error(serialno + " doesn't have a supplier, So couldn't send to ThingsCloud") return if not cloud_server: frappe.logger(__name__).error("ThingsCloud url Configuration missing in ThingsCloud Settings") return if not authorization_code: frappe.logger(__name__).error("Authorization Code Configuration missing in ThingsCloud Settings") return try: # r = requests.session().get(cloud_server + "/query", params={"q": ''}, timeout=1) headers = {'HDB-AuthorizationCode': authorization_code, 'Content-Type': 'application/json', 'Accept': 'application/json'} r = requests.session().post(cloud_server + "/api/method/iot.hdb_api.batch_add_device", headers=headers, json=send_data, timeout=3) # print(json.dumps(r.json(), sort_keys=True, indent=4, separators=(',', ':'))) if r.status_code != 200: print(json.dumps(r.json, sort_keys=True, indent=4, separators=(',', ':'))) frappe.logger(__name__).error(r.text) if max_retry > 0: frappe.enqueue('erp2thingscloud.controllers.item_serial_event_hooks.post_serial', serialno=serialno, supplier=supplier, max_retry=max_retry, sleep=60) else: sn_exists = frappe.db.get_value("Serial Number list", {"serial_no": serialno}, "serial_no") if not sn_exists: serialno_doc = frappe.get_doc( {"doctype": "Serial Number list", "serial_no": serialno, "sync_status": 'failed'}) serialno_doc.insert(ignore_permissions=True) else: serialno_doc = frappe.get_doc("Serial Number list", serialno) serialno_doc.set("sync_status", 'failed') serialno_doc.save() else: frappe.logger(__name__).debug(r.text) # print("----------------------2-------------------------") # print("@@@set serialno successful :::", serialno) # print("-----------------------------------------------") sn_exists = frappe.db.get_value("Serial Number list", {"serial_no": serialno}, "serial_no") if not sn_exists: serialno_doc = frappe.get_doc( {"doctype": "Serial Number list", "serial_no": serialno, "sync_status": 'successful'}) serialno_doc.insert(ignore_permissions=True) else: serialno_doc = frappe.get_doc("Serial Number list", serialno) serialno_doc.set("sync_status", 'successful') serialno_doc.save() except Exception as ex: # print("-----------------------3------------------------") # print("@@@set serialno failed :::", serialno) # print("-----------------------------------------------") sn_exists = frappe.db.get_value("Serial Number list", {"serial_no": serialno}, "serial_no") if not sn_exists: serialno_doc = frappe.get_doc( {"doctype": "Serial Number list", "serial_no": serialno, "sync_status": 'failed'}) serialno_doc.insert(ignore_permissions=True) else: serialno_doc = frappe.get_doc("Serial Number list", serialno) serialno_doc.set("sync_status", 'failed') serialno_doc.save() frappe.logger(__name__).error(ex) if max_retry > 0: frappe.enqueue('erp2thingscloud.controllers.item_serial_event_hooks.post_serial', serialno=serialno, supplier=supplier, max_retry=max_retry, sleep=60)
def after_delete(doc, method): # print("@@@serial_no delete:::", doc.serial_no, doc.item_code, doc.batch_no, doc.item_name, doc.supplier, doc.item_code) frappe.enqueue('erp2thingscloud.controllers.item_serial_event_hooks.delete_serial', serialno=doc.serial_no, supplier=doc.supplier)
def run_command(commands, doctype, key, cwd='..', docname=' ', after_command=None): verify_whitelisted_call() start_time = frappe.utils.time.time() console_dump = "" logged_command = " && ".join(commands) logged_command += " " #to make sure passwords at the end of the commands are also hidden sensitive_data = [ "--mariadb-root-password", "--admin-password", "--root-password" ] for password in sensitive_data: logged_command = re.sub("{password} .*? ".format(password=password), '', logged_command, flags=re.DOTALL) doc = frappe.get_doc({ 'doctype': 'Bench Manager Command', 'key': key, 'source': doctype + ': ' + docname, 'command': logged_command, 'console': console_dump, 'status': 'Ongoing' }) doc.insert() frappe.db.commit() frappe.publish_realtime(key, "Executing Command:\n{logged_command}\n\n".format( logged_command=logged_command), user=frappe.session.user) status = 'Failed' buffer = [] try: for command in commands: terminal = Popen(shlex.split(command), stdin=PIPE, stdout=PIPE, stderr=STDOUT, cwd=cwd, universal_newlines=True) for c in iter(lambda: safe_decode(terminal.stdout.read(1)), ''): buffer.append(c) if '\n' == c: frappe.publish_realtime(key, ''.join(buffer), user=frappe.session.user) buffer = [] console_dump += c # Write out pending if any (there may be no newline?) if len(buffer): frappe.publish_realtime(key, ''.join(buffer), user=frappe.session.user) buffer = [] if not terminal.wait(): status = 'Success' except Exception as e: console_dump = "{} \n\n{}".format(e, console_dump) finally: _close_the_doc(start_time, key, console_dump, status=status, user=frappe.session.user) frappe.enqueue('bench_manager.bench_manager.utils._refresh', doctype=doctype, docname=docname, commands=commands)
def disable_dimension(doc): if frappe.flags.in_test: toggle_disabling(doc=doc) else: frappe.enqueue(toggle_disabling, doc=doc)
def setup_company_independent_fixtures(): make_custom_fields() add_permissions() add_custom_roles_for_reports() frappe.enqueue('erpnext.regional.india.setup.add_hsn_sac_codes', now=frappe.flags.in_test) add_print_formats()
def create_site_internal(email, full_name, plan): einvoice_plan = ['EInvoice', 'الفاتورة الالكترونية'] verify_whitelisted_call() settings = frappe.get_single('SAAS Settings') install_erpnext = "true" mysql_password = settings.mysql_password admin_password = settings.admin_password email = email customers = frappe.get_list("Customer", {"customer_email": email}, ignore_permissions=True) if customers: customer = frappe.get_doc("Customer", {"customer_email": email}) site_name = customer.site_name + "." + settings.main_domain letters = string.ascii_lowercase key = ''.join(random.choice(letters) for i in range(10)) commands = [ "bench new-site --mariadb-root-password {mysql_password} --admin-password {admin_password} {site_name}" .format(site_name=site_name, admin_password=admin_password, mysql_password=mysql_password) ] site_request = None sr = frappe.get_list("Site Request", {"email": email}, ignore_permissions=True) if sr: site_request = email if not site_exist(site_name): if install_erpnext == "true": with open('apps.txt', 'r') as f: app_list = f.read() if 'erpnext' not in app_list: commands.append("bench get-app erpnext") if plan not in einvoice_plan: commands.append( "bench --site {site_name} install-app erpnext".format( site_name=site_name)) if plan in einvoice_plan: commands.append( "bench --site {site_name} install-app einvoice".format( site_name=site_name)) if 'lite' in app_list and plan not in einvoice_plan: commands.append( "bench --site {site_name} install-app lite".format( site_name=site_name)) if 'mawred_theme' in app_list: commands.append( "bench --site {site_name} install-app mawred_theme". format(site_name=site_name)) a = "bench --site pas.com.sa execute bench_manager.api.add_data_to_site --kwargs \"{'site':'" + site_name + "','full_name': '" + full_name + "','company_name': '" + customer.company_name + "','email': '" + email + "'}\"" commands.append(a) if 'loginapp' in app_list: commands.append( "bench --site {site_name} install-app loginapp".format( site_name=site_name)) domain = settings.main_domain alias = settings.alias_domain alias_site_name = customer.site_name + "." + alias commands.append( "bench setup add-domain {site_name} --site {site_name} --ssl-certificate /etc/letsencrypt/live/{domain}/fullchain.pem --ssl-certificate-key /etc/letsencrypt/live/{domain}/privkey.pem " .format(site_name=site_name, domain=domain)) if alias: commands.append( "bench setup add-domain {alias_site_name} --site {site_name} --ssl-certificate /etc/letsencrypt/live/{alias_domain}/fullchain.pem --ssl-certificate-key /etc/letsencrypt/live/{alias_domain}/privkey.pem " .format(site_name=site_name, alias_domain=alias, alias_site_name=alias_site_name)) commands.append("bench setup nginx --yes") commands.append("sudo service nginx restart") # if plan in einvoice_plan: # commands.append("bench --site {site_name} uninstall-app erpnext".format(site_name=site_name)) # commands.append("bench --site {site_name} uninstall-app lite".format(site_name=site_name)) # commands.append("bench --site {site_name} install-app einvoice".format(site_name=site_name)) frappe.enqueue('bench_manager.bench_manager.utils.run_command', commands=commands, doctype="Site Request", docname=email, site_request=site_request, key=key, timeout=1200)
def enqueue_replace_abbr(company, old, new): kwargs = dict(company=company, old=old, new=new) frappe.enqueue('erpnext.setup.doctype.company.company.replace_abbr', **kwargs)
def enqueue_replace_bom(args): if isinstance(args, string_types): args = json.loads(args) frappe.enqueue("erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.replace_bom", args=args, timeout=4000) frappe.msgprint(_("Queued for replacing the BOM. It may take a few minutes."))
def delete_doc(doctype=None, name=None, force=0, ignore_doctypes=None, for_reload=False, ignore_permissions=False, flags=None, ignore_on_trash=False, ignore_missing=True): """ Deletes a doc(dt, dn) and validates if it is not submitted and not linked in a live record """ if not ignore_doctypes: ignore_doctypes = [] # get from form if not doctype: doctype = frappe.form_dict.get('dt') name = frappe.form_dict.get('dn') names = name if isinstance(name, string_types): names = [name] for name in names or []: # already deleted..? if not frappe.db.exists(doctype, name): if not ignore_missing: raise frappe.DoesNotExistError else: return False # delete passwords delete_all_passwords_for(doctype, name) doc = None if doctype=="DocType": if for_reload: try: doc = frappe.get_doc(doctype, name) except frappe.DoesNotExistError: pass else: doc.run_method("before_reload") else: doc = frappe.get_doc(doctype, name) update_flags(doc, flags, ignore_permissions) check_permission_and_not_submitted(doc) frappe.db.sql("delete from `tabCustom Field` where dt = %s", name) frappe.db.sql("delete from `tabCustom Script` where dt = %s", name) frappe.db.sql("delete from `tabProperty Setter` where doc_type = %s", name) frappe.db.sql("delete from `tabReport` where ref_doctype=%s", name) frappe.db.sql("delete from `tabCustom DocPerm` where parent=%s", name) delete_from_table(doctype, name, ignore_doctypes, None) else: doc = frappe.get_doc(doctype, name) if not for_reload: update_flags(doc, flags, ignore_permissions) check_permission_and_not_submitted(doc) if not ignore_on_trash: doc.run_method("on_trash") doc.flags.in_delete = True doc.run_method('on_change') frappe.enqueue('frappe.model.delete_doc.delete_dynamic_links', doctype=doc.doctype, name=doc.name, async=False if frappe.flags.in_test else True) # check if links exist if not force: check_if_doc_is_linked(doc) check_if_doc_is_dynamically_linked(doc) update_naming_series(doc) delete_from_table(doctype, name, ignore_doctypes, doc) doc.run_method("after_delete") # delete attachments remove_all(doctype, name, from_delete=True) # delete global search entry delete_for_document(doc) if doc and not for_reload: add_to_deleted_document(doc) if not frappe.flags.in_patch: try: doc.notify_update() insert_feed(doc) except ImportError: pass # delete user_permissions frappe.defaults.clear_default(parenttype="User Permission", key=doctype, value=name)
def new_event_notification(producer_url): """Pull data from producer when notified""" enqueued_method = 'frappe.event_streaming.doctype.event_producer.event_producer.pull_from_node' jobs = get_jobs() if not jobs or enqueued_method not in jobs[frappe.local.site]: frappe.enqueue(enqueued_method, queue='default', **{'event_producer': producer_url})
def send_leave_application_email(doc, handler=None): # send email based on workflow status email_args = { "recipients": [], "message": "", "subject": '', "reference_doctype": doc.doctype, "reference_name": doc.name } if doc.workflow_state == "Pending HOD Approval": email_args["recipients"] = [doc.leave_approver] email_args[ "message"] = "<b>Leave Application</b><br>Employee: {0}<br>Approve/Reject: <a href='http://41.73.226.7/desk#Form/Leave%20Application/{1}'>http://41.73.226.7/desk#Form/Leave%20Application/{1}</a>".format( doc.employee_name, doc.name) email_args['subject'] = "Leave Application for {0}".format( doc.employee_name) frappe.enqueue(method=frappe.sendmail, queue='short', timeout=300, **email_args) elif doc.workflow_state == "Pending HR Approval" and doc.status == "Open": company = frappe.get_doc( 'Company', frappe.get_doc('Leave Application', doc.name).company) #company_abbr = f"{company.name} - {company.abbr}" hrm = frappe.get_doc( "Department", "Administration/Human Resources/Corporate Services - {0}".format( company.abbr)).leave_approvers[0].approver email_args["recipients"] = [hrm] email_args[ "message"] = "<b>Leave Application</b><br>Employee: {0}<br>Approve/Reject: <a href='http://41.73.226.7/desk#Form/Leave%20Application/{1}'>http://41.73.226.7/desk#Form/Leave%20Application/{1}</a>".format( doc.employee_name, doc.name) email_args['subject'] = "Leave Application for {0}: HR Action".format( doc.employee_name) frappe.enqueue(method=frappe.sendmail, queue='short', timeout=300, **email_args) elif doc.workflow_state == "HOD Rejected" or doc.workflow_state == "HR Rejected": email_args["recipients"] = [ frappe.get_doc("Employee", doc.employee).user_id ] email_args[ "message"] = "<b>Leave Application rejected</b><br>Link: <a href='http://41.73.226.7/desk#Form/Leave%20Application/{0}'>http://41.73.226.7/desk#Form/Leave%20Application/{0}</a>".format( doc.name) email_args['subject'] = "Leave Application Rejected" frappe.enqueue(method=frappe.sendmail, queue='short', timeout=300, **email_args) elif doc.workflow_state == "Approved by HR": email_args["recipients"] = [ frappe.get_doc("Employee", doc.employee).user_id ] email_args[ "message"] = "<b>Leave Application Approved</b><br>Link: <a href='http://41.73.226.7/desk#Form/Leave%20Application/{0}'>http://41.73.226.7/desk#Form/Leave%20Application/{0}</a>".format( doc.name) email_args['subject'] = "Leave Application Approved" frappe.enqueue(method=frappe.sendmail, queue='short', timeout=300, **email_args)
def delete_doc(doctype=None, name=None, force=0, ignore_doctypes=None, for_reload=False, ignore_permissions=False, flags=None, ignore_on_trash=False, ignore_missing=True): """ Deletes a doc(dt, dn) and validates if it is not submitted and not linked in a live record """ if not ignore_doctypes: ignore_doctypes = [] # get from form if not doctype: doctype = frappe.form_dict.get('dt') name = frappe.form_dict.get('dn') names = name if isinstance(name, string_types): names = [name] for name in names or []: # already deleted..? if not frappe.db.exists(doctype, name): if not ignore_missing: raise frappe.DoesNotExistError else: return False # delete passwords delete_all_passwords_for(doctype, name) doc = None if doctype == "DocType": if for_reload: try: doc = frappe.get_doc(doctype, name) except frappe.DoesNotExistError: pass else: doc.run_method("before_reload") else: doc = frappe.get_doc(doctype, name) update_flags(doc, flags, ignore_permissions) check_permission_and_not_submitted(doc) frappe.db.sql("delete from `tabCustom Field` where dt = %s", name) frappe.db.sql("delete from `tabCustom Script` where dt = %s", name) frappe.db.sql( "delete from `tabProperty Setter` where doc_type = %s", name) frappe.db.sql("delete from `tabReport` where ref_doctype=%s", name) frappe.db.sql( "delete from `tabCustom DocPerm` where parent=%s", name) delete_from_table(doctype, name, ignore_doctypes, None) else: doc = frappe.get_doc(doctype, name) if not for_reload: update_flags(doc, flags, ignore_permissions) check_permission_and_not_submitted(doc) if not ignore_on_trash: doc.run_method("on_trash") doc.flags.in_delete = True doc.run_method('on_change') frappe.enqueue('frappe.model.delete_doc.delete_dynamic_links', doctype=doc.doctype, name=doc.name, async=False if frappe.flags.in_test else True) # check if links exist if not force: check_if_doc_is_linked(doc) check_if_doc_is_dynamically_linked(doc) update_naming_series(doc) delete_from_table(doctype, name, ignore_doctypes, doc) doc.run_method("after_delete") # delete attachments remove_all(doctype, name, from_delete=True) # delete global search entry delete_for_document(doc) if doc and not for_reload: add_to_deleted_document(doc) if not frappe.flags.in_patch: try: doc.notify_update() insert_feed(doc) except ImportError: pass # delete user_permissions frappe.defaults.clear_default(parenttype="User Permission", key=doctype, value=name)
def run_command(commands, doctype, key, cwd="..", docname=" ", after_command=None): verify_whitelisted_call() start_time = frappe.utils.time.time() console_dump = "" logged_command = " && ".join(commands) logged_command += ( " " # to make sure passwords at the end of the commands are also hidden ) sensitive_data = [ "--mariadb-root-password", "--admin-password", "--root-password" ] for password in sensitive_data: logged_command = re.sub("{password} .*? ".format(password=password), "", logged_command, flags=re.DOTALL) doc = frappe.get_doc({ "doctype": "Bench Manager Command", "key": key, "source": doctype + ": " + docname, "command": logged_command, "console": console_dump, "status": "Ongoing", }) doc.insert() frappe.db.commit() frappe.publish_realtime( key, "Executing Command:\n{logged_command}\n\n".format( logged_command=logged_command), user=frappe.session.user, ) try: for command in commands: terminal = Popen(shlex.split(command), stdin=PIPE, stdout=PIPE, stderr=STDOUT, cwd=cwd) for c in iter(lambda: safe_decode(terminal.stdout.read(1)), ""): frappe.publish_realtime(key, c, user=frappe.session.user) console_dump += c if terminal.wait(): _close_the_doc(start_time, key, console_dump, status="Failed", user=frappe.session.user) else: _close_the_doc(start_time, key, console_dump, status="Success", user=frappe.session.user) except Exception as e: _close_the_doc( start_time, key, "{} \n\n{}".format(e, console_dump), status="Failed", user=frappe.session.user, ) finally: frappe.db.commit() # hack: frappe.db.commit() to make sure the log created is robust, # and the _refresh throws an error if the doc is deleted frappe.enqueue( "bench_manager.bench_manager.utils._refresh", doctype=doctype, docname=docname, commands=commands, )
def update_current_month_sales(self): if frappe.flags.in_test: update_company_current_month_sales(self.company) else: frappe.enqueue('erpnext.setup.doctype.company.company.update_company_current_month_sales', company=self.company)
def create_note_from_meeting_notice_board(doc, handler=None): # create Hse Meeting notice board print("CREATING NOTE") print(doc.minutes) newdoc = frappe.new_doc("Note") newdoc.title = doc.name newdoc.public = True newdoc.notify_on_login = True newdoc.notify_on_every_login = True newdoc.expire_notification_on = doc.meeting_date newdoc.content = "Date: <b>{0}</b><br>Time: <b>{1}</b>\ <br>Venue: <b>{2}</b><br>Link : <b><a style='color:red;' \ href='{4}/desk#Form/HSE%20Meeting%20Notice%20Board/{3}'> Click here to visit </a></b>\ ".format( datetime.strptime(str(doc.meeting_date), '%Y-%m-%d').strftime('%d-%m-%Y'), datetime.strptime(str(doc.meeting_time), '%H:%M:%S').strftime('%I:%M%p').lower(), doc.meeting_venue, doc.name, get_ip()) newdoc.insert() # get users email and send mail # link = "<p>Attached is the minutes of the last HSE meeting.</p><br>Attachment : <b><a style='color:red;' href='http://41.73.226.7"+doc.minutes+"'> Click here to download </a></b><p></p>" if doc.minutes else "<hr>" download = "<a style='color:red;' href='" + get_ip( ) + doc.minutes + "'> download </a></b><p></p>" if doc.minutes else "<hr>" link = "<a style='color:red;' href='" + get_ip( ) + "/desk#Form/HSE%20Meeting%20Notice%20Board/" + doc.name + "'> visit </a>" emails = [ i[0] for i in frappe.db.sql( "SELECT email FROM tabUser WHERE email LIKE '%@%';", as_list=True) ] email_args = { "recipients": [], "message": "", "subject": '', "reference_doctype": doc.doctype, "reference_name": doc.name } email_args["recipients"] = emails # try: # email_args['attachments'] = [] #doc.attachments # except Exception as e: # pass meeting_msg = frappe.get_doc("Meeting Notice Setup").meeting_message email_args["message"] = meeting_msg.format( month=doc.month, year=doc.year, date=datetime.strptime(str(doc.meeting_date), '%Y-%m-%d').strftime('%d-%m-%Y'), time=datetime.strptime(str(doc.meeting_time), '%H:%M:%S').strftime('%I:%M%p').lower(), meeting_venue=doc.meeting_venue, download=download, docname=doc.name, here=link) email_args['subject'] = "HSE Meeting Notification" frappe.enqueue(method=frappe.sendmail, queue='short', timeout=300, **email_args) # redirect # frappe.local.flags.redirect_location = '/desk#Form/HSE%20Meeting%20Notice%20Board/{0}'.format(doc.name) # raise frappe.Redirect print("dONE CREATING NOTE")
def on_validate_item(doc,method=None): frappe.enqueue(on_update_item, doc=frappe.get_doc("Item", doc.name))
def enqueue_replace_bom(args): if isinstance(args, string_types): args = json.loads(args) frappe.enqueue("erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool.replace_bom", args=args) frappe.msgprint(_("Queued for replacing the BOM. It may take a few minutes."))
def on_trash(self): frappe.enqueue( 'app_center.app_center.doctype.iot_application.iot_application.update_stars', app=self.app)
def enqueue_multiple_variant_creation(item, args): # There can be innumerable attribute combinations, enqueue frappe.enqueue("erpnext.controllers.item_variant.create_multiple_variants", item=item, args=args, now=frappe.flags.in_test);
def rename_doc(doctype, old, new, force=False, merge=False, ignore_permissions=False, ignore_if_exists=False): """ Renames a doc(dt, old) to doc(dt, new) and updates all linked fields of type "Link" """ if not frappe.db.exists(doctype, old): return if ignore_if_exists and frappe.db.exists(doctype, new): return if old==new: frappe.msgprint(_('Please select a new name to rename')) return force = cint(force) merge = cint(merge) meta = frappe.get_meta(doctype) # call before_rename old_doc = frappe.get_doc(doctype, old) out = old_doc.run_method("before_rename", old, new, merge) or {} new = (out.get("new") or new) if isinstance(out, dict) else (out or new) if doctype != "DocType": new = validate_rename(doctype, new, meta, merge, force, ignore_permissions) if not merge: rename_parent_and_child(doctype, old, new, meta) # update link fields' values link_fields = get_link_fields(doctype) update_link_field_values(link_fields, old, new, doctype) rename_dynamic_links(doctype, old, new) # save the user settings in the db update_user_settings(old, new, link_fields) if doctype=='DocType': rename_doctype(doctype, old, new, force) update_attachments(doctype, old, new) rename_versions(doctype, old, new) # call after_rename new_doc = frappe.get_doc(doctype, new) # copy any flags if required new_doc._local = getattr(old_doc, "_local", None) new_doc.run_method("after_rename", old, new, merge) if not merge: rename_password(doctype, old, new) # update user_permissions frappe.db.sql("""update tabDefaultValue set defvalue=%s where parenttype='User Permission' and defkey=%s and defvalue=%s""", (new, doctype, old)) if merge: new_doc.add_comment('Edit', _("merged {0} into {1}").format(frappe.bold(old), frappe.bold(new))) else: new_doc.add_comment('Edit', _("renamed from {0} to {1}").format(frappe.bold(old), frappe.bold(new))) if merge: frappe.delete_doc(doctype, old) frappe.clear_cache() frappe.enqueue('frappe.utils.global_search.rebuild_for_doctype', doctype=doctype) return new
def wechat_notify(): for doc in frappe.get_all("Wechat Send Doc", "name", filters={"status": ["in", ["New", "Partial"]], "docstatus": 1}): frappe.enqueue('wechat.wechat.doctype.wechat_send_doc.wechat_send_doc.wechat_send', doc_name=doc.name)
def on_submit(self): frappe.enqueue('wechat.wechat.doctype.wechat_send_doc.wechat_send_doc.wechat_send', doc_name=self.name, doc_doc=self)
def on_update(self): if self.license_need_update == 1: frappe.enqueue( 'make.license.doctype.device_license.device_license.gen_license_data', doc_name=self.name, doc_doc=self)
def create_site(site_name, install_erpnext, mysql_password, admin_password, key, email=None, doc=None): verify_whitelisted_call() commands = [ "bench new-site --mariadb-root-password {mysql_password} --admin-password {admin_password} {site_name}" .format(site_name=site_name, admin_password=admin_password, mysql_password=mysql_password) ] if install_erpnext == "true": with open('apps.txt', 'r') as f: app_list = f.read() if 'erpnext' not in app_list: commands.append("bench get-app erpnext") commands.append("bench --site {site_name} install-app erpnext".format( site_name=site_name)) if 'lite' in app_list: commands.append("bench --site {site_name} install-app lite".format( site_name=site_name)) if 'mawred_theme' in app_list: commands.append( "bench --site {site_name} install-app mawred_theme".format( site_name=site_name)) sits_list = frappe.get_list("Site Request", {"email": email}) if sits_list: doc = frappe.get_doc("Site Request", {"email": email}) a = "bench --site pas.com.sa execute bench_manager.api.add_data_to_site --kwargs \"{'site':'" + site_name + "','full_name': '" + doc.full_name + "','company_name': '" + doc.association_name + "','email': '" + doc.email + "'}\"" commands.append(a) if 'loginapp' in app_list: commands.append( "bench --site {site_name} install-app loginapp".format( site_name=site_name)) settings = frappe.get_single('SAAS Settings') domain = settings.main_domain alias = settings.alias_domain alias_site_name = doc.subdomain + "." + alias commands.append( "bench setup add-domain {site_name} --site {site_name} --ssl-certificate /etc/letsencrypt/live/{domain}/fullchain.pem --ssl-certificate-key /etc/letsencrypt/live/{domain}/privkey.pem " .format(site_name=site_name, domain=domain)) if alias: commands.append( "bench setup add-domain {alias_site_name} --site {site_name} --ssl-certificate /etc/letsencrypt/live/{alias_domain}/fullchain.pem --ssl-certificate-key /etc/letsencrypt/live/{alias_domain}/privkey.pem " .format(site_name=site_name, alias_domain=alias, alias_site_name=alias_site_name)) commands.append("bench setup nginx --yes") commands.append("sudo service nginx restart") frappe.enqueue('bench_manager.bench_manager.utils.run_command', commands=commands, doctype="Bench Settings", key=key, timeout=1200) all_sites = safe_decode(check_output("ls")).strip('\n').split('\n') while site_name not in all_sites: time.sleep(2) print("waiting for site creation...") all_sites = safe_decode(check_output("ls")).strip('\n').split('\n') doc = frappe.get_doc({ 'doctype': 'Site', 'site_name': site_name, 'app_list': 'frappe', 'developer_flag': 1 }) doc.insert() frappe.db.commit() if email: sits_list = frappe.get_list("Site Request", {"email": email}) if sits_list: site = frappe.get_doc("Site Request", {"email": email}) email_args = { "recipients": site.email, "sender": None, "subject": "Your New site created " + site_name, "message": "site :" + site_name + "<br>" + "user :"******"administrator" + "<br>" + "passwored :" + admin_password, "now": True, } enqueue(method=frappe.sendmail, queue='short', timeout=300, is_async=True, **email_args)