Ejemplo n.º 1
0
    def get_payment_url(self):
        if self.reference_doctype != "Fees":
            data = frappe.db.get_value(self.reference_doctype,
                                       self.reference_name,
                                       ["company", "customer_name"],
                                       as_dict=1)
        else:
            data = frappe.db.get_value(self.reference_doctype,
                                       self.reference_name, ["student_name"],
                                       as_dict=1)
            data.update({"company": frappe.defaults.get_defaults().company})

        controller = get_payment_gateway_controller(self.payment_gateway)
        controller.validate_transaction_currency(self.currency)

        if hasattr(controller, 'validate_minimum_transaction_amount'):
            controller.validate_minimum_transaction_amount(
                self.currency, self.grand_total)

        return controller.get_payment_url(
            **{
                "amount": flt(self.grand_total, self.precision("grand_total")),
                "title": frappe.as_unicode(data.company),
                "description": frappe.as_unicode(self.subject),
                "reference_doctype": "Payment Request",
                "reference_docname": self.name,
                "payer_email": self.email_to or frappe.session.user,
                "payer_name": frappe.as_unicode(data.customer_name),
                "order_id": self.name,
                "currency": self.currency
            })
def execute():
	ignore_doctypes = ["Lead", "Opportunity", "POS Profile", "Tax Rule", "Pricing Rule"]
	customers = frappe.get_all('Customer', fields=["name", "customer_group"])
	customer_group_fetch = get_fetch_fields('Customer', 'Customer Group', ignore_doctypes)

	batch_size = 1000
	for i in range(0, len(customers), batch_size):
		batch_customers = customers[i:i + batch_size]
		for d in customer_group_fetch:
			when_then = []
			for customer in batch_customers:
				value = frappe.db.escape(frappe.as_unicode(customer.get("customer_group")))

				when_then.append('''
					WHEN `%s` = "%s" and %s != "%s"
					THEN "%s"
				'''%(d["master_fieldname"], frappe.db.escape(frappe.as_unicode(customer.name)),
					d["linked_to_fieldname"], value, value))

			frappe.db.sql("""
				update
					`tab%s`
				set
					%s = CASE %s  ELSE `%s` END
			"""%(d['doctype'], d.linked_to_fieldname, " ".join(when_then), d.linked_to_fieldname))
Ejemplo n.º 3
0
	def _create_reference_document(self, doctype):
		""" Create reference document if it does not exist in the system.
		"""
		parent = frappe.new_doc(doctype)
		email_fileds = self.get_email_fields(doctype)

		if email_fileds.subject_field:
			parent.set(email_fileds.subject_field, frappe.as_unicode(self.subject)[:140])

		if email_fileds.sender_field:
			parent.set(email_fileds.sender_field, frappe.as_unicode(self.from_email))

		parent.flags.ignore_mandatory = True

		try:
			parent.insert(ignore_permissions=True)
		except frappe.DuplicateEntryError:
			# try and find matching parent
			parent_name = frappe.db.get_value(self.email_account.append_to,
				{email_fileds.sender_field: self.from_email}
			)
			if parent_name:
				parent.name = parent_name
			else:
				parent = None
		return parent
Ejemplo n.º 4
0
def execute():
    ignore_doctypes = [
        "Lead", "Opportunity", "POS Profile", "Tax Rule", "Pricing Rule"
    ]
    customers = frappe.get_all('Customer', fields=["name", "customer_group"])
    customer_group_fetch = get_fetch_fields('Customer', 'Customer Group',
                                            ignore_doctypes)

    batch_size = 1000
    for i in range(0, len(customers), batch_size):
        batch_customers = customers[i:i + batch_size]
        for d in customer_group_fetch:
            when_then = []
            for customer in batch_customers:
                value = frappe.db.escape(
                    frappe.as_unicode(customer.get("customer_group")))

                when_then.append('''
					WHEN `%s` = "%s" and %s != "%s"
					THEN "%s"
				''' % (d["master_fieldname"],
                frappe.db.escape(frappe.as_unicode(
                customer.name)), d["linked_to_fieldname"], value, value))

            frappe.db.sql("""
				update
					`tab%s`
				set
					%s = CASE %s  ELSE `%s` END
			""" % (d['doctype'], d.linked_to_fieldname, " ".join(when_then),
            d.linked_to_fieldname))
Ejemplo n.º 5
0
    def create_new_parent(self, communication, email):
        '''If no parent found, create a new reference document'''

        # no parent found, but must be tagged
        # insert parent type doc
        parent = frappe.new_doc(self.append_to)

        if self.subject_field:
            parent.set(self.subject_field,
                       frappe.as_unicode(email.subject)[:140])

        if self.sender_field:
            parent.set(self.sender_field, frappe.as_unicode(email.from_email))

        if parent.meta.has_field("email_account"):
            parent.email_account = self.name

        parent.flags.ignore_mandatory = True

        try:
            parent.insert(ignore_permissions=True)
        except frappe.DuplicateEntryError:
            # try and find matching parent
            parent_name = frappe.db.get_value(
                self.append_to, {self.sender_field: email.from_email})
            if parent_name:
                parent.name = parent_name
            else:
                parent = None

        # NOTE if parent isn't found and there's no subject match, it is likely that it is a new conversation thread and hence is_first = True
        communication.is_first = True

        return parent
Ejemplo n.º 6
0
	def create_new_parent(self, communication, email):
		'''If no parent found, create a new reference document'''

		# no parent found, but must be tagged
		# insert parent type doc
		parent = frappe.new_doc(self.append_to)

		if self.subject_field:
			parent.set(self.subject_field, frappe.as_unicode(email.subject))

		if self.sender_field:
			parent.set(self.sender_field, frappe.as_unicode(email.from_email))

		parent.flags.ignore_mandatory = True

		try:
			parent.insert(ignore_permissions=True)
		except frappe.DuplicateEntryError:
			# try and find matching parent
			parent_name = frappe.db.get_value(self.append_to, {self.sender_field: email.from_email})
			if parent_name:
				parent.name = parent_name
			else:
				parent = None

		# NOTE if parent isn't found and there's no subject match, it is likely that it is a new conversation thread and hence is_first = True
		communication.is_first = True

		return parent
