示例#1
0
	def send(self):
		# send email only to enabled users
		valid_users = [p[0] for p in frappe.db.sql("""select name from `tabUser`
			where enabled=1""")]
		recipients = list(filter(lambda r: r in valid_users,
			self.recipient_list.split("\n")))

		original_user = frappe.session.user

		if recipients:
			for user_id in recipients:
				frappe.set_user(user_id)
				frappe.set_user_lang(user_id)
				msg_for_this_recipient = self.get_msg_html()
				if msg_for_this_recipient:
					frappe.sendmail(
						recipients=user_id,
						subject=_("{0} Digest").format(self.frequency),
						message=msg_for_this_recipient,
						reference_doctype = self.doctype,
						reference_name = self.name,
						unsubscribe_message = _("Unsubscribe from this Email Digest"))

		frappe.set_user(original_user)
		frappe.set_user_lang(original_user)
示例#2
0
def send_event_digest():
    today = nowdate()
    for user in frappe.db.sql("""select name, email, language
		from tabUser where ifnull(enabled,0)=1
		and user_type='System User' and name not in ({})""".format(", ".join(
        ["%s"] * len(STANDARD_USERS))),
                              STANDARD_USERS,
                              as_dict=1):

        events = get_events(today, today, user.name, for_reminder=True)
        if events:
            text = ""
            frappe.set_user_lang(user.name, user.language)

            text = "<h3>" + frappe._("Events In Today's Calendar") + "</h3>"
            for e in events:
                if e.all_day:
                    e.starts_on = "All Day"
                text += "<h4>%(starts_on)s: %(subject)s</h4><p>%(description)s</p>" % e

            text += '<p style="color: #888; font-size: 80%; margin-top: 20px; padding-top: 10px; border-top: 1px solid #eee;">'\
             + frappe._("Daily Event Digest is sent for Calendar Events where reminders are set.")+'</p>'

            from frappe.utils.email_lib import sendmail
            sendmail(recipients=user.email,
                     subject=frappe._("Upcoming Events for Today"),
                     msg=text)
示例#3
0
文件: boot.py 项目: hatwar/frappe
def get_bootinfo():
	"""build and return boot info"""
	frappe.set_user_lang(frappe.session.user)
	bootinfo = frappe._dict()
	hooks = frappe.get_hooks()
	doclist = []

	# user
	get_user(bootinfo)

	# system info
	bootinfo['sysdefaults'] = frappe.defaults.get_defaults()
	bootinfo['server_date'] = frappe.utils.nowdate()

	if frappe.session['user'] != 'Guest':
		bootinfo['user_info'] = get_fullnames()
		bootinfo['sid'] = frappe.session['sid'];

	# home page
	bootinfo.modules = {}
	for app in frappe.get_installed_apps():
		try:
			bootinfo.modules.update(frappe.get_attr(app + ".config.desktop.get_data")() or {})
		except ImportError:
			pass
		except AttributeError:
			pass

	bootinfo.module_app = frappe.local.module_app
	bootinfo.hidden_modules = frappe.db.get_global("hidden_modules")
	bootinfo.doctype_icons = dict(frappe.db.sql("""select name, icon from
		tabDocType where ifnull(icon,'')!=''"""))
	bootinfo.single_types = frappe.db.sql_list("""select name from tabDocType where ifnull(issingle,0)=1""")
	add_home_page(bootinfo, doclist)
	bootinfo.page_info = get_allowed_pages()
	load_translations(bootinfo)
	add_timezone_info(bootinfo)
	load_conf_settings(bootinfo)
	load_print(bootinfo, doclist)
	doclist.extend(get_meta_bundle("Page"))
	bootinfo.home_folder = frappe.db.get_value("File", {"is_home_folder": 1})

	# ipinfo
	if frappe.session['data'].get('ipinfo'):
		bootinfo['ipinfo'] = frappe.session['data']['ipinfo']

	# add docs
	bootinfo['docs'] = doclist

	for method in hooks.boot_session or []:
		frappe.get_attr(method)(bootinfo)

	if bootinfo.lang:
		bootinfo.lang = unicode(bootinfo.lang)
	bootinfo['versions'] = {k: v['version'] for k, v in get_versions().items()}

	bootinfo.error_report_email = frappe.get_hooks("error_report_email")
	bootinfo.calendars = sorted(frappe.get_hooks("calendars"))

	return bootinfo
示例#4
0
def run():
	frappe.set_user("*****@*****.**")
	frappe.set_user_lang("fr")

	for i in range(random.randint(1,7)):
		if random.random() < 0.5:
			make_item_booking()
示例#5
0
def get_bootinfo():
    """build and return boot info"""
    frappe.set_user_lang(frappe.session.user)
    bootinfo = frappe._dict()
    hooks = frappe.get_hooks()
    doclist = []

    # user
    get_user(bootinfo)

    # system info
    bootinfo.sysdefaults = frappe.defaults.get_defaults()
    bootinfo.server_date = frappe.utils.nowdate()

    if frappe.session['user'] != 'Guest':
        bootinfo.user_info = get_fullnames()
        bootinfo.sid = frappe.session['sid']

    bootinfo.modules = {}
    bootinfo.module_list = []
    load_desktop_icons(bootinfo)
    bootinfo.letter_heads = get_letter_heads()
    bootinfo.active_domains = frappe.get_active_domains()
    bootinfo.all_domains = [d.get("name") for d in frappe.get_all("Domain")]

    bootinfo.module_app = frappe.local.module_app
    bootinfo.single_types = frappe.db.sql_list("""select name from tabDocType
		where issingle=1""")
    add_home_page(bootinfo, doclist)
    bootinfo.page_info = get_allowed_pages()
    load_translations(bootinfo)
    add_timezone_info(bootinfo)
    load_conf_settings(bootinfo)
    load_print(bootinfo, doclist)
    doclist.extend(get_meta_bundle("Page"))
    bootinfo.home_folder = frappe.db.get_value("File", {"is_home_folder": 1})

    # ipinfo
    if frappe.session.data.get('ipinfo'):
        bootinfo.ipinfo = frappe.session['data']['ipinfo']

    # add docs
    bootinfo.docs = doclist

    for method in hooks.boot_session or []:
        frappe.get_attr(method)(bootinfo)

    if bootinfo.lang:
        bootinfo.lang = unicode(bootinfo.lang)
    bootinfo.versions = {k: v['version'] for k, v in get_versions().items()}

    bootinfo.error_report_email = frappe.get_hooks("error_report_email")
    bootinfo.calendars = sorted(frappe.get_hooks("calendars"))
    bootinfo.treeviews = frappe.get_hooks("treeviews") or []
    bootinfo.lang_dict = get_lang_dict()
    bootinfo.feedback_triggers = get_enabled_feedback_trigger()
    bootinfo.gsuite_enabled = get_gsuite_status()
    bootinfo.update(get_email_accounts(user=frappe.session.user))

    return bootinfo
示例#6
0
    def send(self):
        # send email only to enabled users
        valid_users = [
            p[0] for p in frappe.db.sql("""select name from `tabUser`
			where enabled=1""")
        ]
        recipients = list(
            filter(lambda r: r in valid_users,
                   self.recipient_list.split("\n")))

        original_user = frappe.session.user

        if recipients:
            for user_id in recipients:
                frappe.set_user(user_id)
                frappe.set_user_lang(user_id)
                msg_for_this_recipient = self.get_msg_html()
                if msg_for_this_recipient:
                    frappe.sendmail(recipients=user_id,
                                    subject=_("{0} Digest").format(
                                        self.frequency),
                                    message=msg_for_this_recipient,
                                    reference_doctype=self.doctype,
                                    reference_name=self.name,
                                    unsubscribe_message=_(
                                        "Unsubscribe from this Email Digest"))

        frappe.set_user(original_user)
        frappe.set_user_lang(original_user)
示例#7
0
文件: projects.py 项目: ektai/erpnext
def run_projects(current_date):
    frappe.set_user(frappe.db.get_global('demo_projects_user'))
    frappe.set_user_lang(frappe.db.get_global('demo_projects_user'))
    if frappe.db.get_global('demo_projects_user'):
        make_project(current_date)
        make_timesheet_for_projects(current_date)
        close_tasks(current_date)
示例#8
0
def work():
	frappe.set_user(frappe.db.get_global('demo_hr_user'))
	frappe.set_user_lang(frappe.db.get_global('demo_hr_user'))
	year, month = frappe.flags.current_date.strftime("%Y-%m").split("-")
	setup_department_approvers()
	mark_attendance()
	make_leave_application()

	# payroll entry
	if not frappe.db.sql('select name from `tabSalary Slip` where month(adddate(start_date, interval 1 month))=month(curdate())'):
		# based on frequency
		payroll_entry = get_payroll_entry()
		payroll_entry.salary_slip_based_on_timesheet = 0
		payroll_entry.save()
		payroll_entry.create_salary_slips()
		payroll_entry.submit_salary_slips()
		payroll_entry.make_accrual_jv_entry()
		payroll_entry.submit()
		# payroll_entry.make_journal_entry(reference_date=frappe.flags.current_date,
		# 	reference_number=random_string(10))

		# based on timesheet
		payroll_entry = get_payroll_entry()
		payroll_entry.salary_slip_based_on_timesheet = 1
		payroll_entry.save()
		payroll_entry.create_salary_slips()
		payroll_entry.submit_salary_slips()
		payroll_entry.make_accrual_jv_entry()
		payroll_entry.submit()
		# payroll_entry.make_journal_entry(reference_date=frappe.flags.current_date,
		# 	reference_number=random_string(10))

	if frappe.db.get_global('demo_hr_user'):
		make_timesheet_records()

		#expense claim
		expense_claim = frappe.new_doc("Expense Claim")
		expense_claim.extend('expenses', get_expenses())
		expense_claim.employee = get_random("Employee")
		expense_claim.company = frappe.flags.company
		expense_claim.payable_account = get_payable_account(expense_claim.company)
		expense_claim.posting_date = frappe.flags.current_date
		expense_claim.expense_approver = frappe.db.get_global('demo_hr_user')
		expense_claim.save()

		rand = random.random()

		if rand < 0.4:
			update_sanctioned_amount(expense_claim)
			expense_claim.approval_status = 'Approved'
			expense_claim.submit()

			if random.randint(0, 1):
				#make journal entry against expense claim
				je = frappe.get_doc(make_bank_entry("Expense Claim", expense_claim.name))
				je.posting_date = frappe.flags.current_date
				je.cheque_no = random_string(10)
				je.cheque_date = frappe.flags.current_date
				je.flags.ignore_permissions = 1
				je.submit()