Ejemplo n.º 7
0
	def test_base_template(self):
		content = get_page_content('/_test/_test_custom_base.html')

		# assert the text in base template is rendered
		self.assertTrue('<h1>This is for testing</h1>' in frappe.as_unicode(content))

		# assert template block rendered
		self.assertTrue('<p>Test content</p>' in frappe.as_unicode(content))
Ejemplo n.º 8
0
def login():
	# LDAP LOGIN LOGIC
	args = frappe.form_dict
	user = authenticate_ldap_user(frappe.as_unicode(args.usr), frappe.as_unicode(args.pwd))

	frappe.local.login_manager.user = user.name
	frappe.local.login_manager.post_login()

	# because of a GET request!
	frappe.db.commit()
Ejemplo n.º 9
0
def login():
	#### LDAP LOGIN LOGIC #####
	args = frappe.form_dict
	user = authenticate_ldap_user(frappe.as_unicode(args.usr), frappe.as_unicode(args.pwd))

	frappe.local.login_manager.user = user.name
	frappe.local.login_manager.post_login()

	# because of a GET request!
	frappe.db.commit()
Ejemplo n.º 10
0
def employee_shift(work_shift):
    count = 0
    employees = frappe.get_all("Employee",
                               fields=["name", "work_shift"],
                               filters={'status': 'Active'})
    for emp in employees:
        ws = emp.work_shift
        if ws and frappe.as_unicode(work_shift.strip()) == frappe.as_unicode(
                emp.work_shift.strip()):
            count += 1
    return count
Ejemplo n.º 11
0
def login():
    # LDAP LOGIN LOGIC
    args = frappe.form_dict
    ldap = frappe.get_doc("LDAP Settings")

    user = ldap.authenticate(frappe.as_unicode(args.usr),
                             frappe.as_unicode(args.pwd))

    frappe.local.login_manager.user = user.name
    frappe.local.login_manager.post_login()

    # because of a GET request!
    frappe.db.commit()
Ejemplo n.º 12
0
	def escape(self, s, percent=True):
		"""Excape quotes and percent in given string."""
		# pymysql expects unicode argument to escape_string with Python 3
		s = as_unicode(pymysql.escape_string(as_unicode(s)), "utf-8").replace("`", "\\`")

		# NOTE separating % escape, because % escape should only be done when using LIKE operator
		# or when you use python format string to generate query that already has a %s
		# for example: sql("select name from `tabUser` where name=%s and {0}".format(conditions), something)
		# defaulting it to True, as this is the most frequent use case
		# ideally we shouldn't have to use ESCAPE and strive to pass values via the values argument of sql
		if percent:
			s = s.replace("%", "%%")

		return s
Ejemplo n.º 13
0
	def escape(s, percent=True):
		"""Excape quotes and percent in given string."""
		# pymysql expects unicode argument to escape_string with Python 3
		s = frappe.as_unicode(pymysql.escape_string(frappe.as_unicode(s)), "utf-8").replace("`", "\\`")

		# NOTE separating % escape, because % escape should only be done when using LIKE operator
		# or when you use python format string to generate query that already has a %s
		# for example: sql("select name from `tabUser` where name=%s and {0}".format(conditions), something)
		# defaulting it to True, as this is the most frequent use case
		# ideally we shouldn't have to use ESCAPE and strive to pass values via the values argument of sql
		if percent:
			s = s.replace("%", "%%")

		return "'" + s + "'"
Ejemplo n.º 14
0
	def find_parent_based_on_subject_and_sender(self, communication, email):
		'''Find parent document based on subject and sender match'''
		parent = None

		if self.append_to and self.sender_field:
			if self.subject_field:
				# try and match by subject and sender
				# if sent by same sender with same subject,
				# append it to old coversation
				subject = frappe.as_unicode(strip(re.sub("(^\s*(Fw|FW|fwd)[^:]*:|\s*(Re|RE)[^:]*:\s*)*",
					"", email.subject)))

				parent = frappe.db.get_all(self.append_to, filters={
					self.sender_field: email.from_email,
					self.subject_field: ("like", "%{0}%".format(subject)),
					"creation": (">", (get_datetime() - relativedelta(days=10)).strftime(DATE_FORMAT))
				}, fields="name")

				# match only subject field
				# when the from_email is of a user in the system
				# and subject is atleast 10 chars long
				if not parent and len(subject) > 10 and is_system_user(email.from_email):
					parent = frappe.db.get_all(self.append_to, filters={
						self.subject_field: ("like", "%{0}%".format(subject)),
						"creation": (">", (get_datetime() - relativedelta(days=10)).strftime(DATE_FORMAT))
					}, fields="name")

			if parent:
				parent = frappe._dict(doctype=self.append_to, name=parent[0].name)
				return parent
Ejemplo n.º 15
0
def extract_messages_from_code(code):
    """
	Extracts translatable strings from a code file
	:param code: code from which translatable files are to be extracted
	:param is_py: include messages in triple quotes e.g. `_('''message''')`
	"""
    from jinja2 import TemplateError

    try:
        code = frappe.as_unicode(render_include(code))

    # Exception will occur when it encounters John Resig's microtemplating code
    except (TemplateError, ImportError, InvalidIncludePath, IOError) as e:
        if isinstance(e, InvalidIncludePath):
            frappe.clear_last_message()

        pass

    messages = []

    for m in TRANSLATE_PATTERN.finditer(code):
        message = m.group("message")
        context = m.group("py_context") or m.group("js_context")
        pos = m.start()

        if is_translatable(message):
            messages.append([pos, message, context])

    return add_line_number(messages, code)