示例#9
0
def get_bootinfo():
    """build and return boot info"""
    frappe.set_user_lang(frappe.session.user)
    bootinfo = frappe._dict()
    hooks = frappe.get_hooks()
    doclist = []

    # user
    get_user(bootinfo)

    # system info
    bootinfo['sysdefaults'] = frappe.defaults.get_defaults()
    bootinfo['server_date'] = frappe.utils.nowdate()
    bootinfo["send_print_in_body_and_attachment"] = frappe.db.get_value(
        "Outgoing Email Settings", None, "send_print_in_body_and_attachment")

    if frappe.session['user'] != 'Guest':
        bootinfo['user_info'] = get_fullnames()
        bootinfo['sid'] = frappe.session['sid']

    # home page
    bootinfo.modules = {}
    for app in frappe.get_installed_apps():
        try:
            bootinfo.modules.update(
                frappe.get_attr(app + ".config.desktop.get_data")() or {})
        except ImportError:
            pass

    bootinfo.module_app = frappe.local.module_app
    bootinfo.hidden_modules = frappe.db.get_global("hidden_modules")
    bootinfo.doctype_icons = dict(
        frappe.db.sql("""select name, icon from
		tabDocType where ifnull(icon,'')!=''"""))
    bootinfo.doctype_icons.update(
        dict(
            frappe.db.sql("""select name, icon from
		tabPage where ifnull(icon,'')!=''""")))

    add_home_page(bootinfo, doclist)
    add_allowed_pages(bootinfo)
    load_translations(bootinfo)
    load_conf_settings(bootinfo)

    # ipinfo
    if frappe.session['data'].get('ipinfo'):
        bootinfo['ipinfo'] = frappe.session['data']['ipinfo']

    # add docs
    bootinfo['docs'] = doclist

    for method in hooks.boot_session or []:
        frappe.get_attr(method)(bootinfo)

    if bootinfo.lang:
        bootinfo.lang = unicode(bootinfo.lang)

    return bootinfo
示例#10
0
def get_bootinfo():
	"""build and return boot info"""
	frappe.set_user_lang(frappe.session.user)
	bootinfo = frappe._dict()
	hooks = frappe.get_hooks()
	doclist = []

	# user
	get_user(bootinfo)

	# system info
	bootinfo['sysdefaults'] = frappe.defaults.get_defaults()
	bootinfo['server_date'] = frappe.utils.nowdate()

	if frappe.session['user'] != 'Guest':
		bootinfo['user_info'] = get_fullnames()
		bootinfo['sid'] = frappe.session['sid'];

	# home page
	bootinfo.modules = {}
	for app in frappe.get_installed_apps():
		try:
			bootinfo.modules.update(frappe.get_attr(app + ".config.desktop.get_data")() or {})
		except ImportError:
			pass
		except AttributeError:
			pass

	bootinfo.module_app = frappe.local.module_app
	bootinfo.hidden_modules = frappe.db.get_global("hidden_modules")
	bootinfo.doctype_icons = dict(frappe.db.sql("""select name, icon from
		tabDocType where ifnull(icon,'')!=''"""))
	bootinfo.single_types = frappe.db.sql_list("""select name from tabDocType where ifnull(issingle,0)=1""")
	add_home_page(bootinfo, doclist)
	bootinfo.page_info = get_allowed_pages()
	load_translations(bootinfo)
	add_timezone_info(bootinfo)
	load_conf_settings(bootinfo)
	load_print(bootinfo, doclist)

	# ipinfo
	if frappe.session['data'].get('ipinfo'):
		bootinfo['ipinfo'] = frappe.session['data']['ipinfo']

	# add docs
	bootinfo['docs'] = doclist

	for method in hooks.boot_session or []:
		frappe.get_attr(method)(bootinfo)

	if bootinfo.lang:
		bootinfo.lang = unicode(bootinfo.lang)

	bootinfo.error_report_email = frappe.get_hooks("error_report_email")
	bootinfo.default_background_image = "/assets/frappe/images/ui/into-the-dawn.jpg"

	return bootinfo
示例#11
0
文件: boot.py 项目: indautgrp/frappe
def get_bootinfo():
	"""build and return boot info"""
	frappe.set_user_lang(frappe.session.user)
	bootinfo = frappe._dict()
	hooks = frappe.get_hooks()
	doclist = []

	# user
	get_user(bootinfo)

	# system info
	bootinfo.sysdefaults = frappe.defaults.get_defaults()
	bootinfo.server_date = frappe.utils.nowdate()

	if frappe.session['user'] != 'Guest':
		bootinfo.user_info = get_fullnames()
		bootinfo.sid = frappe.session['sid'];

	bootinfo.modules = {}
	bootinfo.module_list = []
	load_desktop_icons(bootinfo)

	bootinfo.module_app = frappe.local.module_app
	bootinfo.single_types = frappe.db.sql_list("""select name from tabDocType
		where issingle=1""")
	add_home_page(bootinfo, doclist)
	bootinfo.page_info = get_allowed_pages()
	load_translations(bootinfo)
	add_timezone_info(bootinfo)
	load_conf_settings(bootinfo)
	load_print(bootinfo, doclist)
	doclist.extend(get_meta_bundle("Page"))
	bootinfo.home_folder = frappe.db.get_value("File", {"is_home_folder": 1})

	# ipinfo
	if frappe.session.data.get('ipinfo'):
		bootinfo.ipinfo = frappe.session['data']['ipinfo']

	# add docs
	bootinfo.docs = doclist

	for method in hooks.boot_session or []:
		frappe.get_attr(method)(bootinfo)

	if bootinfo.lang:
		bootinfo.lang = unicode(bootinfo.lang)
	bootinfo.versions = {k: v['version'] for k, v in get_versions().items()}

	bootinfo.error_report_email = frappe.get_hooks("error_report_email")
	bootinfo.calendars = sorted(frappe.get_hooks("calendars"))
	bootinfo.treeviews = frappe.get_hooks("treeviews") or []
	bootinfo.email_accounts = frappe.get_all('User Emails', fields=['email_account', 'email_id'],
		filters=dict(parent=frappe.session.user), order_by='idx')
	bootinfo.lang_dict = get_lang_dict()

	return bootinfo
示例#12
0
文件: stock.py 项目: ektai/erpnext
def work():
    frappe.set_user(frappe.db.get_global('demo_manufacturing_user'))
    frappe.set_user_lang(frappe.db.get_global('demo_manufacturing_user'))

    make_purchase_receipt()
    make_delivery_note()
    make_stock_reconciliation()
    submit_draft_stock_entries()
    make_sales_return_records()
    make_purchase_return_records()
示例#13
0
    def before_import(self):
        # set user lang for translations
        frappe.cache().hdel("lang", frappe.session.user)
        frappe.set_user_lang(frappe.session.user)

        # set flags
        frappe.flags.in_import = True
        frappe.flags.mute_emails = self.data_import.mute_emails

        self.data_import.db_set("template_warnings", "")
示例#14
0
def get_bootinfo():
	"""build and return boot info"""
	frappe.set_user_lang(frappe.session.user)
	bootinfo = frappe._dict()
	hooks = frappe.get_hooks()
	doclist = []

	# user
	get_user(bootinfo)

	# system info
	bootinfo['sysdefaults'] = frappe.defaults.get_defaults()
	bootinfo['server_date'] = frappe.utils.nowdate()
	bootinfo["send_print_in_body_and_attachment"] = frappe.db.get_value("Outgoing Email Settings",
		None, "send_print_in_body_and_attachment")

	if frappe.session['user'] != 'Guest':
		bootinfo['user_info'] = get_fullnames()
		bootinfo['sid'] = frappe.session['sid'];

	# home page
	bootinfo.modules = {}
	for app in frappe.get_installed_apps():
		try:
			bootinfo.modules.update(frappe.get_attr(app + ".config.desktop.data") or {})
		except ImportError:
			pass

	bootinfo.module_app = frappe.local.module_app
	bootinfo.hidden_modules = frappe.db.get_global("hidden_modules")
	bootinfo.doctype_icons = dict(frappe.db.sql("""select name, icon from
		tabDocType where ifnull(icon,'')!=''"""))
	bootinfo.doctype_icons.update(dict(frappe.db.sql("""select name, icon from
		tabPage where ifnull(icon,'')!=''""")))

	add_home_page(bootinfo, doclist)
	add_allowed_pages(bootinfo)
	load_translations(bootinfo)
	load_conf_settings(bootinfo)

	# ipinfo
	if frappe.session['data'].get('ipinfo'):
		bootinfo['ipinfo'] = frappe.session['data']['ipinfo']

	# add docs
	bootinfo['docs'] = doclist

	for method in hooks.boot_session or []:
		frappe.get_attr(method)(bootinfo)

	if bootinfo.lang:
		bootinfo.lang = unicode(bootinfo.lang)

	return bootinfo
示例#15
0
def verify_request():
    woocommerce_settings = frappe.get_doc("Woocommerce Settings")
    sig = base64.b64encode(
        hmac.new(woocommerce_settings.secret.encode('utf8'),
                 frappe.request.data, hashlib.sha256).digest())

    if frappe.request.data and \
     frappe.get_request_header("X-Wc-Webhook-Signature") and \
     not sig == bytes(frappe.get_request_header("X-Wc-Webhook-Signature").encode()):
        frappe.throw(_("Unverified Webhook Data"))
    frappe.set_user(woocommerce_settings.creation_user)
    frappe.set_user_lang(woocommerce_settings.creation_user)
示例#16
0
def get_bootinfo():
    """build and return boot info"""
    frappe.set_user_lang(frappe.session.user)
    bootinfo = frappe._dict()
    hooks = frappe.get_hooks()
    doclist = []

    # user
    get_user(bootinfo)

    # system info
    bootinfo['sysdefaults'] = frappe.defaults.get_defaults()
    bootinfo['server_date'] = frappe.utils.nowdate()

    if frappe.session['user'] != 'Guest':
        bootinfo['user_info'] = get_fullnames()
        bootinfo['sid'] = frappe.session['sid']

    bootinfo.modules = {}
    bootinfo.module_list = []
    load_desktop_icons(bootinfo)

    bootinfo.module_app = frappe.local.module_app
    bootinfo.single_types = frappe.db.sql_list(
        """select name from tabDocType where issingle=1""")
    add_home_page(bootinfo, doclist)
    bootinfo.page_info = get_allowed_pages()
    load_translations(bootinfo)
    add_timezone_info(bootinfo)
    load_conf_settings(bootinfo)
    load_print(bootinfo, doclist)
    doclist.extend(get_meta_bundle("Page"))
    bootinfo.home_folder = frappe.db.get_value("File", {"is_home_folder": 1})

    # ipinfo
    if frappe.session['data'].get('ipinfo'):
        bootinfo['ipinfo'] = frappe.session['data']['ipinfo']

    # add docs
    bootinfo['docs'] = doclist

    for method in hooks.boot_session or []:
        frappe.get_attr(method)(bootinfo)

    if bootinfo.lang:
        bootinfo.lang = unicode(bootinfo.lang)
    bootinfo['versions'] = {k: v['version'] for k, v in get_versions().items()}

    bootinfo.error_report_email = frappe.get_hooks("error_report_email")
    bootinfo.calendars = sorted(frappe.get_hooks("calendars"))
    bootinfo["lang_dict"] = get_lang_dict()

    return bootinfo