Ejemplo n.º 16
0
def make_boilerplate(template, doc, opts=None):
    target_path = get_doc_path(doc.module, doc.doctype, doc.name)
    template_name = template.replace("controller", scrub(doc.name))
    if template_name.endswith('._py'):
        template_name = template_name[:-4] + '.py'
    target_file_path = os.path.join(target_path, template_name)

    if not doc: doc = {}

    app_publisher = get_app_publisher(doc.module)

    if not os.path.exists(target_file_path):
        if not opts:
            opts = {}

        with open(target_file_path, 'w') as target:
            with open(
                    os.path.join(get_module_path("core"), "doctype",
                                 scrub(doc.doctype), "boilerplate", template),
                    'r') as source:
                target.write(
                    frappe.as_unicode(
                        frappe.utils.cstr(source.read()).format(
                            app_publisher=app_publisher,
                            year=frappe.utils.nowdate()[:4],
                            classname=doc.name.replace(" ", ""),
                            doctype=doc.name,
                            **opts)))
Ejemplo n.º 17
0
def extract_messages_from_code(code, is_py=False):
    """Extracts translatable srings from a code file

	:param code: code from which translatable files are to be extracted
	:param is_py: include messages in triple quotes e.g. `_('''message''')`"""
    try:
        code = frappe.as_unicode(render_include(code))
    except (TemplateError, ImportError, InvalidIncludePath, IOError):
        # Exception will occur when it encounters John Resig's microtemplating code
        pass

    messages = []
    messages += [(m.start(), m.groups()[0])
                 for m in re.compile('_\("([^"]*)"').finditer(code)]
    messages += [(m.start(), m.groups()[0])
                 for m in re.compile("_\('([^']*)'").finditer(code)]
    if is_py:
        messages += [
            (m.start(), m.groups()[0])
            for m in re.compile('_\("{3}([^"]*)"{3}.*\)').finditer(code)
        ]

    messages = [(pos, message) for pos, message in messages
                if is_translatable(message)]
    return pos_to_line_no(messages, code)
Ejemplo n.º 18
0
def get_value(doctype, fieldname, filters=None, as_dict=True, debug=False, parent=None):
	'''Returns a value form a document

	:param doctype: DocType to be queried
	:param fieldname: Field to be returned (default `name`)
	:param filters: dict or string for identifying the record'''
	if frappe.is_table(doctype):
		check_parent_permission(parent, doctype)

	if not frappe.has_permission(doctype):
		frappe.throw(_("No permission for {0}".format(doctype)), frappe.PermissionError)

	try:
		filters = json.loads(filters)

		if isinstance(filters, (integer_types, float)):
			filters = frappe.as_unicode(filters)

	except (TypeError, ValueError):
		# filters are not passesd, not json
		pass

	try:
		fieldname = json.loads(fieldname)
	except (TypeError, ValueError):
		# name passed, not json
		pass

	# check whether the used filters were really parseable and usable
	# and did not just result in an empty string or dict
	if not filters:
		filters = None

	return frappe.db.get_value(doctype, filters, fieldname, as_dict=as_dict, debug=debug)
Ejemplo n.º 19
0
def get_chart(chart_template, existing_company=None):
	chart = {}
	if existing_company:
		return get_account_tree_from_existing_company(existing_company)
	
	elif chart_template == "Standard":
		from erpnext.accounts.doctype.account.chart_of_accounts.verified import standard_chart_of_accounts
		return standard_chart_of_accounts.get()
	elif chart_template == "Standard with Numbers":
		from erpnext.accounts.doctype.account.chart_of_accounts.verified \
			import standard_chart_of_accounts_with_account_number
		return standard_chart_of_accounts_with_account_number.get()
	else:
		folders = ("verified",)
		if frappe.local.flags.allow_unverified_charts:
			folders = ("verified", "unverified")
		for folder in folders:
			path = os.path.join(os.path.dirname(__file__), folder)
			for fname in os.listdir(path):
				fname = frappe.as_unicode(fname)
				if fname.endswith(".json"):
					with open(os.path.join(path, fname), "r") as f:
						chart = f.read()
						if chart and json.loads(chart).get("name") == chart_template:
							return json.loads(chart).get("tree")
Ejemplo n.º 20
0
def get_charts_for_country(country, with_standard=False):
	charts = []

	def _get_chart_name(content):
		if content:
			content = json.loads(content)
			if (content and content.get("disabled", "No") == "No") \
				or frappe.local.flags.allow_unverified_charts:
					charts.append(content["name"])

	country_code = frappe.db.get_value("Country", country, "code")
	if country_code:
		folders = ("verified",)
		if frappe.local.flags.allow_unverified_charts:
			folders = ("verified", "unverified")

		for folder in folders:
			path = os.path.join(os.path.dirname(__file__), folder)

			for fname in os.listdir(path):
				fname = frappe.as_unicode(fname)
				if (fname.startswith(country_code) or fname.startswith(country)) and fname.endswith(".json"):
					with open(os.path.join(path, fname), "r") as f:
						_get_chart_name(f.read())

	if len(charts) != 1 or with_standard:
		charts += ["Standard", "Standard with Numbers"]

	return charts
Ejemplo n.º 21
0
def get_chart(chart_template, existing_company=None):
    chart = {}
    if existing_company:
        return get_account_tree_from_existing_company(existing_company)

    elif chart_template == "Standard":
        from erpnext.accounts.doctype.account.chart_of_accounts.verified import standard_chart_of_accounts
        return standard_chart_of_accounts.get()
    elif chart_template == "Standard with Numbers":
        from erpnext.accounts.doctype.account.chart_of_accounts.verified \
         import standard_chart_of_accounts_with_account_number
        return standard_chart_of_accounts_with_account_number.get()
    else:
        folders = ("verified", )
        if frappe.local.flags.allow_unverified_charts:
            folders = ("verified", "unverified")
        for folder in folders:
            path = os.path.join(os.path.dirname(__file__), folder)
            for fname in os.listdir(path):
                fname = frappe.as_unicode(fname)
                if fname.endswith(".json"):
                    with open(os.path.join(path, fname), "r") as f:
                        chart = f.read()
                        if chart and json.loads(chart).get(
                                "name") == chart_template:
                            return json.loads(chart).get("tree")
Ejemplo n.º 22
0
def make_boilerplate(template, doc, opts=None):
    target_path = get_doc_path(doc.module, doc.doctype, doc.name)
    template_name = template.replace("controller", scrub(doc.name))
    if template_name.endswith("._py"):
        template_name = template_name[:-4] + ".py"
    target_file_path = os.path.join(target_path, template_name)

    if not doc:
        doc = {}

    app_publisher = get_app_publisher(doc.module)

    if not os.path.exists(target_file_path):
        if not opts:
            opts = {}

        base_class = "Document"
        base_class_import = "from frappe.model.document import Document"
        if doc.get("is_tree"):
            base_class = "NestedSet"
            base_class_import = "from frappe.utils.nestedset import NestedSet"

        custom_controller = "pass"
        if doc.get("is_virtual"):
            custom_controller = """
	def db_insert(self):
		pass

	def load_from_db(self):
		pass

	def db_update(self):
		pass

	def get_list(self, args):
		pass

	def get_count(self, args):
		pass

	def get_stats(self, args):
		pass"""

        with open(target_file_path, "w") as target:
            with open(
                    os.path.join(get_module_path("core"), "doctype",
                                 scrub(doc.doctype), "boilerplate", template),
                    "r",
            ) as source:
                target.write(
                    frappe.as_unicode(
                        frappe.utils.cstr(source.read()).format(
                            app_publisher=app_publisher,
                            year=frappe.utils.nowdate()[:4],
                            classname=doc.name.replace(" ", ""),
                            base_class_import=base_class_import,
                            base_class=base_class,
                            doctype=doc.name,
                            **opts,
                            custom_controller=custom_controller)))
Ejemplo n.º 23
0
def auth(username=None, password=None):
    username = username or frappe.form_dict.username
    password = password or frappe.form_dict.password
    print('auth', username, password)

    if username == 'root':
        root_password = frappe.db.get_single_value(
            "IOT HDB Settings", "mqtt_root_password") or 'bXF0dF9pb3RfYWRtaW4K'
        if password == root_password:
            return http_200ok()
        else:
            return http_403("Auth Error")
    else:
        sid = frappe.db.get_single_value(
            "IOT HDB Settings",
            "mqtt_device_password_sid") or 'ZGV2aWNlIGlkCg=='
        m = hashlib.md5()
        m.update(frappe.as_unicode(username + sid).encode('utf-8'))
        if password == m.hexdigest():
            # TODO: for the one which is not in IOT Device should we check the frappe-make module to see if it is our device?
            if frappe.get_value("IOT Device", username, "enabled") == 1:
                return http_200ok()
            else:
                return http_403("Auth Error")
        else:
            try:
                frappe.local.login_manager.authenticate(username, password)
                if frappe.local.login_manager.user == username:
                    return http_200ok()
                else:
                    return http_403("Auth Error")
            except Exception as ex:
                return http_403("Auth Error")

    return http_403("Auth Error")
Ejemplo n.º 24
0
def handle_html(data):
	# return if no html tags found
	data = frappe.as_unicode(data)

	if '<' not in data:
		return data
	if '>' not in data:
		return data

	from html2text import HTML2Text

	h = HTML2Text()
	h.unicode_snob = True
	h = h.unescape(data or "")

	obj = HTML2Text()
	obj.ignore_links = True
	obj.body_width = 0

	try:
		value = obj.handle(h)
	except Exception:
		# unable to parse html, send it raw
		return value

	value = ", ".join(value.split('  \n'))
	value = " ".join(value.split('\n'))
	value = ", ".join(value.split('# '))

	return value
Ejemplo n.º 25
0
def login():
	# LDAP LOGIN LOGIC
	args = frappe.form_dict
	ldap = frappe.get_doc("LDAP Settings")

	user = ldap.authenticate(frappe.as_unicode(args.usr), frappe.as_unicode(args.pwd))

	frappe.local.login_manager.user = user.name
	if should_run_2fa(user.name):
		authenticate_for_2factor(user.name)
		if not confirm_otp_token(frappe.local.login_manager):
			return False
	frappe.local.login_manager.post_login()

	# because of a GET request!
	frappe.db.commit()
Ejemplo n.º 26
0
def handle_html(data):
    from html2text import HTML2Text

    # return if no html tags found
    data = frappe.as_unicode(data)

    if "<" not in data or ">" not in data:
        return data

    h = unescape_html(data or "")

    obj = HTML2Text()
    obj.ignore_links = True
    obj.body_width = 0

    try:
        value = obj.handle(h)
    except Exception:
        # unable to parse html, send it raw
        return data

    value = ", ".join(value.split("  \n"))
    value = " ".join(value.split("\n"))
    value = ", ".join(value.split("# "))

    return value
Ejemplo n.º 27
0
def get_charts_for_country(country, with_standard=False):
    charts = []

    def _get_chart_name(content):
        if content:
            content = json.loads(content)
            if (content and content.get("disabled", "No") == "No") \
             or frappe.local.flags.allow_unverified_charts:
                charts.append(content["name"])

    country_code = frappe.db.get_value("Country", country, "code")
    if country_code:
        folders = ("verified", )
        if frappe.local.flags.allow_unverified_charts:
            folders = ("verified", "unverified")

        for folder in folders:
            path = os.path.join(os.path.dirname(__file__), folder)

            for fname in os.listdir(path):
                fname = frappe.as_unicode(fname)
                if (fname.startswith(country_code) or
                        fname.startswith(country)) and fname.endswith(".json"):
                    with open(os.path.join(path, fname), "r") as f:
                        _get_chart_name(f.read())

    if len(charts) != 1 or with_standard:
        charts += ["Standard", "Standard with Numbers"]

    return charts