示例#17
0
def run():
	frappe.set_user("*****@*****.**")
	frappe.set_user_lang("fr")

	if random.random() <= 0.6:
		sales_orders = frappe.get_all("Sales Order", filters={"per_billed": ("<", 100)})
		for so in sales_orders[:random.randint(1, 5)]:
			try:
				si = frappe.get_doc(make_sales_invoice(so))
				si.set_posting_time = True
				si.posting_date = frappe.flags.current_date
				si.payment_schedule = []
				for d in si.get("items"):
					if not d.income_account:
						d.income_account = "Sales - {}".format(frappe.get_cached_value('Company',  si.company,  'abbr'))
				si.insert()
				si.submit()
				frappe.db.commit()
			except frappe.ValidationError:
				pass
			except erpnext.accounts.utils.FiscalYearError:
				add_fiscal_year(frappe.flags.current_date)

	# TODO
	"""
	if random.random() <= 0.6:
		report = "Received Items to be Billed"
		for pr in list(set([r[0] for r in query_report.run(report)["result"]
			if r[0]!="Total"]))[:random.randint(1, 5)]:
			try:
				pi = frappe.get_doc(make_purchase_invoice(pr))
				pi.set_posting_time = True
				pi.posting_date = frappe.flags.current_date
				pi.bill_no = random_string(6)
				pi.insert()
				pi.submit()
				frappe.db.commit()
			except frappe.ValidationError:
				pass
	"""


	if random.random() < 0.5:
		make_payment_entries("Sales Invoice", "Accounts Receivable")

	# TODO
	"""
示例#18
0
def send_summary(timespan):
    from frappe.utils.user import get_enabled_system_users
    from frappe.social.doctype.energy_point_settings.energy_point_settings import is_energy_point_enabled

    if not is_energy_point_enabled():
        return
    from_date = frappe.utils.add_to_date(None, weeks=-1)
    if timespan == 'Monthly':
        from_date = frappe.utils.add_to_date(None, months=-1)

    user_points = get_user_energy_and_review_points(from_date=from_date,
                                                    as_dict=False)

    # do not send report if no activity found
    if not user_points or not user_points[0].energy_points: return

    from_date = getdate(from_date)
    to_date = getdate()
    settings = {x["name"]: x["energy_points_summary"] for x in frappe.get_all("User", \
     filters={"user_type": "System User", "enabled": 1}, fields=["name", "energy_points_summary"])}
    all_users = [
        user for user in get_enabled_system_users()
        if settings.get(user["name"]) == 1
    ]

    for user in all_users:
        frappe.set_user_lang(user.name)
        frappe.sendmail(
            subject=_('{} energy points summary').format(_(timespan)),
            recipients=user.email,
            template="energy_points_summary",
            args={
                'top_performer':
                user_points[0],
                'top_reviewer':
                max(user_points, key=lambda x: x['given_points']),
                'standings':
                user_points[:10],  # top 10
                'footer_message':
                get_footer_message(timespan).format(from_date, to_date)
            })

    frappe.set_user_lang(frappe.session.user)
示例#19
0
def send_event_digest():
	today = nowdate()
	for user in get_enabled_system_users():
		events = get_events(today, today, user.name, for_reminder=True)
		if events:
			text = ""
			frappe.set_user_lang(user.name, user.language)

			text = "<h3>" + frappe._("Events In Today's Calendar") + "</h3>"
			for e in events:
				if e.all_day:
					e.starts_on = "All Day"
				text += "<h4>%(starts_on)s: %(subject)s</h4><p>%(description)s</p>" % e

			text += '<p style="color: #888; font-size: 80%; margin-top: 20px; padding-top: 10px; border-top: 1px solid #eee;">'\
				+ frappe._("Daily Event Digest is sent for Calendar Events where reminders are set.")+'</p>'

			frappe.sendmail(recipients=user.email, subject=frappe._("Upcoming Events for Today"),
				content = text)
示例#20
0
def send_event_digest():
    today = nowdate()
    for user in get_enabled_system_users():
        events = get_events(today, today, user.name, for_reminder=True)
        if events:
            frappe.set_user_lang(user.name, user.language)

            for e in events:
                e.starts_on = format_datetime(e.starts_on, 'hh:mm a')
                if e.all_day:
                    e.starts_on = "All Day"

            frappe.sendmail(
                recipients=user.email,
                subject=frappe._("Upcoming Events for Today"),
                template="upcoming_events",
                args={
                    'events': events,
                },
                header=[frappe._("Events in Today's Calendar"), 'blue'])
示例#21
0
def work():
    frappe.set_user(frappe.db.get_global('demo_accounts_user'))
    frappe.set_user_lang(frappe.db.get_global('demo_accounts_user'))

    # Enable booking asset depreciation entry automatically
    frappe.db.set_value("Accounts Settings", None,
                        "book_asset_depreciation_entry_automatically", 1)

    # post depreciation entries as on today
    post_depreciation_entries()

    # scrap a random asset
    frappe.db.set_value("Company", "Wind Power", "disposal_account",
                        _("Gain/Loss on Asset Disposal") + " - WP")

    asset = get_random_asset()
    scrap_asset(asset.name)

    # Sell a random asset
    sell_an_asset()
示例#22
0
文件: event.py 项目: ESS-LLP/frappe
def send_event_digest():
	today = nowdate()
	for user in get_enabled_system_users():
		events = get_events(today, today, user.name, for_reminder=True)
		if events:
			frappe.set_user_lang(user.name, user.language)

			for e in events:
				e.starts_on = format_datetime(e.starts_on, 'hh:mm a')
				if e.all_day:
					e.starts_on = "All Day"

			frappe.sendmail(
				recipients=user.email,
				subject=frappe._("Upcoming Events for Today"),
				template="upcoming_events",
				args={
					'events': events,
				},
				header=[frappe._("Events in Today's Calendar"), 'blue']
			)
示例#23
0
def make_item_booking():
	user = get_random("User")
	item = get_random("Item", filters={"enable_item_booking": 1})

	frappe.set_user(user)
	frappe.set_user_lang("fr")

	availabilities = get_availabilities(item, add_days(frappe.flags.current_date, 1), add_days(frappe.flags.current_date, 2))
	if availabilities:
		availability = availabilities[random.randint(0, len(availabilities) - 1)]

		ib = frappe.get_doc({
			"doctype": "Item Booking",
			"user": user,
			"item": item,
			"starts_on": availability.get("start"),
			"ends_on": availability.get("end"),
			"status": STATUSES[random.randint(0, 2)]
		})

		ib.insert(ignore_permissions=True)
		frappe.db.commit()
示例#24
0
def send_event_digest():
	today = nowdate()
	for user in frappe.db.sql("""select name, email, language
		from tabUser where ifnull(enabled,0)=1
		and user_type='System User' and name not in ({})""".format(", ".join(["%s"]*len(STANDARD_USERS))),
		STANDARD_USERS, as_dict=1):

		events = get_events(today, today, user.name, for_reminder=True)
		if events:
			text = ""
			frappe.set_user_lang(user.name, user.language)

			text = "<h3>" + frappe._("Events In Today's Calendar") + "</h3>"
			for e in events:
				if e.all_day:
					e.starts_on = "All Day"
				text += "<h4>%(starts_on)s: %(subject)s</h4><p>%(description)s</p>" % e

			text += '<p style="color: #888; font-size: 80%; margin-top: 20px; padding-top: 10px; border-top: 1px solid #eee;">'\
				+ frappe._("Daily Event Digest is sent for Calendar Events where reminders are set.")+'</p>'

			from frappe.utils.email_lib import sendmail
			sendmail(recipients=user.email, subject=frappe._("Upcoming Events for Today"),
				msg = text)
示例#25
0
def upload(rows = None, submit_after_import=None, ignore_encoding_errors=False, no_email=True, overwrite=None,
	update_only = None, ignore_links=False, pre_process=None, via_console=False, from_data_import="No",
	skip_errors = True, data_import_doc=None, validate_template=False, user=None):
	"""upload data"""

	# for translations
	if user:
		frappe.cache().hdel("lang", user)
		frappe.set_user_lang(user)

	if data_import_doc and isinstance(data_import_doc, string_types):
		data_import_doc = frappe.get_doc("Data Import", data_import_doc)
	if data_import_doc and from_data_import == "Yes":
		no_email = data_import_doc.no_email
		ignore_encoding_errors = data_import_doc.ignore_encoding_errors
		update_only = data_import_doc.only_update
		submit_after_import = data_import_doc.submit_after_import
		overwrite = data_import_doc.overwrite
		skip_errors = data_import_doc.skip_errors
	else:
		# extra input params
		params = json.loads(frappe.form_dict.get("params") or '{}')
		if params.get("submit_after_import"):
			submit_after_import = True
		if params.get("ignore_encoding_errors"):
			ignore_encoding_errors = True
		if not params.get("no_email"):
			no_email = False
		if params.get('update_only'):
			update_only = True
		if params.get('from_data_import'):
			from_data_import = params.get('from_data_import')
		if not params.get('skip_errors'):
			skip_errors = params.get('skip_errors')

	frappe.flags.in_import = True
	frappe.flags.mute_emails = no_email

	def get_data_keys_definition():
		return get_data_keys()

	def bad_template():
		frappe.throw(_("Please do not change the rows above {0}").format(get_data_keys_definition().data_separator))

	def check_data_length():
		if not data:
			frappe.throw(_("No data found in the file. Please reattach the new file with data."))

	def get_start_row():
		for i, row in enumerate(rows):
			if row and row[0]==get_data_keys_definition().data_separator:
				return i+1
		bad_template()

	def get_header_row(key):
		return get_header_row_and_idx(key)[0]

	def get_header_row_and_idx(key):
		for i, row in enumerate(header):
			if row and row[0]==key:
				return row, i
		return [], -1

	def filter_empty_columns(columns):
		empty_cols = list(filter(lambda x: x in ("", None), columns))

		if empty_cols:
			if columns[-1*len(empty_cols):] == empty_cols:
				# filter empty columns if they exist at the end
				columns = columns[:-1*len(empty_cols)]
			else:
				frappe.msgprint(_("Please make sure that there are no empty columns in the file."),
					raise_exception=1)

		return columns

	def make_column_map():
		doctype_row, row_idx = get_header_row_and_idx(get_data_keys_definition().doctype)
		if row_idx == -1: # old style
			return

		dt = None
		for i, d in enumerate(doctype_row[1:]):
			if d not in ("~", "-"):
				if d and doctype_row[i] in (None, '' ,'~', '-', _("DocType") + ":"):
					dt, parentfield = d, None
					# xls format truncates the row, so it may not have more columns
					if len(doctype_row) > i+2:
						parentfield = doctype_row[i+2]
					doctypes.append((dt, parentfield))
					column_idx_to_fieldname[(dt, parentfield)] = {}
					column_idx_to_fieldtype[(dt, parentfield)] = {}
				if dt:
					column_idx_to_fieldname[(dt, parentfield)][i+1] = rows[row_idx + 2][i+1]
					column_idx_to_fieldtype[(dt, parentfield)][i+1] = rows[row_idx + 4][i+1]

	def get_doc(start_idx):
		if doctypes:
			doc = {}
			attachments = []
			last_error_row_idx = None
			for idx in range(start_idx, len(rows)):
				last_error_row_idx = idx	# pylint: disable=W0612
				if (not doc) or main_doc_empty(rows[idx]):
					for dt, parentfield in doctypes:
						d = {}
						for column_idx in column_idx_to_fieldname[(dt, parentfield)]:
							try:
								fieldname = column_idx_to_fieldname[(dt, parentfield)][column_idx]
								fieldtype = column_idx_to_fieldtype[(dt, parentfield)][column_idx]

								if not fieldname or not rows[idx][column_idx]:
									continue

								d[fieldname] = rows[idx][column_idx]
								if fieldtype in ("Int", "Check"):
									d[fieldname] = cint(d[fieldname])
								elif fieldtype in ("Float", "Currency", "Percent"):
									d[fieldname] = flt(d[fieldname])
								elif fieldtype == "Date":
									if d[fieldname] and isinstance(d[fieldname], string_types):
										d[fieldname] = getdate(parse_date(d[fieldname]))
								elif fieldtype == "Datetime":
									if d[fieldname]:
										if " " in d[fieldname]:
											_date, _time = d[fieldname].split()
										else:
											_date, _time = d[fieldname], '00:00:00'
										_date = parse_date(d[fieldname])
										d[fieldname] = get_datetime(_date + " " + _time)
									else:
										d[fieldname] = None

								elif fieldtype in ("Image", "Attach Image", "Attach"):
									# added file to attachments list
									attachments.append(d[fieldname])

								elif fieldtype in ("Link", "Dynamic Link", "Data") and d[fieldname]:
									# as fields can be saved in the number format(long type) in data import template
									d[fieldname] = cstr(d[fieldname])

							except IndexError:
								pass

						# scrub quotes from name and modified
						if d.get("name") and d["name"].startswith('"'):
							d["name"] = d["name"][1:-1]

						if sum([0 if not val else 1 for val in d.values()]):
							d['doctype'] = dt
							if dt == doctype:
								doc.update(d)
							else:
								if not overwrite and doc.get("name"):
									d['parent'] = doc["name"]
								d['parenttype'] = doctype
								d['parentfield'] = parentfield
								doc.setdefault(d['parentfield'], []).append(d)
				else:
					break

			return doc, attachments, last_error_row_idx
		else:
			doc = frappe._dict(zip(columns, rows[start_idx][1:]))
			doc['doctype'] = doctype
			return doc, [], None

	# used in testing whether a row is empty or parent row or child row
	# checked only 3 first columns since first two columns can be blank for example the case of
	# importing the item variant where item code and item name will be blank.
	def main_doc_empty(row):
		if row:
			for i in range(3,0,-1):
				if len(row) > i and row[i]:
					return False
		return True

	def validate_naming(doc):
		autoname = frappe.get_meta(doctype).autoname
		if autoname:
			if autoname[0:5] == 'field':
				autoname = autoname[6:]
			elif autoname == 'naming_series:':
				autoname = 'naming_series'
			else:
				return True

			if (autoname not in doc) or (not doc[autoname]):
				from frappe.model.base_document import get_controller
				if not hasattr(get_controller(doctype), "autoname"):
					frappe.throw(_("{0} is a mandatory field".format(autoname)))
		return True

	users = frappe.db.sql_list("select name from tabUser")
	def prepare_for_insert(doc):
		# don't block data import if user is not set
		# migrating from another system
		if not doc.owner in users:
			doc.owner = frappe.session.user
		if not doc.modified_by in users:
			doc.modified_by = frappe.session.user

	def is_valid_url(url):
		is_valid = False
		if url.startswith("/files") or url.startswith("/private/files"):
			url = get_url(url)

		try:
			r = requests.get(url)
			is_valid = True if r.status_code == 200 else False
		except Exception:
			pass

		return is_valid

	def attach_file_to_doc(doctype, docname, file_url):
		# check if attachment is already available
		# check if the attachement link is relative or not
		if not file_url:
			return
		if not is_valid_url(file_url):
			return

		files = frappe.db.sql("""Select name from `tabFile` where attached_to_doctype='{doctype}' and
			attached_to_name='{docname}' and (file_url='{file_url}' or thumbnail_url='{file_url}')""".format(
				doctype=doctype,
				docname=docname,
				file_url=file_url
			))

		if files:
			# file is already attached
			return

		save_url(file_url, None, doctype, docname, "Home/Attachments", 0)

	# header
	filename, file_extension = ['','']
	if not rows:
		from frappe.utils.file_manager import get_file # get_file_doc
		fname, fcontent = get_file(data_import_doc.import_file)
		filename, file_extension = os.path.splitext(fname)

		if file_extension == '.xlsx' and from_data_import == 'Yes':
			from frappe.utils.xlsxutils import read_xlsx_file_from_attached_file
			rows = read_xlsx_file_from_attached_file(file_id=data_import_doc.import_file)

		elif file_extension == '.csv':
			from frappe.utils.csvutils import read_csv_content
			rows = read_csv_content(fcontent, ignore_encoding_errors)

		else:
			frappe.throw(_("Unsupported File Format"))

	start_row = get_start_row()
	header = rows[:start_row]
	data = rows[start_row:]
	try:
		doctype = get_header_row(get_data_keys_definition().main_table)[1]
		columns = filter_empty_columns(get_header_row(get_data_keys_definition().columns)[1:])
	except:
		frappe.throw(_("Cannot change header content"))
	doctypes = []
	column_idx_to_fieldname = {}
	column_idx_to_fieldtype = {}

	if skip_errors:
		data_rows_with_error = header

	if submit_after_import and not cint(frappe.db.get_value("DocType",
			doctype, "is_submittable")):
		submit_after_import = False

	parenttype = get_header_row(get_data_keys_definition().parent_table)

	if len(parenttype) > 1:
		parenttype = parenttype[1]

	# check permissions
	if not frappe.permissions.can_import(parenttype or doctype):
		frappe.flags.mute_emails = False
		return {"messages": [_("Not allowed to Import") + ": " + _(doctype)], "error": True}

	# Throw expception in case of the empty data file
	check_data_length()
	make_column_map()
	total = len(data)

	if validate_template:
		if total:
			data_import_doc.total_rows = total
		return True

	if overwrite==None:
		overwrite = params.get('overwrite')

	# delete child rows (if parenttype)
	parentfield = None
	if parenttype:
		parentfield = get_parent_field(doctype, parenttype)

		if overwrite:
			delete_child_rows(data, doctype)

	import_log = []
	def log(**kwargs):
		if via_console:
			print((kwargs.get("title") + kwargs.get("message")).encode('utf-8'))
		else:
			import_log.append(kwargs)

	def as_link(doctype, name):
		if via_console:
			return "{0}: {1}".format(doctype, name)
		else:
			return getlink(doctype, name)

	# publish realtime task update
	def publish_progress(achieved, reload=False):
		if data_import_doc:
			frappe.publish_realtime("data_import_progress", {"progress": str(int(100.0*achieved/total)),
				"data_import": data_import_doc.name, "reload": reload}, user=frappe.session.user)


	error_flag = rollback_flag = False

	batch_size = frappe.conf.data_import_batch_size or 1000

	for batch_start in range(0, total, batch_size):
		batch = data[batch_start:batch_start + batch_size]

		for i, row in enumerate(batch):
			# bypass empty rows
			if main_doc_empty(row):
				continue

			row_idx = i + start_row
			doc = None

			publish_progress(i)

			try:
				doc, attachments, last_error_row_idx = get_doc(row_idx)
				validate_naming(doc)
				if pre_process:
					pre_process(doc)

				original = None
				if parentfield:
					parent = frappe.get_doc(parenttype, doc["parent"])
					doc = parent.append(parentfield, doc)
					parent.save()
				else:
					if overwrite and doc.get("name") and frappe.db.exists(doctype, doc["name"]):
						original = frappe.get_doc(doctype, doc["name"])
						original_name = original.name
						original.update(doc)
						# preserve original name for case sensitivity
						original.name = original_name
						original.flags.ignore_links = ignore_links
						original.save()
						doc = original
					else:
						if not update_only:
							doc = frappe.get_doc(doc)
							prepare_for_insert(doc)
							doc.flags.ignore_links = ignore_links
							doc.insert()
					if attachments:
						# check file url and create a File document
						for file_url in attachments:
							attach_file_to_doc(doc.doctype, doc.name, file_url)
					if submit_after_import:
						doc.submit()

				# log errors
				if parentfield:
					log(**{"row": doc.idx, "title": 'Inserted row for "%s"' % (as_link(parenttype, doc.parent)),
						"link": get_url_to_form(parenttype, doc.parent), "message": 'Document successfully saved', "indicator": "green"})
				elif submit_after_import:
					log(**{"row": row_idx + 1, "title":'Submitted row for "%s"' % (as_link(doc.doctype, doc.name)),
						"message": "Document successfully submitted", "link": get_url_to_form(doc.doctype, doc.name), "indicator": "blue"})
				elif original:
					log(**{"row": row_idx + 1,"title":'Updated row for "%s"' % (as_link(doc.doctype, doc.name)),
						"message": "Document successfully updated", "link": get_url_to_form(doc.doctype, doc.name), "indicator": "green"})
				elif not update_only:
					log(**{"row": row_idx + 1, "title":'Inserted row for "%s"' % (as_link(doc.doctype, doc.name)),
						"message": "Document successfully saved", "link": get_url_to_form(doc.doctype, doc.name), "indicator": "green"})
				else:
					log(**{"row": row_idx + 1, "title":'Ignored row for %s' % (row[1]), "link": None,
						"message": "Document updation ignored", "indicator": "orange"})

			except Exception as e:
				error_flag = True

				# build error message
				if frappe.local.message_log:
					err_msg = "\n".join(['<p class="border-bottom small">{}</p>'.format(json.loads(msg).get('message')) for msg in frappe.local.message_log])
				else:
					err_msg = '<p class="border-bottom small">{}</p>'.format(cstr(e))

				error_trace = frappe.get_traceback()
				if error_trace:
					error_log_doc = frappe.log_error(error_trace)
					error_link = get_url_to_form("Error Log", error_log_doc.name)
				else:
					error_link = None

				log(**{
					"row": row_idx + 1,
					"title": 'Error for row %s' % (len(row)>1 and frappe.safe_decode(row[1]) or ""),
					"message": err_msg,
					"indicator": "red",
					"link":error_link
				})

				# data with error to create a new file
				# include the errored data in the last row as last_error_row_idx will not be updated for the last row
				if skip_errors:
					if last_error_row_idx == len(rows)-1:
						last_error_row_idx = len(rows)
					data_rows_with_error += rows[row_idx:last_error_row_idx]
				else:
					rollback_flag = True
			finally:
				frappe.local.message_log = []

		start_row += batch_size
		if rollback_flag:
			frappe.db.rollback()
		else:
			frappe.db.commit()

	frappe.flags.mute_emails = False
	frappe.flags.in_import = False

	log_message = {"messages": import_log, "error": error_flag}
	if data_import_doc:
		data_import_doc.log_details = json.dumps(log_message)

		import_status = None
		if error_flag and data_import_doc.skip_errors and len(data) != len(data_rows_with_error):
			import_status = "Partially Successful"
			# write the file with the faulty row
			from frappe.utils.file_manager import save_file
			file_name = 'error_' + filename + file_extension
			if file_extension == '.xlsx':
				from frappe.utils.xlsxutils import make_xlsx
				xlsx_file = make_xlsx(data_rows_with_error, "Data Import Template")
				file_data = xlsx_file.getvalue()
			else:
				from frappe.utils.csvutils import to_csv
				file_data = to_csv(data_rows_with_error)
			error_data_file = save_file(file_name, file_data, "Data Import",
				data_import_doc.name,  "Home/Attachments")
			data_import_doc.error_file = error_data_file.file_url

		elif error_flag:
			import_status = "Failed"
		else:
			import_status = "Successful"

		data_import_doc.import_status = import_status
		data_import_doc.save()
		if data_import_doc.import_status in ["Successful", "Partially Successful"]:
			data_import_doc.submit()
			publish_progress(100, True)
		else:
			publish_progress(0, True)
		frappe.db.commit()
	else:
		return log_message
示例#26
0
def run():
	frappe.set_user("*****@*****.**")
	frappe.set_user_lang("fr")

	if random.random() < 0.6:
		report = "Items To Be Requested"
		for row in query_report.run(report)["result"][:random.randint(1, 5)]:
			item_code, qty = row[0], abs(row[-1])

			mr = make_material_request(item_code, qty)

	if random.random() < 0.6:
		for mr in frappe.get_all('Material Request',
			filters={'material_request_type': 'Purchase', 'status': 'Open'},
			limit=random.randint(1,6)):
			if not frappe.get_all('Request for Quotation',
				filters={'material_request': mr.name}, limit=1):
				rfq = make_request_for_quotation(mr.name)
				rfq.transaction_date = frappe.flags.current_date
				add_suppliers(rfq)
				rfq.save()
				rfq.submit()

	# Make suppier quotation from RFQ against each supplier.
	if random.random() < 0.6:
		for rfq in frappe.get_all('Request for Quotation',
			filters={'status': 'Open'}, limit=random.randint(1, 6)):
			if not frappe.get_all('Supplier Quotation',
				filters={'request_for_quotation': rfq.name}, limit=1):
				rfq = frappe.get_doc('Request for Quotation', rfq.name)

				for supplier in rfq.suppliers:
					supplier_quotation = make_quotation_from_rfq(rfq.name, supplier.supplier)
					supplier_quotation.save()
					supplier_quotation.submit()

	# get supplier details
	supplier = get_random("Supplier")

	company_currency = frappe.get_cached_value('Company', erpnext.get_default_company(), "default_currency")
	party_account_currency = get_party_account_currency("Supplier", supplier, erpnext.get_default_company())
	if company_currency == party_account_currency:
		exchange_rate = 1
	else:
		exchange_rate = get_exchange_rate(party_account_currency, company_currency, args="for_buying")

	# make supplier quotations
	if random.random() < 0.5:
		from erpnext.stock.doctype.material_request.material_request import make_supplier_quotation

		report = "Material Requests for which Supplier Quotations are not created"
		for row in query_report.run(report)["result"][:random.randint(1, 3)]:
			if row[0] != "Total":
				sq = frappe.get_doc(make_supplier_quotation(row[0]))
				sq.transaction_date = frappe.flags.current_date
				sq.supplier = supplier
				sq.currency = party_account_currency or company_currency
				sq.conversion_rate = exchange_rate
				sq.insert()
				sq.submit()
				frappe.db.commit()

	# make purchase orders
	if random.random() < 0.5:
		from erpnext.stock.doctype.material_request.material_request import make_purchase_order
		report = "Requested Items To Be Ordered"
		for row in query_report.run(report)["result"][:how_many("Purchase Order")]:
			if row[0] != "Total":
				try:
					po = frappe.get_doc(make_purchase_order(row[0]))
					po.supplier = supplier
					po.currency = party_account_currency or company_currency
					po.conversion_rate = exchange_rate
					po.transaction_date = frappe.flags.current_date
					po.insert()
					po.submit()
				except Exception:
					pass
				else:
					frappe.db.commit()

	if random.random() < 0.5:
		make_subcontract()
示例#27
0
def run():
    frappe.set_user("*****@*****.**")
    frappe.set_user_lang("fr")

    for i in range(random.randint(1, 7)):
        if random.random() < 0.5:
            make_opportunity()

    for i in range(random.randint(1, 7)):
        if random.random() < 0.5:
            make_quotation()

    try:
        lost_reason = frappe.get_doc({
            "doctype": "Opportunity Lost Reason",
            "lost_reason": _("Did not ask")
        })
        lost_reason.save(ignore_permissions=True)
    except frappe.exceptions.DuplicateEntryError:
        pass

    # lost quotations / inquiries
    if random.random() < 0.3:
        for i in range(random.randint(1, 3)):
            quotation = get_random('Quotation', doc=True)
            if quotation and quotation.status == 'Submitted':
                quotation.declare_order_lost([{
                    'lost_reason': _('Did not ask')
                }])

        for i in range(random.randint(1, 3)):
            opportunity = get_random('Opportunity', doc=True)
            if opportunity and opportunity.status in ('Open', 'Replied'):
                opportunity.declare_enquiry_lost([{
                    'lost_reason':
                    _('Did not ask')
                }])

    for i in range(random.randint(1, 7)):
        if random.random() < 0.6:
            make_sales_order()

    if random.random() < 0.5:
        #make payment request against Sales Order
        sales_order_name = get_random("Sales Order", filters={"docstatus": 1})
        try:
            if sales_order_name:
                so = frappe.get_doc("Sales Order", sales_order_name)
                if flt(so.per_billed) != 100:
                    payment_request = make_payment_request(
                        dt="Sales Order",
                        dn=so.name,
                        recipient_id=so.contact_email,
                        submit_doc=True,
                        mute_email=True,
                        use_dummy_message=True)

                    payment_entry = frappe.get_doc(
                        make_payment_entry(payment_request.name))
                    payment_entry.posting_date = frappe.flags.current_date
                    payment_entry.submit()
        except Exception:
            pass
示例#28
0
	def import_data(self):
		# set user lang for translations
		frappe.cache().hdel("lang", frappe.session.user)
		frappe.set_user_lang(frappe.session.user)

		if not self.console:
			self.data_import.db_set("template_warnings", "")

		# set flags
		frappe.flags.in_import = True
		frappe.flags.mute_emails = self.data_import.mute_emails

		# prepare a map for missing link field values
		self.prepare_missing_link_field_values()

		# parse docs from rows
		payloads = self.get_payloads_for_import()

		# dont import if there are non-ignorable warnings
		warnings = [w for w in self.warnings if w.get("type") != "info"]
		if warnings:
			if self.console:
				self.print_grouped_warnings(warnings)
			else:
				self.data_import.db_set("template_warnings", json.dumps(warnings))
				frappe.publish_realtime(
					"data_import_refresh", {"data_import": self.data_import.name}
				)
			return

		# setup import log
		if self.data_import.import_log:
			import_log = frappe.parse_json(self.data_import.import_log)
		else:
			import_log = []

		# remove previous failures from import log
		import_log = [l for l in import_log if l.get("success") == True]

		# get successfully imported rows
		imported_rows = []
		for log in import_log:
			log = frappe._dict(log)
			if log.success:
				imported_rows += log.row_indexes

		# start import
		total_payload_count = len(payloads)
		batch_size = frappe.conf.data_import_batch_size or 1000

		for batch_index, batched_payloads in enumerate(
			frappe.utils.create_batch(payloads, batch_size)
		):
			for i, payload in enumerate(batched_payloads):
				doc = payload.doc
				row_indexes = [row[0] for row in payload.rows]
				current_index = (i + 1) + (batch_index * batch_size)

				if set(row_indexes).intersection(set(imported_rows)):
					print("Skipping imported rows", row_indexes)
					if total_payload_count > 5:
						frappe.publish_realtime(
							"data_import_progress",
							{
								"current": current_index,
								"total": total_payload_count,
								"skipping": True,
								"data_import": self.data_import.name,
							},
						)
					continue

				try:
					start = timeit.default_timer()
					doc = self.process_doc(doc)
					processing_time = timeit.default_timer() - start
					eta = self.get_eta(current_index, total_payload_count, processing_time)

					if total_payload_count > 5:
						frappe.publish_realtime(
							"data_import_progress",
							{
								"current": current_index,
								"total": total_payload_count,
								"docname": doc.name,
								"data_import": self.data_import.name,
								"success": True,
								"row_indexes": row_indexes,
								"eta": eta,
							},
						)
					if self.console:
						update_progress_bar(
							"Importing {0} records".format(total_payload_count),
							current_index,
							total_payload_count,
						)
					import_log.append(
						frappe._dict(success=True, docname=doc.name, row_indexes=row_indexes)
					)
					# commit after every successful import
					frappe.db.commit()

				except Exception:
					import_log.append(
						frappe._dict(
							success=False,
							exception=frappe.get_traceback(),
							messages=frappe.local.message_log,
							row_indexes=row_indexes,
						)
					)
					frappe.clear_messages()
					# rollback if exception
					frappe.db.rollback()

		# set status
		failures = [l for l in import_log if l.get("success") == False]
		if len(failures) == total_payload_count:
			status = "Pending"
		elif len(failures) > 0:
			status = "Partial Success"
		else:
			status = "Success"

		if self.console:
			self.print_import_log(import_log)
		else:
			self.data_import.db_set("status", status)
			self.data_import.db_set("import_log", json.dumps(import_log))

		frappe.flags.in_import = False
		frappe.flags.mute_emails = False
		frappe.publish_realtime("data_import_refresh", {"data_import": self.data_import.name})

		return import_log
示例#29
0
文件: boot.py 项目: britlog/frappe
def get_bootinfo():
	"""build and return boot info"""
	frappe.set_user_lang(frappe.session.user)
	bootinfo = frappe._dict()
	hooks = frappe.get_hooks()
	doclist = []

	# user
	get_user(bootinfo)

	# system info
	bootinfo.sitename = frappe.local.site
	bootinfo.sysdefaults = frappe.defaults.get_defaults()
	bootinfo.user_permissions = get_user_permissions()
	bootinfo.server_date = frappe.utils.nowdate()

	if frappe.session['user'] != 'Guest':
		bootinfo.user_info = get_fullnames()
		bootinfo.sid = frappe.session['sid'];

	bootinfo.modules = {}
	bootinfo.module_list = []
	load_desktop_icons(bootinfo)
	bootinfo.letter_heads = get_letter_heads()
	bootinfo.active_domains = frappe.get_active_domains()
	bootinfo.all_domains = [d.get("name") for d in frappe.get_all("Domain")]

	bootinfo.module_app = frappe.local.module_app
	bootinfo.single_types = frappe.db.sql_list("""select name from tabDocType
		where issingle=1""")
	add_home_page(bootinfo, doclist)
	bootinfo.page_info = get_allowed_pages()
	load_translations(bootinfo)
	add_timezone_info(bootinfo)
	load_conf_settings(bootinfo)
	load_print(bootinfo, doclist)
	doclist.extend(get_meta_bundle("Page"))
	bootinfo.home_folder = frappe.db.get_value("File", {"is_home_folder": 1})

	# ipinfo
	if frappe.session.data.get('ipinfo'):
		bootinfo.ipinfo = frappe.session['data']['ipinfo']

	# add docs
	bootinfo.docs = doclist

	for method in hooks.boot_session or []:
		frappe.get_attr(method)(bootinfo)

	if bootinfo.lang:
		bootinfo.lang = text_type(bootinfo.lang)
	bootinfo.versions = {k: v['version'] for k, v in get_versions().items()}

	bootinfo.error_report_email = frappe.get_hooks("error_report_email")
	bootinfo.calendars = sorted(frappe.get_hooks("calendars"))
	bootinfo.treeviews = frappe.get_hooks("treeviews") or []
	bootinfo.lang_dict = get_lang_dict()
	bootinfo.feedback_triggers = get_enabled_feedback_trigger()
	bootinfo.gsuite_enabled = get_gsuite_status()
	bootinfo.update(get_email_accounts(user=frappe.session.user))

	return bootinfo
示例#30
0
def work():
    if random.random() < 0.3: return

    frappe.set_user(frappe.db.get_global('demo_manufacturing_user'))
    frappe.set_user_lang(frappe.db.get_global('demo_manufacturing_user'))
    if not frappe.get_all('Sales Order'): return

    from erpnext.projects.doctype.timesheet.timesheet import OverlapError

    ppt = frappe.new_doc("Production Plan")
    ppt.company = erpnext.get_default_company()
    # ppt.use_multi_level_bom = 1 #refactored
    ppt.get_items_from = "Sales Order"
    # ppt.purchase_request_for_warehouse = "Stores - WP" # refactored
    ppt.run_method("get_open_sales_orders")
    if not ppt.get("sales_orders"): return
    ppt.run_method("get_items")
    ppt.run_method("raise_material_requests")
    ppt.save()
    ppt.submit()
    ppt.run_method("raise_work_orders")
    frappe.db.commit()

    # submit work orders
    for pro in frappe.db.get_values("Work Order", {"docstatus": 0}, "name"):
        b = frappe.get_doc("Work Order", pro[0])
        b.wip_warehouse = "Work in Progress - WP"
        b.submit()
        frappe.db.commit()

    # submit material requests
    for pro in frappe.db.get_values("Material Request", {"docstatus": 0},
                                    "name"):
        b = frappe.get_doc("Material Request", pro[0])
        b.submit()
        frappe.db.commit()

    # stores -> wip
    if random.random() < 0.4:
        for pro in query_report.run("Open Work Orders")[
                "result"][:how_many("Stock Entry for WIP")]:
            make_stock_entry_from_pro(pro[0],
                                      "Material Transfer for Manufacture")

    # wip -> fg
    if random.random() < 0.4:
        for pro in query_report.run("Work Orders in Progress")[
                "result"][:how_many("Stock Entry for FG")]:
            make_stock_entry_from_pro(pro[0], "Manufacture")

    for bom in frappe.get_all('BOM',
                              fields=['item'],
                              filters={'with_operations': 1}):
        pro_order = make_wo_order_test_record(
            item=bom.item,
            qty=2,
            source_warehouse=_("Stores") + " - WP",
            wip_warehouse=_("Work in Progress") + " - WP",
            fg_warehouse=_("Stores") + " - WP",
            company=erpnext.get_default_company(),
            stock_uom=frappe.db.get_value('Item', bom.item, 'stock_uom'),
            planned_start_date=get_datetime(frappe.flags.current_date))

    # submit job card
    if random.random() < 0.4:
        submit_job_cards()
示例#31
0
def get_bootinfo():
    """build and return boot info"""
    frappe.set_user_lang(frappe.session.user)
    bootinfo = frappe._dict()
    hooks = frappe.get_hooks()
    doclist = []

    # user
    get_user(bootinfo)

    # system info
    bootinfo["sysdefaults"] = frappe.defaults.get_defaults()
    bootinfo["server_date"] = frappe.utils.nowdate()

    if frappe.session["user"] != "Guest":
        bootinfo["user_info"] = get_fullnames()
        bootinfo["sid"] = frappe.session["sid"]

        # home page
    bootinfo.modules = {}
    for app in frappe.get_installed_apps():
        try:
            bootinfo.modules.update(frappe.get_attr(app + ".config.desktop.get_data")() or {})
        except ImportError:
            pass
        except AttributeError:
            pass

    bootinfo.module_app = frappe.local.module_app
    bootinfo.hidden_modules = frappe.db.get_global("hidden_modules")
    bootinfo.doctype_icons = dict(
        frappe.db.sql(
            """select name, icon from
		tabDocType where ifnull(icon,'')!=''"""
        )
    )
    bootinfo.single_types = frappe.db.sql_list("""select name from tabDocType where ifnull(issingle,0)=1""")
    add_home_page(bootinfo, doclist)
    bootinfo.page_info = get_allowed_pages()
    load_translations(bootinfo)
    add_timezone_info(bootinfo)
    load_conf_settings(bootinfo)
    load_print(bootinfo, doclist)
    doclist.extend(get_meta_bundle("Page"))

    # ipinfo
    if frappe.session["data"].get("ipinfo"):
        bootinfo["ipinfo"] = frappe.session["data"]["ipinfo"]

        # add docs
    bootinfo["docs"] = doclist

    for method in hooks.boot_session or []:
        frappe.get_attr(method)(bootinfo)

    if bootinfo.lang:
        bootinfo.lang = unicode(bootinfo.lang)
    bootinfo["versions"] = {k: v["version"] for k, v in get_versions().items()}

    bootinfo.error_report_email = frappe.get_hooks("error_report_email")
    bootinfo.default_background_image = get_url("/assets/frappe/images/ui/into-the-dawn.jpg")
    bootinfo.calendars = sorted(frappe.get_hooks("calendars"))

    return bootinfo
示例#32
0
def get_bootinfo():
    """build and return boot info"""
    frappe.set_user_lang(frappe.session.user)
    bootinfo = frappe._dict()
    hooks = frappe.get_hooks()
    doclist = []

    # user
    get_user(bootinfo)

    # system info
    bootinfo.sitename = frappe.local.site
    bootinfo.sysdefaults = frappe.defaults.get_defaults()
    bootinfo.server_date = frappe.utils.nowdate()

    if frappe.session['user'] != 'Guest':
        bootinfo.user_info = get_user_info()
        bootinfo.sid = frappe.session['sid']

    bootinfo.modules = {}
    bootinfo.module_list = []
    load_desktop_data(bootinfo)
    bootinfo.letter_heads = get_letter_heads()
    bootinfo.active_domains = frappe.get_active_domains()
    bootinfo.all_domains = [d.get("name") for d in frappe.get_all("Domain")]
    add_layouts(bootinfo)

    bootinfo.module_app = frappe.local.module_app
    bootinfo.single_types = [
        d.name for d in frappe.get_all('DocType', {'issingle': 1})
    ]
    bootinfo.nested_set_doctypes = [
        d.parent
        for d in frappe.get_all('DocField', {'fieldname': 'lft'}, ['parent'])
    ]
    add_home_page(bootinfo, doclist)
    bootinfo.page_info = get_allowed_pages()
    load_translations(bootinfo)
    add_timezone_info(bootinfo)
    load_conf_settings(bootinfo)
    load_print(bootinfo, doclist)
    doclist.extend(get_meta_bundle("Page"))
    bootinfo.home_folder = frappe.db.get_value("File", {"is_home_folder": 1})
    bootinfo.navbar_settings = get_navbar_settings()
    bootinfo.notification_settings = get_notification_settings()

    # ipinfo
    if frappe.session.data.get('ipinfo'):
        bootinfo.ipinfo = frappe.session['data']['ipinfo']

    # add docs
    bootinfo.docs = doclist

    for method in hooks.boot_session or []:
        frappe.get_attr(method)(bootinfo)

    if bootinfo.lang:
        bootinfo.lang = text_type(bootinfo.lang)
    bootinfo.versions = {k: v['version'] for k, v in get_versions().items()}

    bootinfo.error_report_email = frappe.conf.error_report_email
    bootinfo.calendars = sorted(frappe.get_hooks("calendars"))
    bootinfo.treeviews = frappe.get_hooks("treeviews") or []
    bootinfo.lang_dict = get_lang_dict()
    bootinfo.success_action = get_success_action()
    bootinfo.update(get_email_accounts(user=frappe.session.user))
    bootinfo.energy_points_enabled = is_energy_point_enabled()
    bootinfo.website_tracking_enabled = is_tracking_enabled()
    bootinfo.points = get_energy_points(frappe.session.user)
    bootinfo.frequently_visited_links = frequently_visited_links()
    bootinfo.link_preview_doctypes = get_link_preview_doctypes()
    bootinfo.additional_filters_config = get_additional_filters_from_hooks()
    bootinfo.desk_settings = get_desk_settings()
    bootinfo.app_logo_url = get_app_logo()

    return bootinfo
示例#33
0
文件: boot.py 项目: BIANBS/frappe
def get_bootinfo():
    """build and return boot info"""
    frappe.set_user_lang(frappe.session.user)
    bootinfo = frappe._dict()
    hooks = frappe.get_hooks()
    doclist = []

    # user
    get_user(bootinfo)

    # system info
    bootinfo["sysdefaults"] = frappe.defaults.get_defaults()
    bootinfo["server_date"] = frappe.utils.nowdate()

    if frappe.session["user"] != "Guest":
        bootinfo["user_info"] = get_fullnames()
        bootinfo["sid"] = frappe.session["sid"]

        # home page
    bootinfo.modules = {}
    for app in frappe.get_installed_apps():
        try:
            bootinfo.modules.update(frappe.get_attr(app + ".config.desktop.get_data")() or {})
        except ImportError:
            pass
        except AttributeError:
            pass

    bootinfo.module_app = frappe.local.module_app
    bootinfo.hidden_modules = frappe.db.get_global("hidden_modules")
    bootinfo.doctype_icons = dict(
        frappe.db.sql(
            """select name, icon from
		tabDocType where ifnull(icon,'')!=''"""
        )
    )
    bootinfo.doctype_icons.update(
        dict(
            frappe.db.sql(
                """select name, icon from
		tabPage where ifnull(icon,'')!=''"""
            )
        )
    )

    add_home_page(bootinfo, doclist)
    add_allowed_pages(bootinfo)
    load_translations(bootinfo)
    add_timezone_info(bootinfo)
    load_conf_settings(bootinfo)
    load_print(bootinfo, doclist)

    # ipinfo
    if frappe.session["data"].get("ipinfo"):
        bootinfo["ipinfo"] = frappe.session["data"]["ipinfo"]

        # add docs
    bootinfo["docs"] = doclist

    for method in hooks.boot_session or []:
        frappe.get_attr(method)(bootinfo)

    if bootinfo.lang:
        bootinfo.lang = unicode(bootinfo.lang)

    bootinfo.error_report_email = frappe.get_hooks("error_report_email")

    return bootinfo
示例#34
0
文件: boot.py 项目: fogueri/frappe
def load_translations(bootinfo):
    frappe.set_user_lang(frappe.session.user)

    if frappe.lang != 'en':
        bootinfo["__messages"] = frappe.get_lang_dict("include")
        bootinfo["lang"] = frappe.lang
示例#35
0
def upload(rows=None,
           submit_after_import=None,
           ignore_encoding_errors=False,
           no_email=True,
           overwrite=None,
           update_only=None,
           ignore_links=False,
           pre_process=None,
           via_console=False,
           from_data_import="No",
           skip_errors=True,
           data_import_doc=None,
           validate_template=False,
           user=None):
    """upload data"""

    # for translations
    if user:
        frappe.cache().hdel("lang", user)
        frappe.set_user_lang(user)
    #frappe.msgprint(data_import_doc.overwrite)
    if data_import_doc and isinstance(data_import_doc, string_types):
        data_import_doc = frappe.get_doc("Data Import", data_import_doc)
        #frappe.msgprint("found in database")
        #frappe.msgprint(data_import_doc.overwrite)
    if data_import_doc and from_data_import == "Yes":
        no_email = data_import_doc.no_email
        ignore_encoding_errors = data_import_doc.ignore_encoding_errors
        update_only = data_import_doc.only_update
        submit_after_import = data_import_doc.submit_after_import
        overwrite = data_import_doc.overwrite
        #frappe.msgprint("overwrite %s" % overwrite)
        skip_errors = data_import_doc.skip_errors
    else:
        # extra input params
        params = json.loads(frappe.form_dict.get("params") or '{}')
        if params.get("submit_after_import"):
            submit_after_import = True
        if params.get("ignore_encoding_errors"):
            ignore_encoding_errors = True
        if not params.get("no_email"):
            no_email = False
        if params.get('update_only'):
            update_only = True
        if params.get('from_data_import'):
            from_data_import = params.get('from_data_import')
        if not params.get('skip_errors'):
            skip_errors = params.get('skip_errors')

    frappe.flags.in_import = True
    frappe.flags.mute_emails = no_email

    def get_data_keys_definition():
        return get_data_keys()

    def bad_template():
        frappe.throw(
            _("Please do not change the rows above {0}").format(
                get_data_keys_definition().data_separator))

    def check_data_length():
        if not data:
            frappe.throw(
                _("No data found in the file. Please reattach the new file with data."
                  ))

    def get_start_row():
        for i, row in enumerate(rows):
            if row and row[0] == get_data_keys_definition().data_separator:
                return i + 1
        bad_template()

    def get_header_row(key):
        return get_header_row_and_idx(key)[0]

    def get_header_row_and_idx(key):
        for i, row in enumerate(header):
            if row and row[0] == key:
                return row, i
        return [], -1

    def filter_empty_columns(columns):
        empty_cols = list(filter(lambda x: x in ("", None), columns))

        if empty_cols:
            if columns[-1 * len(empty_cols):] == empty_cols:
                # filter empty columns if they exist at the end
                columns = columns[:-1 * len(empty_cols)]
            else:
                frappe.msgprint(_(
                    "Please make sure that there are no empty columns in the file."
                ),
                                raise_exception=1)

        return columns

    def make_column_map():
        doctype_row, row_idx = get_header_row_and_idx(
            get_data_keys_definition().doctype)
        if row_idx == -1:  # old style
            return

        dt = None
        for i, d in enumerate(doctype_row[1:]):
            if d not in ("~", "-"):
                if d and doctype_row[i] in (None, '', '~', '-',
                                            _("DocType") + ":"):
                    dt, parentfield = d, None
                    # xls format truncates the row, so it may not have more columns
                    if len(doctype_row) > i + 2:
                        parentfield = doctype_row[i + 2]
                    doctypes.append((dt, parentfield))
                    column_idx_to_fieldname[(dt, parentfield)] = {}
                    column_idx_to_fieldtype[(dt, parentfield)] = {}
                if dt:
                    column_idx_to_fieldname[(dt,
                                             parentfield)][i +
                                                           1] = rows[row_idx +
                                                                     2][i + 1]
                    column_idx_to_fieldtype[(dt,
                                             parentfield)][i +
                                                           1] = rows[row_idx +
                                                                     4][i + 1]

    def get_doc(start_idx):
        if doctypes:
            doc = {}
            attachments = []
            last_error_row_idx = None
            for idx in range(start_idx, len(rows)):
                last_error_row_idx = idx  # pylint: disable=W0612
                if (not doc) or main_doc_empty(rows[idx]):
                    for dt, parentfield in doctypes:
                        d = {}
                        for column_idx in column_idx_to_fieldname[(
                                dt, parentfield)]:
                            try:
                                fieldname = column_idx_to_fieldname[(
                                    dt, parentfield)][column_idx]
                                fieldtype = column_idx_to_fieldtype[(
                                    dt, parentfield)][column_idx]

                                if not fieldname or not rows[idx][column_idx]:
                                    continue

                                d[fieldname] = rows[idx][column_idx]
                                if fieldtype in ("Int", "Check"):
                                    d[fieldname] = cint(d[fieldname])
                                elif fieldtype in ("Float", "Currency",
                                                   "Percent"):
                                    d[fieldname] = flt(d[fieldname])
                                elif fieldtype == "Date":
                                    if d[fieldname] and isinstance(
                                            d[fieldname], string_types):
                                        d[fieldname] = getdate(
                                            parse_date(d[fieldname]))
                                elif fieldtype == "Datetime":
                                    if d[fieldname]:
                                        if " " in d[fieldname]:
                                            _date, _time = d[fieldname].split()
                                        else:
                                            _date, _time = d[
                                                fieldname], '00:00:00'
                                        _date = parse_date(d[fieldname])
                                        d[fieldname] = get_datetime(_date +
                                                                    " " +
                                                                    _time)
                                    else:
                                        d[fieldname] = None

                                elif fieldtype in ("Image", "Attach Image",
                                                   "Attach"):
                                    # added file to attachments list
                                    attachments.append(d[fieldname])

                                elif fieldtype in ("Link", "Dynamic Link",
                                                   "Data") and d[fieldname]:
                                    # as fields can be saved in the number format(long type) in data import template
                                    d[fieldname] = cstr(d[fieldname])

                            except IndexError:
                                pass

                        # scrub quotes from name and modified
                        if d.get("name") and d["name"].startswith('"'):
                            d["name"] = d["name"][1:-1]

                        if sum([0 if not val else 1 for val in d.values()]):
                            d['doctype'] = dt
                            if dt == doctype:
                                doc.update(d)
                            else:
                                if not overwrite and doc.get("name"):
                                    d['parent'] = doc["name"]
                                d['parenttype'] = doctype
                                d['parentfield'] = parentfield
                                doc.setdefault(d['parentfield'], []).append(d)
                else:
                    break
            #frappe.msgprint(doc)
            return doc, attachments, last_error_row_idx
        else:
            doc = frappe._dict(zip(columns, rows[start_idx][1:]))
            doc['doctype'] = doctype
            return doc, [], None

    # used in testing whether a row is empty or parent row or child row
    # checked only 3 first columns since first two columns can be blank for example the case of
    # importing the item variant where item code and item name will be blank.
    def main_doc_empty(row):
        if row:
            for i in range(3, 0, -1):
                if len(row) > i and row[i]:
                    return False
        return True

    def validate_naming(doc):
        autoname = frappe.get_meta(doctype).autoname
        if autoname:
            if autoname[0:5] == 'field':
                autoname = autoname[6:]
            elif autoname == 'naming_series:':
                autoname = 'naming_series'
            else:
                return True

            if (autoname not in doc) or (not doc[autoname]):
                from frappe.model.base_document import get_controller
                if not hasattr(get_controller(doctype), "autoname"):
                    frappe.throw(_(
                        "{0} is a mandatory field".format(autoname)))
        return True

    users = frappe.db.sql_list("select name from tabUser")

    def prepare_for_insert(doc):
        # don't block data import if user is not set
        # migrating from another system
        if not doc.owner in users:
            doc.owner = frappe.session.user
        if not doc.modified_by in users:
            doc.modified_by = frappe.session.user

    def is_valid_url(url):
        is_valid = False
        if url.startswith("/files") or url.startswith("/private/files"):
            url = get_url(url)

        try:
            r = requests.get(url)
            is_valid = True if r.status_code == 200 else False
        except Exception:
            pass

        return is_valid

    def attach_file_to_doc(doctype, docname, file_url):
        # check if attachment is already available
        # check if the attachement link is relative or not
        if not file_url:
            return
        if not is_valid_url(file_url):
            return

        files = frappe.db.sql(
            """Select name from `tabFile` where attached_to_doctype='{doctype}' and
			attached_to_name='{docname}' and (file_url='{file_url}' or thumbnail_url='{file_url}')"""
            .format(doctype=doctype, docname=docname, file_url=file_url))

        if files:
            # file is already attached
            return

        save_url(file_url, None, doctype, docname, "Home/Attachments", 0)

    # header
    filename, file_extension = ['', '']
    if not rows:
        from frappe.utils.file_manager import get_file  # get_file_doc
        fname, fcontent = get_file(data_import_doc.import_file)
        filename, file_extension = os.path.splitext(fname)

        if file_extension == '.xlsx' and from_data_import == 'Yes':
            from frappe.utils.xlsxutils import read_xlsx_file_from_attached_file
            rows = read_xlsx_file_from_attached_file(
                file_id=data_import_doc.import_file)
            #frappe.msgprint("%d" % len(rows))
            #frappe.msgprint(rows)
        elif file_extension == '.csv':
            from frappe.utils.csvutils import read_csv_content
            rows = read_csv_content(fcontent, ignore_encoding_errors)

        else:
            frappe.throw(_("Unsupported File Format"))

    start_row = get_start_row()
    header = rows[:start_row]
    data = rows[start_row:]
    try:
        doctype = get_header_row(get_data_keys_definition().main_table)[1]
        columns = filter_empty_columns(
            get_header_row(get_data_keys_definition().columns)[1:])
    except:
        frappe.throw(_("Cannot change header content"))
    doctypes = []
    column_idx_to_fieldname = {}
    column_idx_to_fieldtype = {}

    if skip_errors:
        data_rows_with_error = header

    if submit_after_import and not cint(
            frappe.db.get_value("DocType", doctype, "is_submittable")):
        submit_after_import = False

    parenttype = get_header_row(get_data_keys_definition().parent_table)

    if len(parenttype) > 1:
        parenttype = parenttype[1]

    # check permissions
    if not frappe.permissions.can_import(parenttype or doctype):
        frappe.flags.mute_emails = False
        return {
            "messages": [_("Not allowed to Import") + ": " + _(doctype)],
            "error": True
        }

    # Throw expception in case of the empty data file
    check_data_length()
    make_column_map()
    total = len(data)

    if validate_template:
        if total:
            data_import_doc.total_rows = total
        return True

    if overwrite == None:
        overwrite = params.get('overwrite')

    # delete child rows (if parenttype)
    parentfield = None
    if parenttype:
        parentfield = get_parent_field(doctype, parenttype)

        if overwrite:
            frappe.msgprint("still overwrtie")
            delete_child_rows(data, doctype)

    import_log = []

    def log(**kwargs):
        if via_console:
            print(
                (kwargs.get("title") + kwargs.get("message")).encode('utf-8'))
        else:
            import_log.append(kwargs)

    def as_link(doctype, name):
        if via_console:
            return "{0}: {1}".format(doctype, name)
        else:
            return getlink(doctype, name)

    # publish realtime task update
    def publish_progress(achieved, reload=False):
        if data_import_doc:
            frappe.publish_realtime(
                "data_import_progress", {
                    "progress": str(int(100.0 * achieved / total)),
                    "data_import": data_import_doc.name,
                    "reload": reload
                },
                user=frappe.session.user)

    error_flag = rollback_flag = False

    batch_size = frappe.conf.data_import_batch_size or 1000

    for batch_start in range(0, total, batch_size):
        batch = data[batch_start:batch_start + batch_size]

        for i, row in enumerate(batch):
            # bypass empty rows
            if main_doc_empty(row):
                continue
            #frappe.msgprint("in batch %s" % overwrite)
            #frappe.msgprint("docName %s" % doc.get("name"))
            #frappe.msgprint("exist db %s" % frappe.db.exists(doctype,doc["name"]))
            row_idx = i + start_row
            doc = None

            publish_progress(i)

            #frappe.msgprint("in batch %s" % doc)

            try:
                doc, attachments, last_error_row_idx = get_doc(row_idx)
                validate_naming(doc)
                if pre_process:
                    pre_process(doc)

                original = None
                if parentfield:
                    parent = frappe.get_doc(parenttype, doc["parent"])
                    doc = parent.append(parentfield, doc)
                    parent.save()
                else:
                    if overwrite and doc.get("name") and frappe.db.exists(
                            doctype, doc["name"]):
                        original = frappe.get_doc(doctype, doc["name"])
                        #frappe.msgprint("overwite %s" % original.name)
                        original_name = original.name
                        #frappe.msgprint(original)
                        #frappe.msgprint(doc)
                        original.update(doc)
                        #frappe.msgprint(original)
                        # preserve original name for case sensitivity
                        original.name = original_name
                        original.flags.ignore_links = ignore_links
                        original.save()
                        doc = original
                    else:
                        frappe.msgprint("not overwrite")
                        if not update_only:
                            doc = frappe.get_doc(doc)
                            prepare_for_insert(doc)
                            doc.flags.ignore_links = ignore_links
                            doc.insert()
                    if attachments:
                        # check file url and create a File document
                        for file_url in attachments:
                            attach_file_to_doc(doc.doctype, doc.name, file_url)
                    if submit_after_import:
                        doc.submit()

                # log errors
                if parentfield:
                    log(
                        **{
                            "row":
                            doc.idx,
                            "title":
                            'Inserted row for "%s"' %
                            (as_link(parenttype, doc.parent)),
                            "link":
                            get_absolute_url(parenttype, doc.parent),
                            "message":
                            'Document successfully saved',
                            "indicator":
                            "green"
                        })
                elif submit_after_import:
                    log(
                        **{
                            "row":
                            row_idx + 1,
                            "title":
                            'Submitted row for "%s"' %
                            (as_link(doc.doctype, doc.name)),
                            "message":
                            "Document successfully submitted",
                            "link":
                            get_absolute_url(doc.doctype, doc.name),
                            "indicator":
                            "blue"
                        })
                elif original:
                    log(
                        **{
                            "row":
                            row_idx + 1,
                            "title":
                            'Updated row for "%s"' %
                            (as_link(doc.doctype, doc.name)),
                            "message":
                            "Document successfully updated",
                            "link":
                            get_absolute_url(doc.doctype, doc.name),
                            "indicator":
                            "green"
                        })
                elif not update_only:
                    log(
                        **{
                            "row":
                            row_idx + 1,
                            "title":
                            'Inserted row for "%s"' %
                            (as_link(doc.doctype, doc.name)),
                            "message":
                            "Document successfully saved",
                            "link":
                            get_absolute_url(doc.doctype, doc.name),
                            "indicator":
                            "green"
                        })
                else:
                    log(
                        **{
                            "row": row_idx + 1,
                            "title": 'Ignored row for %s' % (row[1]),
                            "link": None,
                            "message": "Document updation ignored",
                            "indicator": "orange"
                        })

            except Exception as e:
                error_flag = True

                # build error message
                if frappe.local.message_log:
                    err_msg = "\n".join([
                        '<p class="border-bottom small">{}</p>'.format(
                            json.loads(msg).get('message'))
                        for msg in frappe.local.message_log
                    ])
                else:
                    err_msg = '<p class="border-bottom small">{}</p>'.format(
                        cstr(e))

                error_trace = frappe.get_traceback()
                if error_trace:
                    error_log_doc = frappe.log_error(error_trace)
                    error_link = get_absolute_url("Error Log",
                                                  error_log_doc.name)
                else:
                    error_link = None

                log(
                    **{
                        "row":
                        row_idx + 1,
                        "title":
                        'Error for row %s' %
                        (len(row) > 1 and frappe.safe_decode(row[1]) or ""),
                        "message":
                        err_msg,
                        "indicator":
                        "red",
                        "link":
                        error_link
                    })

                # data with error to create a new file
                # include the errored data in the last row as last_error_row_idx will not be updated for the last row
                if skip_errors:
                    if last_error_row_idx == len(rows) - 1:
                        last_error_row_idx = len(rows)
                    data_rows_with_error += rows[row_idx:last_error_row_idx]
                else:
                    rollback_flag = True
            finally:
                frappe.local.message_log = []

        start_row += batch_size
        if rollback_flag:
            frappe.db.rollback()
        else:
            frappe.db.commit()

    frappe.flags.mute_emails = False
    frappe.flags.in_import = False

    log_message = {"messages": import_log, "error": error_flag}
    if data_import_doc:
        data_import_doc.log_details = json.dumps(log_message)

        import_status = None
        if error_flag and data_import_doc.skip_errors and len(data) != len(
                data_rows_with_error):
            import_status = "Partially Successful"
            # write the file with the faulty row
            from frappe.utils.file_manager import save_file
            file_name = 'error_' + filename + file_extension
            if file_extension == '.xlsx':
                from frappe.utils.xlsxutils import make_xlsx
                xlsx_file = make_xlsx(data_rows_with_error,
                                      "Data Import Template")
                file_data = xlsx_file.getvalue()
            else:
                from frappe.utils.csvutils import to_csv
                file_data = to_csv(data_rows_with_error)
            error_data_file = save_file(file_name, file_data, "Data Import",
                                        data_import_doc.name,
                                        "Home/Attachments")
            data_import_doc.error_file = error_data_file.file_url

        elif error_flag:
            import_status = "Failed"
        else:
            import_status = "Successful"

        data_import_doc.import_status = import_status
        data_import_doc.save()
        if data_import_doc.import_status in [
                "Successful", "Partially Successful"
        ]:
            data_import_doc.submit()
            publish_progress(100, True)
        else:
            publish_progress(0, True)
        frappe.db.commit()
    else:
        return log_message
示例#36
0
def work():
    frappe.set_user(frappe.db.get_global('demo_accounts_user'))
    frappe.set_user_lang(frappe.db.get_global('demo_accounts_user'))

    if random.random() <= 0.6:
        report = "Ordered Items to be Billed"
        for so in list(
                set([
                    r[0] for r in query_report.run(report)["result"]
                    if r[0] != "Total"
                ]))[:random.randint(1, 5)]:
            try:
                si = frappe.get_doc(make_sales_invoice(so))
                si.set_posting_time = True
                si.posting_date = frappe.flags.current_date
                si.payment_schedule = []
                for d in si.get("items"):
                    if not d.income_account:
                        d.income_account = "Sales - {}".format(
                            frappe.get_cached_value('Company', si.company,
                                                    'abbr'))
                si.insert()
                si.submit()
                frappe.db.commit()
            except frappe.ValidationError:
                pass

    if random.random() <= 0.6:
        report = "Received Items to be Billed"
        for pr in list(
                set([
                    r[0] for r in query_report.run(report)["result"]
                    if r[0] != "Total"
                ]))[:random.randint(1, 5)]:
            try:
                pi = frappe.get_doc(make_purchase_invoice(pr))
                pi.set_posting_time = True
                pi.posting_date = frappe.flags.current_date
                pi.bill_no = random_string(6)
                pi.insert()
                pi.submit()
                frappe.db.commit()
            except frappe.ValidationError:
                pass

    if random.random() < 0.5:
        make_payment_entries("Sales Invoice", "Accounts Receivable")

    if random.random() < 0.5:
        make_payment_entries("Purchase Invoice", "Accounts Payable")

    if random.random() < 0.4:
        #make payment request against sales invoice
        sales_invoice_name = get_random("Sales Invoice",
                                        filters={"docstatus": 1})
        if sales_invoice_name:
            si = frappe.get_doc("Sales Invoice", sales_invoice_name)
            if si.outstanding_amount > 0:
                payment_request = make_payment_request(
                    dt="Sales Invoice",
                    dn=si.name,
                    recipient_id=si.contact_email,
                    no_payment_link=1,
                    submit_doc=True,
                    mute_email=True,
                    use_dummy_message=True)

                payment_entry = frappe.get_doc(
                    make_payment_entry(payment_request.name))
                payment_entry.posting_date = frappe.flags.current_date
                payment_entry.submit()

    make_pos_invoice()