Ejemplo n.º 28
0
def extract_messages_from_code(code):
	"""
		Extracts translatable strings from a code file
		:param code: code from which translatable files are to be extracted
		:param is_py: include messages in triple quotes e.g. `_('''message''')`
	"""
	from jinja2 import TemplateError

	try:
		code = frappe.as_unicode(render_include(code))
	except (TemplateError, ImportError, InvalidIncludePath, IOError):
		# Exception will occur when it encounters John Resig's microtemplating code
		pass

	messages = []
	pattern = r"_\(([\"']{,3})(?P<message>((?!\1).)*)\1(\s*,\s*context\s*=\s*([\"'])(?P<py_context>((?!\5).)*)\5)*(\s*,\s*(.)*?\s*(,\s*([\"'])(?P<js_context>((?!\11).)*)\11)*)*\)"

	for m in re.compile(pattern).finditer(code):
		message = m.group('message')
		context = m.group('py_context') or m.group('js_context')
		pos = m.start()

		if is_translatable(message):
			messages.append([pos, message, context])

	return add_line_number(messages, code)
Ejemplo n.º 29
0
def make_boilerplate(template, doc, opts=None):
	target_path = get_doc_path(doc.module, doc.doctype, doc.name)
	template_name = template.replace("controller", scrub(doc.name))
	if template_name.endswith('._py'):
		template_name = template_name[:-4] + '.py'
	target_file_path = os.path.join(target_path, template_name)

	if not doc: doc = {}

	app_publisher = get_app_publisher(doc.module)

	if not os.path.exists(target_file_path):
		if not opts:
			opts = {}

		with open(target_file_path, 'w') as target:
			with open(os.path.join(get_module_path("core"), "doctype", scrub(doc.doctype),
				"boilerplate", template), 'r') as source:
				target.write(frappe.as_unicode(
					frappe.utils.cstr(source.read()).format(
						app_publisher=app_publisher,
						year=frappe.utils.nowdate()[:4],
						classname=doc.name.replace(" ", ""),
						doctype=doc.name, **opts)
				))
Ejemplo n.º 30
0
	def update_app_details(self):
		pkg_info_file = os.path.join('..', 'apps', self.app_name, '{app_name}.egg-info'.format(app_name=self.app_name), 'PKG-INFO')
		if os.path.isfile(pkg_info_file):
			app_data_path = pkg_info_file
			with open(app_data_path, 'r') as f:
				app_data = f.readlines()
			app_data = frappe.as_unicode(''.join(app_data)).split('\n')
			if '' in app_data:
				app_data.remove('')
			app_data = [x+'\n' for x in app_data]
			for data in app_data:
				if 'Version:' in data:
					self.version = ''.join(re.findall('Version: (.*?)\\n', data))
				elif 'Summary:' in data:
					self.app_description = ''.join(re.findall('Summary: (.*?)\\n', data))
				elif 'Author:' in data:
					self.app_publisher = ''.join(re.findall('Author: (.*?)\\n', data))
				elif 'Author-email:' in data:
					self.app_email = ''.join(re.findall('Author-email: (.*?)\\n', data))
			self.app_title = self.app_name
			self.app_title = self.app_title.replace('-', ' ')
			self.app_title = self.app_title.replace('_', ' ')
			if os.path.isdir(os.path.join('..', 'apps', self.app_name, '.git')):
				self.current_git_branch = safe_decode(check_output("git rev-parse --abbrev-ref HEAD".split(),
					cwd=os.path.join('..', 'apps', self.app_name))).strip('\n')
				self.is_git_repo = True
			else:
				self.current_git_branch = None
				self.is_git_repo = False
		else:
			frappe.throw("Hey developer, the app you're trying to create an \
				instance of doesn't actually exist. You could consider setting \
				developer flag to 0 to actually create the app")
Ejemplo n.º 31
0
def handle_html(data):
    # return if no html tags found
    data = frappe.as_unicode(data)

    if '<' not in data:
        return data
    if '>' not in data:
        return data

    from html2text import HTML2Text

    h = HTML2Text()
    h.unicode_snob = True
    h = h.unescape(data or "")

    obj = HTML2Text()
    obj.ignore_links = True
    obj.body_width = 0

    try:
        value = obj.handle(h)
    except Exception:
        # unable to parse html, send it raw
        return data

    value = ", ".join(value.split('  \n'))
    value = " ".join(value.split('\n'))
    value = ", ".join(value.split('# '))

    return value
Ejemplo n.º 32
0
	def find_parent_based_on_subject_and_sender(self, communication, email):
		'''Find parent document based on subject and sender match'''
		parent = None

		if self.append_to and self.sender_field:
			if self.subject_field:
				# try and match by subject and sender
				# if sent by same sender with same subject,
				# append it to old coversation
				subject = frappe.as_unicode(strip(re.sub(r"(^\s*(fw|fwd|wg)[^:]*:|\s*(re|aw)[^:]*:\s*)*",
					"", email.subject, 0, flags=re.IGNORECASE)))

				parent = frappe.db.get_all(self.append_to, filters={
					self.sender_field: email.from_email,
					self.subject_field: ("like", "%{0}%".format(subject)),
					"creation": (">", (get_datetime() - relativedelta(days=60)).strftime(DATE_FORMAT))
				}, fields="name")

				# match only subject field
				# when the from_email is of a user in the system
				# and subject is atleast 10 chars long
				if not parent and len(subject) > 10 and is_system_user(email.from_email):
					parent = frappe.db.get_all(self.append_to, filters={
						self.subject_field: ("like", "%{0}%".format(subject)),
						"creation": (">", (get_datetime() - relativedelta(days=60)).strftime(DATE_FORMAT))
					}, fields="name")

			if parent:
				parent = frappe._dict(doctype=self.append_to, name=parent[0].name)
				return parent
Ejemplo n.º 33
0
def make_boilerplate(template, doc, opts=None):
	target_path = get_doc_path(doc.module, doc.doctype, doc.name)
	template_name = template.replace("controller", scrub(doc.name))
	if template_name.endswith('._py'):
		template_name = template_name[:-4] + '.py'
	target_file_path = os.path.join(target_path, template_name)

	if not doc: doc = {}

	app_publisher = get_app_publisher(doc.module)

	if not os.path.exists(target_file_path):
		if not opts:
			opts = {}

		base_class = 'Document'
		base_class_import = 'from frappe.model.document import Document'
		if doc.get('is_tree'):
			base_class = 'NestedSet'
			base_class_import = 'from frappe.utils.nestedset import NestedSet'

		with open(target_file_path, 'w') as target:
			with open(os.path.join(get_module_path("core"), "doctype", scrub(doc.doctype),
				"boilerplate", template), 'r') as source:
				target.write(frappe.as_unicode(
					frappe.utils.cstr(source.read()).format(
						app_publisher=app_publisher,
						year=frappe.utils.nowdate()[:4],
						classname=doc.name.replace(" ", ""),
						base_class_import=base_class_import,
						base_class=base_class,
						doctype=doc.name, **opts)
				))
Ejemplo n.º 34
0
def export_query():
    """export from report builder"""
    form_params = get_form_params()
    form_params["limit_page_length"] = None
    form_params["as_list"] = True
    doctype = form_params.doctype
    add_totals_row = None
    file_format_type = form_params["file_format_type"]

    del form_params["doctype"]
    del form_params["file_format_type"]

    if 'add_totals_row' in form_params and form_params['add_totals_row'] == '1':
        add_totals_row = 1
        del form_params["add_totals_row"]

    frappe.permissions.can_export(doctype, raise_exception=True)

    if 'selected_items' in form_params:
        si = json.loads(frappe.form_dict.get('selected_items'))
        form_params["filters"] = {"name": ("in", si)}
        del form_params["selected_items"]

    db_query = DatabaseQuery(doctype)
    ret = db_query.execute(**form_params)

    if add_totals_row:
        ret = append_totals_row(ret)

    data = [['Sr'] + get_labels(db_query.fields, doctype)]
    for i, row in enumerate(ret):
        data.append([i + 1] + list(row))

    if file_format_type == "CSV":

        # convert to csv
        import csv
        from frappe.utils.xlsxutils import handle_html

        f = StringIO()
        writer = csv.writer(f)
        for r in data:
            # encode only unicode type strings and not int, floats etc.
            writer.writerow([handle_html(frappe.as_unicode(v)).encode('utf-8') \
             if isinstance(v, string_types) else v for v in r])

        f.seek(0)
        frappe.response['result'] = text_type(f.read(), 'utf-8')
        frappe.response['type'] = 'csv'
        frappe.response['doctype'] = doctype

    elif file_format_type == "Excel":

        from frappe.utils.xlsxutils import make_xlsx
        xlsx_file = make_xlsx(data, doctype)

        frappe.response['filename'] = doctype + '.xlsx'
        frappe.response['filecontent'] = xlsx_file.getvalue()
        frappe.response['type'] = 'binary'
Ejemplo n.º 35
0
def export_query():
	"""export from report builder"""
	form_params = get_form_params()
	form_params["limit_page_length"] = None
	form_params["as_list"] = True
	doctype = form_params.doctype
	add_totals_row = None
	file_format_type = form_params["file_format_type"]

	del form_params["doctype"]
	del form_params["file_format_type"]

	if 'add_totals_row' in form_params and form_params['add_totals_row']=='1':
		add_totals_row = 1
		del form_params["add_totals_row"]

	frappe.permissions.can_export(doctype, raise_exception=True)

	if 'selected_items' in form_params:
		si = json.loads(frappe.form_dict.get('selected_items'))
		form_params["filters"] = {"name": ("in", si)}
		del form_params["selected_items"]

	db_query = DatabaseQuery(doctype)
	ret = db_query.execute(**form_params)

	if add_totals_row:
		ret = append_totals_row(ret)

	data = [['Sr'] + get_labels(db_query.fields, doctype)]
	for i, row in enumerate(ret):
		data.append([i+1] + list(row))

	if file_format_type == "CSV":

		# convert to csv
		import csv
		from frappe.utils.xlsxutils import handle_html

		f = StringIO()
		writer = csv.writer(f)
		for r in data:
			# encode only unicode type strings and not int, floats etc.
			writer.writerow([handle_html(frappe.as_unicode(v)).encode('utf-8') \
				if isinstance(v, string_types) else v for v in r])

		f.seek(0)
		frappe.response['result'] = text_type(f.read(), 'utf-8')
		frappe.response['type'] = 'csv'
		frappe.response['doctype'] = doctype

	elif file_format_type == "Excel":

		from frappe.utils.xlsxutils import make_xlsx
		xlsx_file = make_xlsx(data, doctype)

		frappe.response['filename'] = doctype + '.xlsx'
		frappe.response['filecontent'] = xlsx_file.getvalue()
		frappe.response['type'] = 'binary'
Ejemplo n.º 36
0
def clean_script_and_style(html):
	# remove script and style
	from bs4 import BeautifulSoup

	soup = BeautifulSoup(html, 'html5lib')
	for s in soup(['script', 'style']):
		s.decompose()
	return frappe.as_unicode(soup)
Ejemplo n.º 37
0
def clean_script_and_style(html):
    # remove script and style
    from bs4 import BeautifulSoup

    soup = BeautifulSoup(html, "html5lib")
    for s in soup(["script", "style"]):
        s.decompose()
    return frappe.as_unicode(soup)
Ejemplo n.º 38
0
	def decode_email(self, email):
		if not email: return
		decoded = ""
		for part, encoding in decode_header(frappe.as_unicode(email).replace("\""," ").replace("\'"," ")):
			if encoding:
				decoded += part.decode(encoding)
			else:
				decoded += safe_decode(part)
		return decoded
Ejemplo n.º 39
0
	def decode_email(self, email):
		if not email: return
		decoded = ""
		for part, encoding in decode_header(frappe.as_unicode(email).replace("\""," ").replace("\'"," ")):
			if encoding:
				decoded += part.decode(encoding)
			else:
				decoded += safe_decode(part)
		return decoded
Ejemplo n.º 40
0
def authenticate_ldap_user(user=None, password=None):
    dn = None
    params = {}
    settings = get_ldap_settings()

    try:
        import ldap
    except:
        msg = """
			<div>
				{{_("Seems ldap is not installed on system.")}}<br>
				<a href"https://discuss.erpnext.com/t/frappe-v-7-1-beta-ldap-dependancies/15841">{{_("Click here")}}</a>,
					{{_("Guidelines to install ldap dependancies and python")}}
			</div>
		"""
        frappe.throw(msg, title=_("LDAP Not Installed"))

    conn = ldap.initialize(settings.ldap_server_url)

    try:
        try:
            # set TLS settings for secure connection
            if settings.ssl_tls_mode == 'StartTLS':
                conn.set_option(ldap.OPT_X_TLS_DEMAND, True)
                if self.require_trusted_certificate == 'Yes':
                    conn.set_option(ldap.OPT_X_TLS_REQUIRE_CERT,
                                    ldap.OPT_X_TLS_DEMAND)
                conn.start_tls_s()
        except:
            frappe.throw(_("StartTLS is not supported"))

        # simple_bind_s is synchronous binding to server, it takes two param  DN and password
        conn.simple_bind_s(settings.base_dn,
                           settings.get_password(raise_exception=False))

        #search for surnames beginning with a
        #available options for how deep a search you want.
        #LDAP_SCOPE_BASE, LDAP_SCOPE_ONELEVEL,LDAP_SCOPE_SUBTREE,
        result = conn.search_s(settings.organizational_unit,
                               ldap.SCOPE_SUBTREE,
                               settings.ldap_search_string.format(user))

        for dn, r in result:
            dn = cstr(dn)
            params["email"] = cstr(r[settings.ldap_email_field][0])
            params["username"] = cstr(r[settings.ldap_username_field][0])
            params["first_name"] = cstr(r[settings.ldap_first_name_field][0])

        if dn:
            conn.simple_bind_s(dn, frappe.as_unicode(password))
            return create_user(params)
        else:
            frappe.throw(_("Not a valid LDAP user"))

    except ldap.LDAPError:
        conn.unbind_s()
        frappe.throw(_("Incorrect UserId or Password"))
Ejemplo n.º 41
0
	def validate_file(self):
		"""Validates existence of public file
		TODO: validate for private file
		"""
		if (self.file_url or "").startswith("/files/"):
			if not self.file_name:
				self.file_name = self.file_url.split("/files/")[-1]

			if not os.path.exists(get_files_path(frappe.as_unicode(self.file_name.lstrip("/")))):
				frappe.throw(_("File {0} does not exist").format(self.file_url), IOError)
Ejemplo n.º 42
0
	def validate_file(self):
		"""Validates existence of public file
		TODO: validate for private file
		"""
		if (self.file_url or "").startswith("/files/"):
			if not self.file_name:
				self.file_name = self.file_url.split("/files/")[-1]

			if not os.path.exists(get_files_path(frappe.as_unicode(self.file_name.lstrip("/")))):
				frappe.throw(_("File {0} does not exist").format(self.file_url), IOError)
Ejemplo n.º 43
0
def authenticate_ldap_user(user=None, password=None):
	dn = None
	params = {}
	settings = get_ldap_settings()

	try:
		import ldap
	except:
		msg = """
			<div>
				{{_("Seems ldap is not installed on system.")}}<br>
				<a href"https://discuss.erpnext.com/t/frappe-v-7-1-beta-ldap-dependancies/15841">{{_("Click here")}}</a>,
					{{_("Guidelines to install ldap dependancies and python")}}
			</div>
		"""
		frappe.throw(msg, title=_("LDAP Not Installed"))

	conn = ldap.initialize(settings.ldap_server_url)

	try:
		try:
			# set TLS settings for secure connection
			if settings.ssl_tls_mode == 'StartTLS':
				conn.set_option(ldap.OPT_X_TLS_DEMAND, True)
				if settings.require_trusted_certificate == 'Yes':
					conn.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_DEMAND)
				conn.start_tls_s()
		except:
			frappe.throw(_("StartTLS is not supported"))

		# simple_bind_s is synchronous binding to server, it takes two param  DN and password
		conn.simple_bind_s(settings.base_dn, settings.get_password(raise_exception=False))

		#search for surnames beginning with a
		#available options for how deep a search you want.
		#LDAP_SCOPE_BASE, LDAP_SCOPE_ONELEVEL,LDAP_SCOPE_SUBTREE,
		result = conn.search_s(settings.organizational_unit, ldap.SCOPE_SUBTREE,
			settings.ldap_search_string.format(user))

		for dn, r in result:
			dn = cstr(dn)
			params["email"] = cstr(r[settings.ldap_email_field][0])
			params["username"] = cstr(r[settings.ldap_username_field][0])
			params["first_name"] = cstr(r[settings.ldap_first_name_field][0])

		if dn:
			conn.simple_bind_s(dn, frappe.as_unicode(password))
			return create_user(params)
		else:
			frappe.throw(_("Not a valid LDAP user"))

	except ldap.LDAPError:
		conn.unbind_s()
		frappe.throw(_("Incorrect UserId or Password"))
Ejemplo n.º 44
0
def get_safe_filters(filters):
    try:
        filters = json.loads(filters)

        if isinstance(filters, (integer_types, float)):
            filters = frappe.as_unicode(filters)

    except (TypeError, ValueError):
        # filters are not passed, not json
        pass

    return filters
Ejemplo n.º 45
0
def get_server_messages(app):
	"""Extracts all translatable strings (tagged with :func:`frappe._`) from Python modules
		inside an app"""
	messages = []
	for basepath, folders, files in os.walk(frappe.get_pymodule_path(app)):
		for dontwalk in (".git", "public", "locale"):
			if dontwalk in folders: folders.remove(dontwalk)

		for f in files:
			f = frappe.as_unicode(f)
			if f.endswith(".py") or f.endswith(".html") or f.endswith(".js"):
				messages.extend(get_messages_from_file(os.path.join(basepath, f)))

	return messages
Ejemplo n.º 46
0
	def get_email_seen_status(self, uid, flag_string):
		""" parse the email FLAGS response """
		if not flag_string:
			return None

		flags = []
		for flag in imaplib.ParseFlags(flag_string) or []:
			pattern = re.compile("\w+")
			match = re.search(pattern, frappe.as_unicode(flag))
			flags.append(match.group(0))

		if "Seen" in flags:
			self.seen_status.update({ uid: "SEEN" })
		else:
			self.seen_status.update({ uid: "UNSEEN" })
Ejemplo n.º 47
0
def get_page_info_from_template(path):
	'''Return page_info from path'''
	for app in frappe.get_installed_apps(frappe_last=True):
		app_path = frappe.get_app_path(app)

		folders = get_start_folders()

		for start in folders:
			search_path = os.path.join(app_path, start, path)
			options = (search_path, search_path + '.html', search_path + '.md',
				search_path + '/index.html', search_path + '/index.md')
			for o in options:
				option = frappe.as_unicode(o)
				if os.path.exists(option) and not os.path.isdir(option):
					return get_page_info(option, app, start, app_path=app_path)

	return None
Ejemplo n.º 48
0
def add_missing_headers():
	'''Walk and add missing headers in docs (to be called from bench execute)'''
	path = frappe.get_app_path('erpnext', 'docs')
	for basepath, folders, files in os.walk(path):
		for fname in files:
			if fname.endswith('.md'):
				with open(os.path.join(basepath, fname), 'r') as f:
					content = frappe.as_unicode(f.read())

				if not content.startswith('# ') and not '<h1>' in content:
					with open(os.path.join(basepath, fname), 'w') as f:
						if fname=='index.md':
							fname = os.path.basename(basepath)
						else:
							fname = fname[:-3]
						h = fname.replace('_', ' ').replace('-', ' ').title()
						content = '# {0}\n\n'.format(h) + content
						f.write(content.encode('utf-8'))
Ejemplo n.º 49
0
def extract_messages_from_code(code, is_py=False):
	"""Extracts translatable srings from a code file

	:param code: code from which translatable files are to be extracted
	:param is_py: include messages in triple quotes e.g. `_('''message''')`"""
	try:
		code = frappe.as_unicode(render_include(code))
	except (TemplateError, ImportError, InvalidIncludePath):
		# Exception will occur when it encounters John Resig's microtemplating code
		pass

	messages = []
	messages += [(m.start(), m.groups()[0]) for m in re.compile('_\("([^"]*)"').finditer(code)]
	messages += [(m.start(), m.groups()[0]) for m in re.compile("_\('([^']*)'").finditer(code)]
	if is_py:
		messages += [(m.start(), m.groups()[0]) for m in re.compile('_\("{3}([^"]*)"{3}.*\)').finditer(code)]

	messages = [(pos, message) for pos, message in messages if is_translatable(message)]
	return pos_to_line_no(messages, code)
Ejemplo n.º 50
0
def has_gravatar(email):
	'''Returns gravatar url if user has set an avatar at gravatar.com'''
	if (frappe.flags.in_import
		or frappe.flags.in_install
		or frappe.flags.in_test):
		# no gravatar if via upload
		# since querying gravatar for every item will be slow
		return ''

	hexdigest = md5.md5(frappe.as_unicode(email).encode('utf-8')).hexdigest()

	gravatar_url = "https://secure.gravatar.com/avatar/{hash}?d=404&s=200".format(hash=hexdigest)
	try:
		res = requests.get(gravatar_url)
		if res.status_code==200:
			return gravatar_url
		else:
			return ''
	except requests.exceptions.ConnectionError:
		return ''
Ejemplo n.º 51
0
	def _sanitize_content(self):
		"""Sanitize HTML and Email in field values. Used to prevent XSS.

			- Ignore if 'Ignore XSS Filter' is checked or fieldtype is 'Code'
		"""
		if frappe.flags.in_install:
			return

		for fieldname, value in self.get_valid_dict().items():
			if not value or not isinstance(value, string_types):
				continue

			value = frappe.as_unicode(value)

			if (u"<" not in value and u">" not in value):
				# doesn't look like html so no need
				continue

			elif "<!-- markdown -->" in value and not ("<script" in value or "javascript:" in value):
				# should be handled separately via the markdown converter function
				continue

			df = self.meta.get_field(fieldname)
			sanitized_value = value

			if df and df.get("fieldtype") in ("Data", "Code", "Small Text") and df.get("options")=="Email":
				sanitized_value = sanitize_email(value)

			elif df and (df.get("ignore_xss_filter")
						or (df.get("fieldtype")=="Code" and df.get("options")!="Email")
						or df.get("fieldtype") in ("Attach", "Attach Image")

						# cancelled and submit but not update after submit should be ignored
						or self.docstatus==2
						or (self.docstatus==1 and not df.get("allow_on_submit"))):
				continue

			else:
				sanitized_value = sanitize_html(value, linkify=df.fieldtype=='Text Editor')

			self.set(fieldname, sanitized_value)
Ejemplo n.º 52
0
def clean_script_and_style(html):
	# remove script and style
	soup = BeautifulSoup(html, 'html5lib')
	for s in soup(['script', 'style']):
		s.decompose()
	return frappe.as_unicode(soup)
Ejemplo n.º 53
0
def add_breadcrumbs_tag(path):
	with open(path, 'r') as f:
		content = frappe.as_unicode(f.read())
	with open(path, 'wb') as f:
		f.write(('<!-- add-breadcrumbs -->\n' + content).encode('utf-8'))
Ejemplo n.º 54
0
def cstr(s, encoding='utf-8'):
	return frappe.as_unicode(s, encoding)