Example #1
0
	def make_gle_for_change_amount(self, gl_entries):
		if cint(self.is_pos) and self.change_amount:
			if self.account_for_change_amount:
				gl_entries.append(
					self.get_gl_dict({
						"account": self.debit_to,
						"party_type": "Customer",
						"party": self.customer,
						"against": self.account_for_change_amount,
						"debit": flt(self.base_change_amount),
						"debit_in_account_currency": flt(self.base_change_amount) \
							if self.party_account_currency==self.company_currency else flt(self.change_amount),
						"against_voucher": self.return_against if cint(self.is_return) else self.name,
						"against_voucher_type": self.doctype
					}, self.party_account_currency)
				)
				
				gl_entries.append(
					self.get_gl_dict({
						"account": self.account_for_change_amount,
						"against": self.customer,
						"credit": self.base_change_amount
					})
				)
			else:
				frappe.throw(_("Select change amount account"), title="Mandatory Field")
def validate_duplicate(doc,method):
	if doc.get("__islocal"):
		if not doc.invitation_member_details:
			doc.load_participents()
		fdate=doc.from_date.split(" ")
		f_date=fdate[0]
		tdate=doc.to_date.split(" ")
		t_date=tdate[0]
		res=frappe.db.sql("select name from `tabAttendance Record` where (cell='%s' or church='%s') and from_date like '%s%%' and to_date like '%s%%'"%(doc.cell,doc.church,f_date,t_date))
		#frappe.errprint(res)
		if res:
			frappe.throw(_("Attendance Record '{0}' is already created for same details on same date '{1}'").format(res[0][0],f_date))

		if doc.from_date and doc.to_date:
			if doc.from_date >= doc.to_date:
				frappe.throw(_("To Date should be greater than From Date..!"))

		if len(doc.invitation_member_details)<1:
			pass
			#rappe.throw(_("Attendance Member table is empty.There should be at least 1 member in attendance list. Please load members in table."))

		if doc.data_17 and cint(doc.data_17) <= 0 :
				frappe.throw(_("Total Attendance cannot be negative..!"))
		if doc.number_of_first_timers and cint(doc.number_of_first_timers) <= 0 :
				frappe.throw(_("Number of First Timers cannot be negative..!"))
		if doc.data_19 and cint(doc.data_19) <= 0 :
				frappe.throw(_("Number of New Converts cannot be negative..!"))
		if doc.data_20 and cint(doc.data_20) <= 0 :
				frappe.throw(_("Total Cell Offering cannot be negative..!"))
Example #3
0
def add(doctype, name, user=None, read=1, write=0, share=0, flags=None):
	"""Share the given document with a user."""
	if not user:
		user = frappe.session.user

	share_name = frappe.db.get_value("DocShare", {"user": user, "share_name": name,
		"share_doctype": doctype})

	if share_name:
		doc = frappe.get_doc("DocShare", share_name)
	else:
		doc = frappe.new_doc("DocShare")
		doc.update({
			"user": user,
			"share_doctype": doctype,
			"share_name": name
		})

	if flags:
		doc.flags.update(flags)

	doc.update({
		# always add read, since you are adding!
		"read": 1,
		"write": cint(write),
		"share": cint(share)
	})

	doc.save(ignore_permissions=True)

	return doc
Example #4
0
	def make_item_gl_entries(self, gl_entries):
		# income account gl entries
		for item in self.get("items"):
			if flt(item.base_net_amount):
				if item.is_fixed_asset:
					asset = frappe.get_doc("Asset", item.asset)

					fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(asset, item.base_net_amount)
					for gle in fixed_asset_gl_entries:
						gle["against"] = self.customer
						gl_entries.append(self.get_gl_dict(gle))

					asset.db_set("disposal_date", self.posting_date)
					asset.set_status("Sold" if self.docstatus==1 else None)
				else:
					account_currency = get_account_currency(item.income_account)
					gl_entries.append(
						self.get_gl_dict({
							"account": item.income_account,
							"against": self.customer,
							"credit": item.base_net_amount,
							"credit_in_account_currency": item.base_net_amount \
								if account_currency==self.company_currency else item.net_amount,
							"cost_center": item.cost_center,
							"project": self.project,
							"support_ticket": self.support_ticket
						}, account_currency)
					)

		# expense account gl entries
		if cint(frappe.defaults.get_global_default("auto_accounting_for_stock")) \
				and cint(self.update_stock):
			gl_entries += super(SalesInvoice, self).get_gl_entries()
Example #5
0
	def make_pos_gl_entries(self, gl_entries):
		if cint(self.is_pos):
			for payment_mode in self.payments:
				# POS, make payment entries
				gl_entries.append(
					self.get_gl_dict({
						"account": self.debit_to,
						"party_type": "Customer",
						"party": self.customer,
						"against": payment_mode.account,
						"credit": payment_mode.base_amount,
						"credit_in_account_currency": payment_mode.base_amount \
							if self.party_account_currency==self.company_currency \
							else payment_mode.amount,
						"against_voucher": self.return_against if cint(self.is_return) else self.name,
						"against_voucher_type": self.doctype,
					}, self.party_account_currency)
				)

				payment_mode_account_currency = get_account_currency(payment_mode.account)
				gl_entries.append(
					self.get_gl_dict({
						"account": payment_mode.account,
						"against": self.customer,
						"debit": payment_mode.base_amount,
						"debit_in_account_currency": payment_mode.base_amount \
							if payment_mode_account_currency==self.company_currency else payment_mode.amount
					}, payment_mode_account_currency)
				)
	def get_current_tax_amount(self, item, tax, item_tax_map):
		tax_rate = self._get_tax_rate(tax, item_tax_map)
		current_tax_amount = 0.0

		if tax.charge_type == "Actual":
			# distribute the tax amount proportionally to each item row
			actual = flt(tax.rate, self.precision("tax_amount", tax))
			current_tax_amount = (self.net_total
				and ((item.base_amount / self.net_total) * actual)
				or 0)
		elif tax.charge_type == "On Net Total":
			current_tax_amount = (tax_rate / 100.0) * item.base_amount
		elif tax.charge_type == "On Previous Row Amount":
			current_tax_amount = (tax_rate / 100.0) * \
				self.tax_doclist[cint(tax.row_id) - 1].tax_amount_for_current_item
		elif tax.charge_type == "On Previous Row Total":
			current_tax_amount = (tax_rate / 100.0) * \
				self.tax_doclist[cint(tax.row_id) - 1].grand_total_for_current_item

		current_tax_amount = flt(current_tax_amount, self.precision("tax_amount", tax))

		# store tax breakup for each item
		key = item.item_code or item.item_name
		if tax.item_wise_tax_detail.get(key):
			item_wise_tax_amount = tax.item_wise_tax_detail[key][1] + current_tax_amount
			tax.item_wise_tax_detail[key] = [tax_rate,item_wise_tax_amount]
		else:
			tax.item_wise_tax_detail[key] = [tax_rate,current_tax_amount]

		return current_tax_amount
Example #7
0
	def __init__(self, login=None, password=None, server=None, port=None, use_ssl=None):
		# get defaults from mail settings
		try:
			self.email_settings = frappe.get_doc('Outgoing Email Settings', 'Outgoing Email Settings')
		except frappe.DoesNotExistError:
			self.email_settings = None

		self._sess = None
		if server:
			self.server = server
			self.port = port
			self.use_ssl = cint(use_ssl)
			self.login = login
			self.password = password
		elif self.email_settings and cint(self.email_settings.enabled):
			self.server = self.email_settings.mail_server
			self.port = self.email_settings.mail_port
			self.use_ssl = cint(self.email_settings.use_ssl)
			self.login = self.email_settings.mail_login
			self.password = self.email_settings.mail_password
			self.always_use_login_id_as_sender = self.email_settings.always_use_login_id_as_sender
		else:
			self.server = frappe.conf.get("mail_server") or "smtp.exmail.qq.com"
			self.port = frappe.conf.get("mail_port") or 25
			self.use_ssl = cint(frappe.conf.get("use_ssl") or 0)
			self.login = frappe.conf.get("mail_login") or "*****@*****.**"
			self.password = frappe.conf.get("mail_password") or "a1!b1!"
			self.always_use_login_id_as_sender = frappe.conf.get("always_use_login_id_as_sender") or 1
Example #8
0
	def make_pos_gl_entries(self, gl_entries):
		if cint(self.is_pos) and self.cash_bank_account and self.paid_amount:
			bank_account_currency = get_account_currency(self.cash_bank_account)
			# POS, make payment entries
			gl_entries.append(
				self.get_gl_dict({
					"account": self.debit_to,
					"party_type": "Customer",
					"party": self.customer,
					"against": self.cash_bank_account,
					"credit": self.base_paid_amount,
					"credit_in_account_currency": self.base_paid_amount \
						if self.party_account_currency==self.company_currency else self.paid_amount,
					"against_voucher": self.return_against if cint(self.is_return) else self.name,
					"against_voucher_type": self.doctype,
				}, self.party_account_currency)
			)
			gl_entries.append(
				self.get_gl_dict({
					"account": self.cash_bank_account,
					"against": self.customer,
					"debit": self.base_paid_amount,
					"debit_in_account_currency": self.base_paid_amount \
						if bank_account_currency==self.company_currency else self.paid_amount
				}, bank_account_currency)
			)
Example #9
0
	def on_submit(self):
		if cint(self.update_stock) == 1:
			self.update_stock_ledger()
		else:
			# Check for Approving Authority
			if not self.recurring_id:
				frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype,
				 	self.company, self.base_grand_total, self)

		self.check_prev_docstatus()

		if self.is_return:
			# NOTE status updating bypassed for is_return
			self.status_updater = []

		self.update_status_updater_args()
		self.update_prevdoc_status()
		self.update_billing_status_in_dn()

		# this sequence because outstanding may get -ve
		self.make_gl_entries()

		if not self.is_return:
			self.update_billing_status_for_zero_amount_refdoc("Sales Order")
			self.check_credit_limit()

		if not cint(self.is_pos) == 1 and not self.is_return:
			self.update_against_document_in_jv()

		self.update_time_log_batch(self.name)
Example #10
0
	def validate(self):
		super(SalesInvoice, self).validate()
		self.validate_posting_time()
		self.so_dn_required()
		self.validate_proj_cust()
		self.validate_with_previous_doc()
		self.validate_uom_is_integer("stock_uom", "qty")
		self.check_close_sales_order("sales_order")
		self.validate_debit_to_acc()
		self.validate_fixed_asset_account()
		self.clear_unallocated_advances("Sales Invoice Advance", "advances")
		self.validate_advance_jv("Sales Order")
		self.add_remarks()
		self.validate_write_off_account()

		if cint(self.is_pos):
			self.validate_pos()

		if cint(self.update_stock):
			self.validate_dropship_item()
			self.validate_item_code()
			self.validate_warehouse()
			self.update_current_stock()
			self.validate_delivery_note()

		if not self.is_opening:
			self.is_opening = 'No'

		self.set_against_income_account()
		self.validate_c_form()
		self.validate_time_logs_are_submitted()
		self.validate_multiple_billing("Delivery Note", "dn_detail", "amount", "items")
		self.update_packing_list()
Example #11
0
	def make_item_gl_entries(self, gl_entries):
		# income account gl entries
		for item in self.get("items"):
			if flt(item.base_net_amount):
				account_currency = get_account_currency(item.income_account)
				account_report_type = frappe.db.get_value("Account", item.income_account, "report_type")
				if account_report_type == "Profit and Loss":
					project_name=self.project
					support_ticket=self.support_ticket
				else:
					project_name=''
					support_ticket=''

				gl_entries.append(
					self.get_gl_dict({
						"account": item.income_account,
						"against": self.customer,
						"credit": item.base_net_amount,
						"credit_in_account_currency": item.base_net_amount \
							if account_currency==self.company_currency else item.net_amount,
						"cost_center": item.cost_center,
                        			"project_name": project_name,
						"support_ticket": support_ticket
					}, account_currency)
				)

		# expense account gl entries
		if cint(frappe.defaults.get_global_default("auto_accounting_for_stock")) \
				and cint(self.update_stock):
			gl_entries += super(SalesInvoice, self).get_gl_entries()
Example #12
0
def get_next_dep_date(doc, dep_freq, tot_dep):
	#Next depreciation date shoud be last date of the purchase date if monthly or last date
	#of period of depreciation
	#if monthly depreciation then last day or month, if bi-monthly then last day of month+1
	#if 3 monthly then last day of quarter and not 3 months
	#if 4 monthly then last day of third and not 4 months and so on and so forth
	fy_doc = get_fy_doc(doc)
	r = relativedelta.relativedelta(add_days(fy_doc.year_end_date,1), fy_doc.year_start_date)
	fy_months = r.years*12 + r.months
	dep_in_fy = cint(fy_months)/flt(dep_freq)
	booked_deps_months = (cint(doc.number_of_depreciations_booked)*cint(dep_freq))
	last_day = add_months(get_last_day(doc.purchase_date), booked_deps_months)
	base_last_day = get_last_day(doc.purchase_date)
	base_dep_date = None
	if dep_in_fy >= 1 and dep_in_fy % 1  == 0:
		for i in range(0, cint(tot_dep)):
			dep_date = get_last_day(add_months(fy_doc.year_start_date, (i*dep_freq -1)))
			if base_last_day <= dep_date and base_dep_date is None:
				base_dep_date = dep_date

			if last_day <= dep_date:
				doc.next_depreciation_date = dep_date
				break
			else:
				doc.next_depreciation_date = fy_doc.year_end_date
	elif dep_in_fy % 1  != 0:
		frappe.throw('Frequency Causing Depreciations not to be posted equally in FY, \
			please change the frequency of depreciation')
	else:
		frappe.throw('Months between depreciation cannot be less than 1')
	return base_dep_date
def get_field_precision(df, doc=None, currency=None):
	"""get precision based on DocField options and fieldvalue in doc"""
	from frappe.utils import get_number_format_info

	if cint(df.precision):
		precision = cint(df.precision)

	elif df.fieldtype == "Currency":
		number_format = None
		if not currency and doc:
			currency = get_field_currency(df, doc)

		if not currency:
			# use default currency
			currency = frappe.db.get_default("currency")

		if currency:
			number_format = frappe.db.get_value("Currency", currency, "number_format", cache=True)

		if not number_format:
			number_format = frappe.db.get_default("number_format") or "#,###.##"

		decimal_str, comma_str, precision = get_number_format_info(number_format)

	else:
		precision = cint(frappe.db.get_default("float_precision")) or 3

	return precision
Example #14
0
def disable_users(limits=None):
	if not limits:
		return

	if limits.get('users'):
		system_manager = get_system_managers(only_name=True)[-1]

		#exclude system manager from active user list
		active_users =  frappe.db.sql_list("""select name from tabUser
			where name not in ('Administrator', 'Guest', %s) and user_type = 'System User' and enabled=1
			order by creation desc""", system_manager)

		user_limit = cint(limits.get('users')) - 1

		if len(active_users) > user_limit:

			# if allowed user limit 1 then deactivate all additional users
			# else extract additional user from active user list and deactivate them
			if cint(limits.get('users')) != 1:
				active_users = active_users[:-1 * user_limit]

			for user in active_users:
				frappe.db.set_value("User", user, 'enabled', 0)

		from frappe.core.doctype.user.user import get_total_users

		if get_total_users() > cint(limits.get('users')):
			reset_simultaneous_sessions(cint(limits.get('users')))

	frappe.db.commit()
Example #15
0
    def make_item_gl_entries(self, gl_entries):
        # income account gl entries
        adon_added = False
        for item in self.get("items"):
            if flt(item.base_net_amount):
                account_currency = get_account_currency(item.income_account)
                gl_entries.append(
                    self.get_gl_dict(
                        {
                            "account": item.income_account,
                            "against": self.customer,
                            "credit": item.base_net_amount + (flt(self.adon) or 0.0 if not adon_added else 0.0),
                            "credit_in_account_currency": item.base_net_amount
                            if account_currency == self.company_currency
                            else item.net_amount,
                            "cost_center": item.cost_center,
                        },
                        account_currency,
                    )
                )
                # print gl_entries
            adon_added = True

            # expense account gl entries
        if cint(frappe.defaults.get_global_default("auto_accounting_for_stock")) and cint(self.update_stock):
            gl_entries += super(SalesInvoice, self).get_gl_entries()
Example #16
0
	def clear_active_sessions(self):
		"""Clear other sessions of the current user if `deny_multiple_sessions` is not set"""
		if not (cint(frappe.conf.get("deny_multiple_sessions")) or cint(frappe.db.get_system_setting('deny_multiple_sessions'))):
			return

		if frappe.session.user != "Guest":
			clear_sessions(frappe.session.user, keep_current=True)
Example #17
0
	def _validate_length(self):
		if frappe.flags.in_install:
			return

		if self.meta.issingle:
			# single doctype value type is mediumtext
			return

		column_types_to_check_length = ('varchar', 'int', 'bigint')

		for fieldname, value in iteritems(self.get_valid_dict()):
			df = self.meta.get_field(fieldname)

			if not df or df.fieldtype == 'Check':
				# skip standard fields and Check fields
				continue

			column_type = type_map[df.fieldtype][0] or None
			default_column_max_length = type_map[df.fieldtype][1] or None

			if df and df.fieldtype in type_map and column_type in column_types_to_check_length:
				max_length = cint(df.get("length")) or cint(default_column_max_length)

				if len(cstr(value)) > max_length:
					if self.parentfield and self.idx:
						reference = _("{0}, Row {1}").format(_(self.doctype), self.idx)

					else:
						reference = "{0} {1}".format(_(self.doctype), self.name)

					frappe.throw(_("{0}: '{1}' ({3}) will get truncated, as max characters allowed is {2}")\
						.format(reference, _(df.label), max_length, value), frappe.CharacterLengthExceededError, title=_('Value too big'))
Example #18
0
def check_if_within_operating_hours(workstation, operation, from_datetime, to_datetime):
	if from_datetime and to_datetime:
		if not cint(frappe.db.get_value("Manufacturing Settings", "None", "allow_production_on_holidays")):
			check_workstation_for_holiday(workstation, from_datetime, to_datetime)

		if not cint(frappe.db.get_value("Manufacturing Settings", None, "allow_overtime")):
			is_within_operating_hours(workstation, operation, from_datetime, to_datetime)
def get_doc_permissions(doc, verbose=False, user=None):
	"""Returns a dict of evaluated permissions for given `doc` like `{"read":1, "write":1}`"""
	if not user: user = frappe.session.user

	if frappe.is_table(doc.doctype):
		return {"read":1, "write":1}

	meta = frappe.get_meta(doc.doctype)

	role_permissions = copy.deepcopy(get_role_permissions(meta, user=user, verbose=verbose))

	if not cint(meta.is_submittable):
		role_permissions["submit"] = 0

	if not cint(meta.allow_import):
		role_permissions["import"] = 0

	if role_permissions.get("apply_user_permissions"):
		# no user permissions, switch off all user-level permissions
		for ptype in role_permissions:
			if role_permissions["apply_user_permissions"].get(ptype) and not user_has_permission(doc, verbose=verbose, user=user,
		user_permission_doctypes=role_permissions.get("user_permission_doctypes", {}).get(ptype) or []):
				role_permissions[ptype] = 0

	# apply owner permissions on top of existing permissions
	if doc.owner == frappe.session.user:
		role_permissions.update(role_permissions.if_owner)

	update_share_permissions(role_permissions, doc, user)

	return role_permissions
Example #20
0
	def on_update(self):
		if cint(self.update_stock) == 1:
			# Set default warehouse from pos setting
			if cint(self.is_pos) == 1:
				w = self.get_warehouse()
				if w:
					for d in self.get('entries'):
						if not d.warehouse:
							d.warehouse = cstr(w)

			from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
			make_packing_list(self, 'entries')
		else:
			self.set('packing_details', [])

		if cint(self.is_pos) == 1:
			if flt(self.paid_amount) == 0:
				if self.cash_bank_account:
					frappe.db.set(self, 'paid_amount',
						(flt(self.grand_total) - flt(self.write_off_amount)))
				else:
					# show message that the amount is not paid
					frappe.db.set(self,'paid_amount',0)
					frappe.msgprint(_("Note: Payment Entry will not be created since 'Cash or Bank Account' was not specified"))
		else:
			frappe.db.set(self,'paid_amount',0)
Example #21
0
def get_feed(limit_start, limit_page_length, show_likes=False):
	"""get feed"""
	match_conditions = get_feed_match_conditions(frappe.session.user)

	result = frappe.db.sql("""select name, owner, modified, creation, seen, comment_type,
			reference_doctype, reference_name, link_doctype, link_name, subject,
			communication_type, communication_medium, content
		from `tabCommunication`
		where
			communication_type in ("Communication", "Comment")
			and (comment_type is null or comment_type != "Like"
				or (comment_type="Like" and (owner=%(user)s or reference_owner=%(user)s)))
			{match_conditions}
			{show_likes}
		order by creation desc
		limit %(limit_start)s, %(limit_page_length)s"""
		.format(match_conditions="and {0}".format(match_conditions) if match_conditions else "",
			show_likes="and comment_type='Like'" if show_likes else ""),
		{
			"user": frappe.session.user,
			"limit_start": cint(limit_start),
			"limit_page_length": cint(limit_page_length)
		}, as_dict=True)

	if show_likes:
		# mark likes as seen!
		frappe.db.sql("""update `tabCommunication` set seen=1
			where comment_type='Like' and reference_owner=%s""", frappe.session.user)
		frappe.local.flags.commit = True

	return result
Example #22
0
def test_password_strength(new_password, key=None, old_password=None, user_data=[]):
	from frappe.utils.password_strength import test_password_strength as _test_password_strength

	password_policy = frappe.db.get_value("System Settings", None,
		["enable_password_policy", "minimum_password_score"], as_dict=True) or {}

	enable_password_policy = cint(password_policy.get("enable_password_policy", 0))
	minimum_password_score = cint(password_policy.get("minimum_password_score", 0))

	if not enable_password_policy:
		return {}

	if not user_data:
		user_data = frappe.db.get_value('User', frappe.session.user,
			['first_name', 'middle_name', 'last_name', 'email', 'birth_date'])

	if new_password:
		result = _test_password_strength(new_password, user_inputs=user_data)
		password_policy_validation_passed = False

		# score should be greater than 0 and minimum_password_score
		if result.get('score') and result.get('score') >= minimum_password_score:
			password_policy_validation_passed = True

		result['feedback']['password_policy_validation_passed'] = password_policy_validation_passed
		return result
Example #23
0
	def get_valid_dict(self, sanitize=True):
		d = frappe._dict()
		for fieldname in self.meta.get_valid_columns():
			d[fieldname] = self.get(fieldname)

			# if no need for sanitization and value is None, continue
			if not sanitize and d[fieldname] is None:
				continue

			df = self.meta.get_field(fieldname)
			if df:
				if df.fieldtype=="Check" and (not isinstance(d[fieldname], int) or d[fieldname] > 1):
					d[fieldname] = 1 if cint(d[fieldname]) else 0

				elif df.fieldtype=="Int" and not isinstance(d[fieldname], int):
					d[fieldname] = cint(d[fieldname])

				elif df.fieldtype in ("Currency", "Float", "Percent") and not isinstance(d[fieldname], float):
					d[fieldname] = flt(d[fieldname])

				elif df.fieldtype in ("Datetime", "Date") and d[fieldname]=="":
					d[fieldname] = None

				elif df.get("unique") and cstr(d[fieldname]).strip()=="":
					# unique empty field should be set to None
					d[fieldname] = None

				if isinstance(d[fieldname], list) and df.fieldtype != 'Table':
					frappe.throw(_('Value for {0} cannot be a list').format(_(df.label)))

		return d
Example #24
0
	def add_system_manager_role(self):
		# if adding system manager, do nothing
		if not cint(self.enabled) or ("System Manager" in [user_role.role for user_role in
				self.get("roles")]):
			return

		if (self.name not in STANDARD_USERS and self.user_type == "System User" and not self.get_other_system_managers()
			and cint(frappe.db.get_single_value('System Settings', 'setup_complete'))):

			msgprint(_("Adding System Manager to this User as there must be atleast one System Manager"))
			self.append("roles", {
				"doctype": "Has Role",
				"role": "System Manager"
			})

		if self.name == 'Administrator':
			# Administrator should always have System Manager Role
			self.extend("roles", [
				{
					"doctype": "Has Role",
					"role": "System Manager"
				},
				{
					"doctype": "Has Role",
					"role": "Administrator"
				}
			])
def limit_exceed(earned_points, redeem_points, net_total_export):
	if cint(redeem_points) > cint(earned_points):
		frappe.msgprint(" Redeemption limit exceeded ", raise_exception=1)
	if cint(redeem_points) < 0:
		frappe.msgprint(" Negative points redeemption not allowed", raise_exception=1)
	if cint(redeem_points) > cint(net_total_export):
		frappe.msgprint(" Can't redeem more points than net total", raise_exception=1)
Example #26
0
	def retrieve_message(self, message_meta, msg_num=None):
		incoming_mail = None
		try:
			self.validate_message_limits(message_meta)

			if cint(self.settings.use_imap):
				status, message = self.imap.uid('fetch', message_meta, '(RFC822)')
				self.latest_messages.append(message[0][1])
			else:
				msg = self.pop.retr(msg_num)
				self.latest_messages.append(b'\n'.join(msg[1]))

		except (TotalSizeExceededError, EmailTimeoutError):
			# propagate this error to break the loop
			self.errors = True
			raise

		except Exception, e:
			if self.has_login_limit_exceeded(e):
				self.errors = True
				raise LoginLimitExceeded, e

			else:
				# log performs rollback and logs error in scheduler log
				log("receive.get_messages", self.make_error_msg(msg_num, incoming_mail))
				self.errors = True
				frappe.db.rollback()

				if not cint(self.settings.use_imap):
					self.pop.dele(msg_num)
Example #27
0
def boot_session(bootinfo):
	"""boot session - send website info if guest"""

	bootinfo.custom_css = frappe.db.get_value('Style Settings', None, 'custom_css') or ''
	bootinfo.website_settings = frappe.get_doc('Website Settings')

	if frappe.session['user']!='Guest':
		update_page_info(bootinfo)

		load_country_and_currency(bootinfo)
		bootinfo.sysdefaults.territory = frappe.db.get_single_value('Selling Settings',
			'territory')
		bootinfo.sysdefaults.customer_group = frappe.db.get_single_value('Selling Settings',
			'customer_group')
		bootinfo.sysdefaults.allow_stale = cint(frappe.db.get_single_value('Accounts Settings',
			'allow_stale'))
		bootinfo.sysdefaults.quotation_valid_till = cint(frappe.db.get_single_value('Selling Settings',
			'default_valid_till'))

		# if no company, show a dialog box to create a new company
		bootinfo.customer_count = frappe.db.sql("""select count(*) from tabCustomer""")[0][0]

		if not bootinfo.customer_count:
			bootinfo.setup_complete = frappe.db.sql("""select name from
				tabCompany limit 1""") and 'Yes' or 'No'

		bootinfo.docs += frappe.db.sql("""select name, default_currency, cost_center, default_terms,
			default_letter_head, default_bank_account, enable_perpetual_inventory from `tabCompany`""",
			as_dict=1, update={"doctype":":Company"})

		party_account_types = frappe.db.sql(""" select name, ifnull(account_type, '') from `tabParty Type`""")
		bootinfo.party_account_types = frappe._dict(party_account_types)
Example #28
0
	def test_warehouse_merging(self):
		set_perpetual_inventory(1)

		create_warehouse("Test Warehouse for Merging 1")
		create_warehouse("Test Warehouse for Merging 2")

		make_stock_entry(item_code="_Test Item", target="Test Warehouse for Merging 1 - _TC",
			qty=1, rate=100)
		make_stock_entry(item_code="_Test Item", target="Test Warehouse for Merging 2 - _TC",
			qty=1, rate=100)

		existing_bin_qty = (
			cint(frappe.db.get_value("Bin",
				{"item_code": "_Test Item", "warehouse": "Test Warehouse for Merging 1 - _TC"}, "actual_qty"))
			+ cint(frappe.db.get_value("Bin",
				{"item_code": "_Test Item", "warehouse": "Test Warehouse for Merging 2 - _TC"}, "actual_qty"))
		)

		rename_doc("Warehouse", "Test Warehouse for Merging 1 - _TC",
			"Test Warehouse for Merging 2 - _TC", merge=True)

		self.assertFalse(frappe.db.exists("Warehouse", "Test Warehouse for Merging 1 - _TC"))

		bin_qty = frappe.db.get_value("Bin",
			{"item_code": "_Test Item", "warehouse": "Test Warehouse for Merging 2 - _TC"}, "actual_qty")

		self.assertEqual(bin_qty, existing_bin_qty)

		self.assertTrue(frappe.db.get_value("Warehouse",
			filters={"account": "Test Warehouse for Merging 2 - _TC"}))
Example #29
0
	def get_data(self, party_naming_by, args):
		from erpnext.accounts.utils import get_currency_precision
		currency_precision = get_currency_precision() or 2
		dr_or_cr = "debit" if args.get("party_type") == "Customer" else "credit"

		voucher_details = self.get_voucher_details(args.get("party_type"))

		future_vouchers = self.get_entries_after(self.filters.report_date, args.get("party_type"))

		company_currency = frappe.db.get_value("Company", self.filters.get("company"), "default_currency")

		data = []
		for gle in self.get_entries_till(self.filters.report_date, args.get("party_type")):
			if self.is_receivable_or_payable(gle, dr_or_cr, future_vouchers):
				outstanding_amount = self.get_outstanding_amount(gle, self.filters.report_date, dr_or_cr)
				if abs(outstanding_amount) > 0.1/10**currency_precision:

					row = [gle.posting_date, gle.party]

					# customer / supplier name
					if party_naming_by == "Naming Series":
						row += [self.get_party_name(gle.party_type, gle.party)]

					# get due date
					due_date = voucher_details.get(gle.voucher_no, {}).get("due_date", "")

					row += [gle.voucher_type, gle.voucher_no, due_date]

					# get supplier bill details
					if args.get("party_type") == "Supplier":
						row += [
							voucher_details.get(gle.voucher_no, {}).get("bill_no", ""),
							voucher_details.get(gle.voucher_no, {}).get("bill_date", "")
						]

					# invoiced and paid amounts
					invoiced_amount = gle.get(dr_or_cr) if (gle.get(dr_or_cr) > 0) else 0
					paid_amt = invoiced_amount - outstanding_amount
					row += [invoiced_amount, paid_amt, outstanding_amount]

					# ageing data
					entry_date = due_date if self.filters.ageing_based_on == "Due Date" else gle.posting_date
					row += get_ageing_data(cint(self.filters.range1), cint(self.filters.range2),
						cint(self.filters.range3), self.age_as_on, entry_date, outstanding_amount)

					# customer territory / supplier type
					if args.get("party_type") == "Customer":
						row += [self.get_territory(gle.party)]
					if args.get("party_type") == "Supplier":
						row += [self.get_supplier_type(gle.party)]

					if self.filters.get(scrub(args.get("party_type"))):
						row.append(gle.account_currency)
					else:
						row.append(company_currency)

					row.append(gle.remarks)
					data.append(row)

		return data
Example #30
0
	def add_comment_count(self, result):
		for r in result:
			if not r.name:
				continue

			if "_comments" in r:
				comment_count = len(json.loads(r._comments or "[]"))
			else:
				comment_count = cint(frappe.db.get_value("Communication",
					filters={
						"communication_type": "Comment",
						"reference_doctype": self.doctype,
						"reference_name": r.name,
						"comment_type": "Comment"
					},
					fieldname="count(name)"))

			communication_count = cint(frappe.db.get_value("Communication",
				filters={
					"communication_type": "Communication",
					"reference_doctype": self.doctype,
					"reference_name": r.name
				},
				fieldname="count(name)"))

			r._comment_count = comment_count + communication_count
def generate_report_result(report, filters=None, user=None):
    status = None
    if not user:
        user = frappe.session.user
    if not filters:
        filters = []

    if filters and isinstance(filters, string_types):
        filters = json.loads(filters)
    columns, result, message, chart, data_to_be_printed, skip_total_row = [], [], None, None, None, 0
    if report.report_type == "Query Report":
        if not report.query:
            status = "error"
            frappe.msgprint(_("Must specify a Query to run"),
                            raise_exception=True)

        if not report.query.lower().startswith("select"):
            status = "error"
            frappe.msgprint(_("Query must be a SELECT"), raise_exception=True)

        result = [list(t) for t in frappe.db.sql(report.query, filters)]
        columns = [cstr(c[0]) for c in frappe.db.get_description()]

    elif report.report_type == 'Script Report':
        res = report.execute_script_report(filters)

        columns, result = res[0], res[1]
        if len(res) > 2:
            message = res[2]
        if len(res) > 3:
            chart = res[3]
        if len(res) > 4:
            data_to_be_printed = res[4]
        if len(res) > 5:
            skip_total_row = cint(res[5])

        if report.custom_columns:
            columns = json.loads(report.custom_columns)
            result = add_data_to_custom_columns(columns, result)

    if result:
        result = get_filtered_data(report.ref_doctype, columns, result, user)

    if cint(report.add_total_row) and result and not skip_total_row:
        result = add_total_row(result, columns)

    return {
        "result":
        result,
        "columns":
        columns,
        "message":
        message,
        "chart":
        chart,
        "data_to_be_printed":
        data_to_be_printed,
        "skip_total_row":
        skip_total_row,
        "status":
        status,
        "execution_time":
        frappe.cache().hget('report_execution_time', report.name) or 0
    }
Example #32
0
    def get_stock_and_rate(self, force=False):
        """get stock and incoming rate on posting date"""

        raw_material_cost = 0.0

        if not self.posting_date or not self.posting_time:
            frappe.throw(_("Posting date and posting time is mandatory"))

        allow_negative_stock = cint(
            frappe.db.get_default("allow_negative_stock"))

        for d in self.get('mtn_details'):
            d.transfer_qty = flt(d.transfer_qty)

            args = frappe._dict({
                "item_code":
                d.item_code,
                "warehouse":
                d.s_warehouse or d.t_warehouse,
                "posting_date":
                self.posting_date,
                "posting_time":
                self.posting_time,
                "qty":
                d.s_warehouse and -1 * d.transfer_qty or d.transfer_qty,
                "serial_no":
                d.serial_no
            })

            # get actual stock at source warehouse
            d.actual_qty = get_previous_sle(args).get(
                "qty_after_transaction") or 0

            # validate qty during submit
            if d.docstatus == 1 and d.s_warehouse and not allow_negative_stock and d.actual_qty < d.transfer_qty:
                frappe.throw(
                    _("""Row {0}: Qty not avalable in warehouse {1} on {2} {3}.
					Available Qty: {4}, Transfer Qty: {5}""").format(d.idx, d.s_warehouse,
                                                      self.posting_date,
                                                      self.posting_time,
                                                      d.actual_qty,
                                                      d.transfer_qty))

            # get incoming rate
            if not d.bom_no:
                if not flt(
                        d.incoming_rate
                ) or d.s_warehouse or self.purpose == "Sales Return" or force:
                    incoming_rate = flt(self.get_incoming_rate(args),
                                        self.precision("incoming_rate", d))
                    if incoming_rate > 0:
                        d.incoming_rate = incoming_rate
                d.amount = flt(
                    flt(d.transfer_qty) * flt(d.incoming_rate),
                    self.precision("amount", d))
                if not d.t_warehouse:
                    raw_material_cost += flt(d.amount)

        # set incoming rate for fg item
        if self.purpose in ["Manufacture", "Repack"]:
            number_of_fg_items = len([
                t.t_warehouse for t in self.get("mtn_details") if t.t_warehouse
            ])
            for d in self.get("mtn_details"):
                if d.bom_no or (d.t_warehouse and number_of_fg_items == 1):
                    if not flt(d.incoming_rate) or force:
                        operation_cost_per_unit = 0
                        if d.bom_no:
                            bom = frappe.db.get_value(
                                "BOM",
                                d.bom_no, ["operating_cost", "quantity"],
                                as_dict=1)
                            operation_cost_per_unit = flt(
                                bom.operating_cost) / flt(bom.quantity)
                        d.incoming_rate = flt(
                            operation_cost_per_unit +
                            (raw_material_cost + flt(self.total_fixed_cost)) /
                            flt(d.transfer_qty),
                            self.precision("incoming_rate", d))
                    d.amount = flt(
                        flt(d.transfer_qty) * flt(d.incoming_rate),
                        self.precision("transfer_qty", d))
                    break
Example #33
0
    def validate_return_reference_doc(self):
        """validate item with reference doc"""
        ref = get_return_doc_and_details(self)

        if ref.doc:
            # validate docstatus
            if ref.doc.docstatus != 1:
                frappe.throw(
                    _("{0} {1} must be submitted").format(
                        ref.doc.doctype, ref.doc.name),
                    frappe.InvalidStatusError)

            # update stock check
            if ref.doc.doctype == "Sales Invoice" and cint(
                    ref.doc.update_stock) != 1:
                frappe.throw(
                    _("'Update Stock' for Sales Invoice {0} must be set").
                    format(ref.doc.name), NotUpdateStockError)

            # posting date check
            ref_posting_datetime = "%s %s" % (cstr(
                ref.doc.posting_date), cstr(ref.doc.posting_time)
                                              or "00:00:00")
            this_posting_datetime = "%s %s" % (cstr(
                self.posting_date), cstr(self.posting_time))
            if this_posting_datetime < ref_posting_datetime:
                from frappe.utils.dateutils import datetime_in_user_format
                frappe.throw(
                    _("Posting timestamp must be after {0}").format(
                        datetime_in_user_format(ref_posting_datetime)))

            stock_items = get_stock_items_for_return(ref.doc, ref.parentfields)
            already_returned_item_qty = self.get_already_returned_item_qty(
                ref.fieldname)

            for item in self.get("mtn_details"):
                # validate if item exists in the ref doc and that it is a stock item
                if item.item_code not in stock_items:
                    frappe.throw(
                        _("Item {0} does not exist in {1} {2}").format(
                            item.item_code, ref.doc.doctype, ref.doc.name),
                        frappe.DoesNotExistError)

                # validate quantity <= ref item's qty - qty already returned
                if self.purpose == "Purchase Return":
                    ref_item_qty = sum([
                        flt(d.qty) * flt(d.conversion_factor)
                        for d in ref.doc.get({"item_code": item.item_code})
                    ])
                elif self.purpose == "Sales Return":
                    ref_item_qty = sum([
                        flt(d.qty)
                        for d in ref.doc.get({"item_code": item.item_code})
                    ])
                returnable_qty = ref_item_qty - flt(
                    already_returned_item_qty.get(item.item_code))
                if not returnable_qty:
                    frappe.throw(
                        _("Item {0} has already been returned").format(
                            item.item_code), StockOverReturnError)
                elif item.transfer_qty > returnable_qty:
                    frappe.throw(
                        _("Cannot return more than {0} for Item {1}").format(
                            returnable_qty, item.item_code),
                        StockOverReturnError)
Example #34
0
	def update_packing_list(self):
		if cint(self.update_stock) == 1:
			from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
			make_packing_list(self)
		else:
			self.set('packed_items', [])
Example #35
0
def search_widget(
	doctype,
	txt,
	query=None,
	searchfield=None,
	start=0,
	page_length=20,
	filters=None,
	filter_fields=None,
	as_dict=False,
	reference_doctype=None,
	ignore_user_permissions=False,
):

	start = cint(start)

	if isinstance(filters, string_types):
		filters = json.loads(filters)

	if searchfield:
		sanitize_searchfield(searchfield)

	if not searchfield:
		searchfield = "name"

	standard_queries = frappe.get_hooks().standard_queries or {}

	if query and query.split()[0].lower() != "select":
		# by method
		try:
			is_whitelisted(frappe.get_attr(query))
			frappe.response["values"] = frappe.call(
				query, doctype, txt, searchfield, start, page_length, filters, as_dict=as_dict
			)
		except frappe.exceptions.PermissionError as e:
			if frappe.local.conf.developer_mode:
				raise e
			else:
				frappe.respond_as_web_page(
					title="Invalid Method", html="Method not found", indicator_color="red", http_status_code=404
				)
			return
		except Exception as e:
			raise e
	elif not query and doctype in standard_queries:
		# from standard queries
		search_widget(
			doctype, txt, standard_queries[doctype][0], searchfield, start, page_length, filters
		)
	else:
		meta = frappe.get_meta(doctype)

		if query:
			frappe.throw(_("This query style is discontinued"))
			# custom query
			# frappe.response["values"] = frappe.db.sql(scrub_custom_query(query, searchfield, txt))
		else:
			if isinstance(filters, dict):
				filters_items = filters.items()
				filters = []
				for f in filters_items:
					if isinstance(f[1], (list, tuple)):
						filters.append([doctype, f[0], f[1][0], f[1][1]])
					else:
						filters.append([doctype, f[0], "=", f[1]])

			if filters == None:
				filters = []
			or_filters = []

			translated_search_doctypes = frappe.get_hooks("translated_search_doctypes")
			# build from doctype
			if txt:
				search_fields = ["name"]
				if meta.title_field:
					search_fields.append(meta.title_field)

				if meta.search_fields:
					search_fields.extend(meta.get_search_fields())

				for f in search_fields:
					fmeta = meta.get_field(f.strip())
					if (doctype not in translated_search_doctypes) and (
						f == "name"
						or (
							fmeta
							and fmeta.fieldtype
							in ["Data", "Text", "Small Text", "Long Text", "Link", "Select", "Read Only", "Text Editor"]
						)
					):
						or_filters.append([doctype, f.strip(), "like", "%{0}%".format(txt)])

			if meta.get("fields", {"fieldname": "enabled", "fieldtype": "Check"}):
				filters.append([doctype, "enabled", "=", 1])
			if meta.get("fields", {"fieldname": "disabled", "fieldtype": "Check"}):
				filters.append([doctype, "disabled", "!=", 1])

			# format a list of fields combining search fields and filter fields
			fields = get_std_fields_list(meta, searchfield or "name")
			if filter_fields:
				fields = list(set(fields + json.loads(filter_fields)))
			formatted_fields = ["`tab%s`.`%s`" % (meta.name, f.strip()) for f in fields]

			# find relevance as location of search term from the beginning of string `name`. used for sorting results.
			formatted_fields.append(
				"""locate({_txt}, `tab{doctype}`.`name`) as `_relevance`""".format(
					_txt=frappe.db.escape((txt or "").replace("%", "").replace("@", "")), doctype=doctype
				)
			)

			# In order_by, `idx` gets second priority, because it stores link count
			from frappe.model.db_query import get_order_by

			order_by_based_on_meta = get_order_by(doctype, meta)
			# 2 is the index of _relevance column
			order_by = "_relevance, {0}, `tab{1}`.idx desc".format(order_by_based_on_meta, doctype)

			ptype = "select" if frappe.only_has_select_perm(doctype) else "read"
			ignore_permissions = (
				True
				if doctype == "DocType"
				else (cint(ignore_user_permissions) and has_permission(doctype, ptype=ptype))
			)

			if doctype in translated_search_doctypes:
				page_length = None

			values = frappe.get_list(
				doctype,
				filters=filters,
				fields=formatted_fields,
				or_filters=or_filters,
				limit_start=start,
				limit_page_length=page_length,
				order_by=order_by,
				ignore_permissions=ignore_permissions,
				reference_doctype=reference_doctype,
				as_list=not as_dict,
				strict=False,
			)

			if doctype in translated_search_doctypes:
				# Filtering the values array so that query is included in very element
				values = (
					v
					for v in values
					if re.search(f"{re.escape(txt)}.*", _(v.name if as_dict else v[0]), re.IGNORECASE)
				)

			# Sorting the values array so that relevant results always come first
			# This will first bring elements on top in which query is a prefix of element
			# Then it will bring the rest of the elements and sort them in lexicographical order
			values = sorted(values, key=lambda x: relevance_sorter(x, txt, as_dict))

			# remove _relevance from results
			if as_dict:
				for r in values:
					r.pop("_relevance")
				frappe.response["values"] = values
			else:
				frappe.response["values"] = [r[:-1] for r in values]
Example #36
0
 def connect(self):
     """Connect to **Email Account**."""
     if cint(self.settings.use_imap):
         return self.connect_imap()
     else:
         return self.connect_pop()
Example #37
0
            num = num_copy
            if not cint(self.settings.use_imap):
                if num > 100 and not self.errors:
                    for m in xrange(101, num + 1):
                        self.pop.dele(m)

        except Exception, e:
            if self.has_login_limit_exceeded(e):
                pass

            else:
                raise

        finally:
            # no matter the exception, pop should quit if connected
            if cint(self.settings.use_imap):
                self.imap.logout()
            else:
                self.pop.quit()

        return self.latest_messages

    def get_new_mails(self):
        """Return list of new mails"""
        if cint(self.settings.use_imap):
            self.imap.select("Inbox")
            response, message = self.imap.uid('search', None, "UNSEEN")
            email_list = message[0].split()
        else:
            email_list = self.pop.list()[1]
Example #38
0
def create_material_request(material_requests):
	"""	Create indent on reaching reorder level	"""
	mr_list = []
	exceptions_list = []

	def _log_exception():
		if frappe.local.message_log:
			exceptions_list.extend(frappe.local.message_log)
			frappe.local.message_log = []
		else:
			exceptions_list.append(frappe.get_traceback())

	for request_type in material_requests:
		for company in material_requests[request_type]:
			try:
				items = material_requests[request_type][company]
				if not items:
					continue

				mr = frappe.new_doc("Material Request")
				mr.update({
					"company": company,
					"transaction_date": nowdate(),
					"material_request_type": "Material Transfer" if request_type=="Transfer" else request_type
				})

				for d in items:
					d = frappe._dict(d)
					item = frappe.get_doc("Item", d.item_code)
					mr.append("items", {
						"doctype": "Material Request Item",
						"item_code": d.item_code,
						"schedule_date": add_days(nowdate(),cint(item.lead_time_days)),
						"uom":	item.stock_uom,
						"warehouse": d.warehouse,
						"item_name": item.item_name,
						"description": item.description,
						"item_group": item.item_group,
						"qty": d.reorder_qty,
						"brand": item.brand,
					})

				mr.insert()
				mr.submit()
				mr_list.append(mr)

			except:
				_log_exception()

	if mr_list:
		if getattr(frappe.local, "reorder_email_notify", None) is None:
			frappe.local.reorder_email_notify = cint(frappe.db.get_value('Stock Settings', None,
				'reorder_email_notify'))

		if(frappe.local.reorder_email_notify):
			send_email_notification(mr_list)

	if exceptions_list:
		notify_errors(exceptions_list)

	return mr_list
Example #39
0
    def set_property_setters(self):
        meta = frappe.get_meta(self.doc_type)
        # doctype property setters

        for property in doctype_properties:
            if self.get(property) != meta.get(property):
                self.make_property_setter(
                    property=property,
                    value=self.get(property),
                    property_type=doctype_properties[property])

        for df in self.get("fields"):
            meta_df = meta.get("fields", {"fieldname": df.fieldname})

            if not meta_df or meta_df[0].get("is_custom_field"):
                continue

            for property in docfield_properties:
                if property != "idx" and (df.get(property) or '') != (
                        meta_df[0].get(property) or ''):
                    if property == "fieldtype":
                        self.validate_fieldtype_change(
                            df, meta_df[0].get(property), df.get(property))

                    elif property == "allow_on_submit" and df.get(property):
                        frappe.msgprint(_("Row {0}: Not allowed to enable Allow on Submit for standard fields")\
                         .format(df.idx))
                        continue

                    elif property == "reqd" and \
                     ((frappe.db.get_value("DocField",
                      {"parent":self.doc_type,"fieldname":df.fieldname}, "reqd") == 1) \
                      and (df.get(property) == 0)):
                        frappe.msgprint(_("Row {0}: Not allowed to disable Mandatory for standard fields")\
                          .format(df.idx))
                        continue

                    elif property == "in_list_view" and df.get(property) \
                     and df.fieldtype!="Attach Image" and df.fieldtype in no_value_fields:
                        frappe.msgprint(
                            _("'In List View' not allowed for type {0} in row {1}"
                              ).format(df.fieldtype, df.idx))
                        continue

                    elif property == "precision" and cint(df.get("precision")) > 6 \
                      and cint(df.get("precision")) > cint(meta_df[0].get("precision")):
                        self.flags.update_db = True

                    elif property == "unique":
                        self.flags.update_db = True

                    elif (property == "read_only"
                          and cint(df.get("read_only")) == 0
                          and frappe.db.get_value("DocField", {
                              "parent": self.doc_type,
                              "fieldname": df.fieldname
                          }, "read_only") == 1):
                        # if docfield has read_only checked and user is trying to make it editable, don't allow it
                        frappe.msgprint(
                            _("You cannot unset 'Read Only' for field {0}").
                            format(df.label))
                        continue

                    elif property == "options" and df.get(
                            "fieldtype"
                    ) not in allowed_fieldtype_for_options_change:
                        frappe.msgprint(
                            _("You can't set 'Options' for field {0}").format(
                                df.label))
                        continue

                    elif property == 'translatable' and not supports_translation(
                            df.get('fieldtype')):
                        frappe.msgprint(
                            _("You can't set 'Translatable' for field {0}").
                            format(df.label))
                        continue

                    self.make_property_setter(
                        property=property,
                        value=df.get(property),
                        property_type=docfield_properties[property],
                        fieldname=df.fieldname)
Example #40
0
	def replace_sender(self):
		if cint(self.email_account.always_use_account_email_id_as_sender):
			self.set_header('X-Original-From', self.sender)
			sender_name, sender_email = parse_addr(self.sender)
			self.sender = email.utils.formataddr((str(Header(sender_name or self.email_account.name, 'utf-8')), self.email_account.email_id))
Example #41
0
def validate_validity(doc, method):
    # gangadhar
    frappe.errprint("validate validity")
    from frappe.utils import get_url, cstr
    frappe.errprint(get_url())
    frappe.errprint("validate validity")
    if doc.get("__islocal") and get_url() != 'http://stich1.tailorpad.com':
        frappe.errprint(get_url())
        frappe.errprint("is local and not stitch1.tailorpad.com")
        res = frappe.db.sql(
            "select name from `tabUser` where name='Administrator' and no_of_users >0"
        )
        frappe.errprint(res)
        if res:
            frappe.errprint("in res if")
            frappe.db.sql(
                "update `tabUser` set no_of_users=no_of_users-1  where name='Administrator'"
            )
            from frappe.utils import nowdate, add_months, cint
            frappe.errprint("user if validity")
            frappe.errprint(doc.add_validity)
            frappe.errprint("user validity1")
            doc.validity_start_date = ''
            doc.validity_end_date = ''
            frappe.errprint("created only user")

        elif doc.add_validity:
            res = frappe.db.sql(
                "select user_name,validity from `tabUser Validity` where name='%s'"
                % doc.add_validity,
                debug=1)
            frappe.errprint(res)
            if res and res[0][0] > 1 and res[0][1] <= 0:
                frappe.db.sql(
                    "update `tabUser Validity` set user_name=user_name-1 where name='%s'"
                    % doc.add_validity,
                    debug=1)
                frappe.errprint("created user")
                from frappe.utils import nowdate, add_months, cint
                doc.add_validity = ''
                frappe.errprint("user if validity")
                frappe.errprint(doc.add_validity)
                frappe.errprint("user validity1")
                doc.validity_start_date = ''
                doc.validity_end_date = ''
            elif res and res[0][0] > 1 and res[0][1] > 0:
                frappe.db.sql(
                    "update `tabUser Validity` set user_name=user_name-1 where name='%s'"
                    % doc.add_validity,
                    debug=1)
                from frappe.utils import nowdate, add_months, cint
                doc.add_validity = ''
                frappe.errprint("user else validity")
                frappe.errprint(doc.add_validity)
                frappe.errprint("user validity1")
                doc.validity_start_date = nowdate()
                doc.validity_end_date = add_months(nowdate(), 1)
            else:
                frappe.throw(
                    _("Your User Creation limit is exceeded . Please contact administrator"
                      ))
        else:
            res1 = frappe.db.sql("select count(name) from `tabUser`")
            frappe.errprint("else res1 ")
            frappe.errprint(res1)
            if res1 and res1[0][0] == 2:
                frappe.errprint("else if")
                #frappe.db.sql("update `tabUser`set no_of_users=no_of_users-1  where name='Administrator'")
                from frappe.utils import nowdate, add_months, cint
                doc.validity_start_date = nowdate()
                doc.validity_end_date = add_months(nowdate(), 1)
            else:
                frappe.throw(
                    _("Your User Creation limit is exceeded . Please contact administrator"
                      ))

    elif (get_url() != 'http://stich1.tailorpad.com'):
        frappe.errprint("updating existing user not smarttailor")
        if doc.add_validity:
            frappe.errprint("updating existing user not smarttailor")
            res1 = frappe.db.sql(
                "select validity from `tabUser Validity` where user_name>0 and name=%s",
                doc.add_validity)
            frappe.errprint(res1)
            if res1:
                frappe.errprint("else res1 ")
                frappe.errprint("update user validity")
                from frappe.utils import nowdate, add_months, cint
                doc.add_validity = ''
                frappe.errprint("user validity")
                frappe.errprint(doc.add_validity)
                frappe.errprint("user validity1")
                doc.validity_start_date = nowdate()
                doc.validity_end_date = add_months(nowdate(), cint(res1[0][0]))
                frappe.errprint(doc.add_validity)
                qr = "update `tabUser Validity` set user_name=user_name-1 where name='" + doc.add_validity + "'"
                frappe.errprint(qr)
                frappe.db.sql(qr)
                frappe.errprint("updated only for validity")
Example #42
0
def make(doctype=None,
         name=None,
         content=None,
         subject=None,
         sent_or_received="Sent",
         sender=None,
         sender_full_name=None,
         recipients=None,
         communication_medium="Email",
         send_email=False,
         print_html=None,
         print_format=None,
         attachments='[]',
         send_me_a_copy=False,
         cc=None,
         flags=None,
         read_receipt=None):
    """Make a new communication.

	:param doctype: Reference DocType.
	:param name: Reference Document name.
	:param content: Communication body.
	:param subject: Communication subject.
	:param sent_or_received: Sent or Received (default **Sent**).
	:param sender: Communcation sender (default current user).
	:param recipients: Communication recipients as list.
	:param communication_medium: Medium of communication (default **Email**).
	:param send_mail: Send via email (default **False**).
	:param print_html: HTML Print format to be sent as attachment.
	:param print_format: Print Format name of parent document to be sent as attachment.
	:param attachments: List of attachments as list of files or JSON string.
	:param send_me_a_copy: Send a copy to the sender (default **False**).
	"""

    is_error_report = (doctype == "User" and name == frappe.session.user
                       and subject == "Error Report")
    send_me_a_copy = cint(send_me_a_copy)

    if doctype and name and not is_error_report and not frappe.has_permission(
            doctype, "email",
            name) and not (flags or {}).get('ignore_doctype_permissions'):
        raise frappe.PermissionError(
            "You are not allowed to send emails related to: {doctype} {name}".
            format(doctype=doctype, name=name))

    if not sender:
        sender = get_formatted_email(frappe.session.user)

    comm = frappe.get_doc({
        "doctype": "Communication",
        "subject": subject,
        "content": content,
        "sender": sender,
        "sender_full_name": sender_full_name,
        "recipients": recipients,
        "cc": cc or None,
        "communication_medium": communication_medium,
        "sent_or_received": sent_or_received,
        "reference_doctype": doctype,
        "reference_name": name,
        "message_id": get_message_id().strip(" <>"),
        "read_receipt": read_receipt,
        "has_attachment": 1 if attachments else 0
    })
    comm.insert(ignore_permissions=True)

    if not doctype:
        # if no reference given, then send it against the communication
        comm.db_set(
            dict(reference_doctype='Communication', reference_name=comm.name))

    if isinstance(attachments, basestring):
        attachments = json.loads(attachments)

    # if not committed, delayed task doesn't find the communication
    if attachments:
        add_attachments(comm.name, attachments)

    frappe.db.commit()

    if cint(send_email):
        comm.send(print_html,
                  print_format,
                  attachments,
                  send_me_a_copy=send_me_a_copy)

    return {
        "name":
        comm.name,
        "emails_not_sent_to":
        ", ".join(comm.emails_not_sent_to)
        if hasattr(comm, "emails_not_sent_to") else None
    }
Example #43
0
 def check_if_enabled(self, user):
     """raise exception if user not enabled"""
     if user == 'Administrator': return
     if not cint(frappe.db.get_value('User', user, 'enabled')):
         self.fail('User disabled or missing', user=user)
Example #44
0
    def check_workstation_time(self, row):
        workstation_doc = frappe.get_cached_doc("Workstation",
                                                self.workstation)
        if (not workstation_doc.working_hours or cint(
                frappe.db.get_single_value("Manufacturing Settings",
                                           "allow_overtime"))):
            if get_datetime(row.planned_end_time) < get_datetime(
                    row.planned_start_time):
                row.planned_end_time = add_to_date(row.planned_start_time,
                                                   minutes=row.time_in_mins)
                row.remaining_time_in_mins = 0.0
            else:
                row.remaining_time_in_mins -= time_diff_in_minutes(
                    row.planned_end_time, row.planned_start_time)

            self.update_time_logs(row)
            return

        start_date = getdate(row.planned_start_time)
        start_time = get_time(row.planned_start_time)

        new_start_date = workstation_doc.validate_workstation_holiday(
            start_date)

        if new_start_date != start_date:
            row.planned_start_time = datetime.datetime.combine(
                new_start_date, start_time)
            start_date = new_start_date

        total_idx = len(workstation_doc.working_hours)

        for i, time_slot in enumerate(workstation_doc.working_hours):
            workstation_start_time = datetime.datetime.combine(
                start_date, get_time(time_slot.start_time))
            workstation_end_time = datetime.datetime.combine(
                start_date, get_time(time_slot.end_time))

            if (get_datetime(row.planned_start_time) >= workstation_start_time
                    and get_datetime(
                        row.planned_start_time) <= workstation_end_time):
                time_in_mins = time_diff_in_minutes(workstation_end_time,
                                                    row.planned_start_time)

                # If remaining time fit in workstation time logs else split hours as per workstation time
                if time_in_mins > row.remaining_time_in_mins:
                    row.planned_end_time = add_to_date(
                        row.planned_start_time,
                        minutes=row.remaining_time_in_mins)
                    row.remaining_time_in_mins = 0
                else:
                    row.planned_end_time = add_to_date(row.planned_start_time,
                                                       minutes=time_in_mins)
                    row.remaining_time_in_mins -= time_in_mins

                self.update_time_logs(row)

                if total_idx != (i + 1) and row.remaining_time_in_mins > 0:
                    row.planned_start_time = datetime.datetime.combine(
                        start_date,
                        get_time(workstation_doc.working_hours[i +
                                                               1].start_time))

        if row.remaining_time_in_mins > 0:
            start_date = add_days(start_date, 1)
            row.planned_start_time = datetime.datetime.combine(
                start_date,
                get_time(workstation_doc.working_hours[0].start_time))
Example #45
0
 def on_recurring(self, reference_doc):
     mcount = month_map[reference_doc.recurring_type]
     self.set(
         "delivery_date",
         get_next_date(reference_doc.delivery_date, mcount,
                       cint(reference_doc.repeat_on_day_of_month)))
Example #46
0
def update_entries_after(args,
                         allow_zero_rate=False,
                         allow_negative_stock=False,
                         via_landed_cost_voucher=False,
                         verbose=1):
    """
		update valution rate and qty after transaction
		from the current time-bucket onwards

		args = {
			"item_code": "ABC",
			"warehouse": "XYZ",
			"posting_date": "2012-12-12",
			"posting_time": "12:00"
		}
	"""
    if not _exceptions:
        frappe.local.stockledger_exceptions = []

    if not allow_negative_stock:
        allow_negative_stock = cint(
            frappe.db.get_default("allow_negative_stock"))

    previous_sle = get_sle_before_datetime(args)

    qty_after_transaction = flt(previous_sle.get("qty_after_transaction"))
    valuation_rate = flt(previous_sle.get("valuation_rate"))
    stock_queue = json.loads(previous_sle.get("stock_queue") or "[]")
    stock_value = flt(previous_sle.get("stock_value"))
    prev_stock_value = flt(previous_sle.get("stock_value"))

    entries_to_fix = get_sle_after_datetime(previous_sle or \
     {"item_code": args["item_code"], "warehouse": args["warehouse"]}, for_update=True)
    valuation_method = get_valuation_method(args["item_code"])
    stock_value_difference = 0.0

    for sle in entries_to_fix:
        if (sle.serial_no
                and not via_landed_cost_voucher) or not allow_negative_stock:
            # validate negative stock for serialized items, fifo valuation
            # or when negative stock is not allowed for moving average
            if not validate_negative_stock(qty_after_transaction, sle):
                qty_after_transaction += flt(sle.actual_qty)
                continue

        if sle.serial_no:
            valuation_rate = get_serialized_values(qty_after_transaction, sle,
                                                   valuation_rate)
            qty_after_transaction += flt(sle.actual_qty)

        else:
            if sle.voucher_type == "Stock Reconciliation":
                valuation_rate = sle.valuation_rate
                qty_after_transaction = sle.qty_after_transaction
                stock_queue = [[qty_after_transaction, valuation_rate]]
            else:
                if valuation_method == "Moving Average":
                    valuation_rate = get_moving_average_values(
                        qty_after_transaction, sle, valuation_rate,
                        allow_zero_rate)
                else:
                    valuation_rate = get_fifo_values(qty_after_transaction,
                                                     sle, stock_queue,
                                                     allow_zero_rate)

                qty_after_transaction += flt(sle.actual_qty)

        # get stock value
        if sle.serial_no:
            stock_value = qty_after_transaction * valuation_rate
        elif valuation_method == "Moving Average":
            stock_value = qty_after_transaction * valuation_rate
        else:
            stock_value = sum(
                (flt(batch[0]) * flt(batch[1]) for batch in stock_queue))

        # rounding as per precision
        from frappe.model.meta import get_field_precision
        meta = frappe.get_meta("Stock Ledger Entry")

        stock_value = flt(
            stock_value,
            get_field_precision(meta.get_field("stock_value"),
                                frappe._dict({"fields": sle})))

        stock_value_difference = stock_value - prev_stock_value
        prev_stock_value = stock_value

        # update current sle
        frappe.db.sql(
            """update `tabStock Ledger Entry`
			set qty_after_transaction=%s, valuation_rate=%s, stock_queue=%s,
			stock_value=%s, stock_value_difference=%s where name=%s""",
            (qty_after_transaction, valuation_rate, json.dumps(stock_queue),
             stock_value, stock_value_difference, sle.name))

    if _exceptions:
        _raise_exceptions(args, verbose)

    # update bin
    if not frappe.db.exists({
            "doctype": "Bin",
            "item_code": args["item_code"],
            "warehouse": args["warehouse"]
    }):
        bin_wrapper = frappe.get_doc({
            "doctype": "Bin",
            "item_code": args["item_code"],
            "warehouse": args["warehouse"],
        })
        bin_wrapper.ignore_permissions = 1
        bin_wrapper.insert()

    frappe.db.sql(
        """update `tabBin` set valuation_rate=%s, actual_qty=%s,
		stock_value=%s,
		projected_qty = (actual_qty + indented_qty + ordered_qty + planned_qty - reserved_qty)
		where item_code=%s and warehouse=%s""",
        (valuation_rate, qty_after_transaction, stock_value, args["item_code"],
         args["warehouse"]))
Example #47
0
def are_emails_muted():
	from frappe.utils import cint
	return flags.mute_emails or cint(conf.get("mute_emails") or 0) or False
Example #48
0
    def execute(self,
                query=None,
                fields=None,
                filters=None,
                or_filters=None,
                docstatus=None,
                group_by=None,
                order_by=None,
                limit_start=False,
                limit_page_length=None,
                as_list=False,
                with_childnames=False,
                debug=False,
                ignore_permissions=False,
                user=None,
                with_comment_count=False,
                join='left join',
                distinct=False,
                start=None,
                page_length=None,
                limit=None,
                ignore_ifnull=False,
                save_user_settings=False,
                save_user_settings_fields=False,
                update=None,
                add_total_row=None,
                user_settings=None,
                reference_doctype=None,
                strict=True):
        if not ignore_permissions and not frappe.has_permission(
                self.doctype, "read", user=user):
            frappe.flags.error_message = _(
                'Insufficient Permission for {0}').format(
                    frappe.bold(self.doctype))
            raise frappe.PermissionError(self.doctype)

        # filters and fields swappable
        # its hard to remember what comes first
        if (isinstance(fields, dict) or (isinstance(fields, list) and fields
                                         and isinstance(fields[0], list))):
            # if fields is given as dict/list of list, its probably filters
            filters, fields = fields, filters

        elif fields and isinstance(filters, list) \
         and len(filters) > 1 and isinstance(filters[0], string_types):
            # if `filters` is a list of strings, its probably fields
            filters, fields = fields, filters

        if fields:
            self.fields = fields
        else:
            self.fields = ["`tab{0}`.`name`".format(self.doctype)]

        if start: limit_start = start
        if page_length: limit_page_length = page_length
        if limit: limit_page_length = limit

        self.filters = filters or []
        self.or_filters = or_filters or []
        self.docstatus = docstatus or []
        self.group_by = group_by
        self.order_by = order_by
        self.limit_start = 0 if (limit_start is False) else cint(limit_start)
        self.limit_page_length = cint(
            limit_page_length) if limit_page_length else None
        self.with_childnames = with_childnames
        self.debug = debug
        self.join = join
        self.distinct = distinct
        self.as_list = as_list
        self.ignore_ifnull = ignore_ifnull
        self.flags.ignore_permissions = ignore_permissions
        self.user = user or frappe.session.user
        self.update = update
        self.user_settings_fields = copy.deepcopy(self.fields)
        self.strict = strict

        # for contextual user permission check
        # to determine which user permission is applicable on link field of specific doctype
        self.reference_doctype = reference_doctype or self.doctype

        if user_settings:
            self.user_settings = json.loads(user_settings)

        if query:
            result = self.run_custom_query(query)
        else:
            result = self.build_and_run()

        if with_comment_count and not as_list and self.doctype:
            self.add_comment_count(result)

        if save_user_settings:
            self.save_user_settings_fields = save_user_settings_fields
            self.update_user_settings()

        return result
Example #49
0
def validate_permissions(doctype, for_remove=False):
    permissions = doctype.get("permissions")
    if not permissions:
        frappe.throw(_('Enter at least one permission row'),
                     frappe.MandatoryError)
    issingle = issubmittable = isimportable = False
    if doctype:
        issingle = cint(doctype.issingle)
        issubmittable = cint(doctype.is_submittable)
        isimportable = cint(doctype.allow_import)

    def get_txt(d):
        return _("For {0} at level {1} in {2} in row {3}").format(
            d.role, d.permlevel, d.parent, d.idx)

    def check_atleast_one_set(d):
        if not d.read and not d.write and not d.submit and not d.cancel and not d.create:
            frappe.throw(_("{0}: No basic permissions set").format(get_txt(d)))

    def check_double(d):
        has_similar = False
        similar_because_of = ""
        for p in permissions:
            if p.role == d.role and p.permlevel == d.permlevel and p != d:
                if p.apply_user_permissions == d.apply_user_permissions:
                    has_similar = True
                    similar_because_of = _("Apply User Permissions")
                    break
                elif p.if_owner == d.if_owner:
                    similar_because_of = _("If Owner")
                    has_similar = True
                    break

        if has_similar:
            frappe.throw(_("{0}: Only one rule allowed with the same Role, Level and {1}")\
             .format(get_txt(d), similar_because_of))

    def check_level_zero_is_set(d):
        if cint(d.permlevel) > 0 and d.role != 'All':
            has_zero_perm = False
            for p in permissions:
                if p.role == d.role and (p.permlevel or 0) == 0 and p != d:
                    has_zero_perm = True
                    break

            if not has_zero_perm:
                frappe.throw(
                    _("{0}: Permission at level 0 must be set before higher levels are set"
                      ).format(get_txt(d)))

            for invalid in ("create", "submit", "cancel", "amend"):
                if d.get(invalid): d.set(invalid, 0)

    def check_permission_dependency(d):
        if d.cancel and not d.submit:
            frappe.throw(
                _("{0}: Cannot set Cancel without Submit").format(get_txt(d)))

        if (d.submit or d.cancel or d.amend) and not d.write:
            frappe.throw(
                _("{0}: Cannot set Submit, Cancel, Amend without Write").
                format(get_txt(d)))
        if d.amend and not d.write:
            frappe.throw(
                _("{0}: Cannot set Amend without Cancel").format(get_txt(d)))
        if d.get("import") and not d.create:
            frappe.throw(
                _("{0}: Cannot set Import without Create").format(get_txt(d)))

    def remove_rights_for_single(d):
        if not issingle:
            return

        if d.report:
            frappe.msgprint(_("Report cannot be set for Single types"))
            d.report = 0
            d.set("import", 0)
            d.set("export", 0)

        for ptype, label in (("set_user_permissions",
                              _("Set User Permissions")),
                             ("apply_user_permissions",
                              _("Apply User Permissions"))):
            if d.get(ptype):
                d.set(ptype, 0)
                frappe.msgprint(
                    _("{0} cannot be set for Single types").format(label))

    def check_if_submittable(d):
        if d.submit and not issubmittable:
            frappe.throw(
                _("{0}: Cannot set Assign Submit if not Submittable").format(
                    get_txt(d)))
        elif d.amend and not issubmittable:
            frappe.throw(
                _("{0}: Cannot set Assign Amend if not Submittable").format(
                    get_txt(d)))

    def check_if_importable(d):
        if d.get("import") and not isimportable:
            frappe.throw(
                _("{0}: Cannot set import as {1} is not importable").format(
                    get_txt(d), doctype))

    for d in permissions:
        if not d.permlevel:
            d.permlevel = 0
        check_atleast_one_set(d)
        if not for_remove:
            check_double(d)
            check_permission_dependency(d)
            check_if_submittable(d)
            check_if_importable(d)
        check_level_zero_is_set(d)
        remove_rights_for_single(d)
Example #50
0
 def get_expiry_in_seconds(self, expiry):
     if not expiry:
         return 3600
     parts = expiry.split(":")
     return (cint(parts[0]) * 3600) + (cint(parts[1]) * 60) + cint(parts[2])
Example #51
0
 def check_width(d):
     if d.fieldtype == "Currency" and cint(d.width) < 100:
         frappe.throw(
             _("Max width for type Currency is 100px in row {0}").format(
                 d.idx))
Example #52
0
    def set_incoming_rate(self):
        if self.doctype not in ("Delivery Note", "Sales Invoice"):
            return

        items = self.get("items") + (self.get("packed_items") or [])
        for d in items:
            if not self.get("return_against"):
                # Get incoming rate based on original item cost based on valuation method
                qty = flt(d.get('stock_qty') or d.get('actual_qty'))

                if not d.incoming_rate:
                    d.incoming_rate = get_incoming_rate(
                        {
                            "item_code":
                            d.item_code,
                            "warehouse":
                            d.warehouse,
                            "posting_date":
                            self.get('posting_date')
                            or self.get('transaction_date'),
                            "posting_time":
                            self.get('posting_time') or nowtime(),
                            "qty":
                            qty if cint(self.get("is_return")) else (-1 * qty),
                            "serial_no":
                            d.get('serial_no'),
                            "company":
                            self.company,
                            "voucher_type":
                            self.doctype,
                            "voucher_no":
                            self.name,
                            "allow_zero_valuation":
                            d.get("allow_zero_valuation")
                        },
                        raise_error_if_no_rate=False)

                # For internal transfers use incoming rate as the valuation rate
                if self.is_internal_transfer():
                    if d.doctype == "Packed Item":
                        incoming_rate = flt(
                            d.incoming_rate * d.conversion_factor,
                            d.precision('incoming_rate'))
                        if d.incoming_rate != incoming_rate:
                            d.incoming_rate = incoming_rate
                    else:
                        rate = flt(d.incoming_rate * d.conversion_factor,
                                   d.precision('rate'))
                        if d.rate != rate:
                            d.rate = rate

                        d.discount_percentage = 0
                        d.discount_amount = 0
                        frappe.msgprint(_(
                            "Row {0}: Item rate has been updated as per valuation rate since its an internal stock transfer"
                        ).format(d.idx),
                                        alert=1)

            elif self.get("return_against"):
                # Get incoming rate of return entry from reference document
                # based on original item cost as per valuation method
                d.incoming_rate = get_rate_for_return(self.doctype,
                                                      self.name,
                                                      d.item_code,
                                                      self.return_against,
                                                      item_row=d)
Example #53
0
def format_value(value, df=None, doc=None, currency=None, translated=False):
    '''Format value based on given fieldtype, document reference, currency reference.
	If docfield info (df) is not given, it will try and guess based on the datatype of the value'''
    if isinstance(df, string_types):
        df = frappe._dict(fieldtype=df)

    if not df:
        df = frappe._dict()
        if isinstance(value, datetime.datetime):
            df.fieldtype = 'Datetime'
        elif isinstance(value, datetime.date):
            df.fieldtype = 'Date'
        elif isinstance(value, datetime.timedelta):
            df.fieldtype = 'Time'
        elif isinstance(value, int):
            df.fieldtype = 'Int'
        elif isinstance(value, float):
            df.fieldtype = 'Float'
        else:
            df.fieldtype = 'Data'

    elif (isinstance(df, dict)):
        # Convert dict to object if necessary
        df = frappe._dict(df)

    if value is None:
        value = ""
    elif translated:
        value = frappe._(value)

    if not df:
        return value

    elif df.get("fieldtype") == "Date":
        return formatdate(value)

    elif df.get("fieldtype") == "Datetime":
        return format_datetime(value)

    elif df.get("fieldtype") == "Time":
        return format_time(value)

    elif value == 0 and df.get("fieldtype") in (
            "Int", "Float", "Currency",
            "Percent") and df.get("print_hide_if_no_value"):
        # this is required to show 0 as blank in table columns
        return ""

    elif df.get("fieldtype") == "Currency" or (df.get("fieldtype") == "Float"
                                               and (df.options or "").strip()):
        return fmt_money(value,
                         precision=get_field_precision(df, doc),
                         currency=currency if currency else
                         (get_field_currency(df, doc) if doc else None))

    elif df.get("fieldtype") == "Float":
        precision = get_field_precision(df, doc)

        # show 1.000000 as 1
        # options should not specified
        if not df.options and value is not None:
            temp = cstr(value).split(".")
            if len(temp) == 1 or cint(temp[1]) == 0:
                precision = 0

        return fmt_money(value, precision=precision)

    elif df.get("fieldtype") == "Percent":
        return "{}%".format(flt(value, 2))

    elif df.get("fieldtype") in ("Text", "Small Text"):
        if not re.search("(\<br|\<div|\<p)", value):
            return frappe.safe_decode(value).replace("\n", "<br>")

    elif df.get("fieldtype") == "Markdown Editor":
        return frappe.utils.markdown(value)

    elif df.get("fieldtype") == "Table MultiSelect":
        meta = frappe.get_meta(df.options)
        link_field = [df for df in meta.fields if df.fieldtype == 'Link'][0]
        values = [v.get(link_field.fieldname, 'asdf') for v in value]
        return ', '.join(values)

    return value
Example #54
0
 def check_precision(d):
     if d.fieldtype in ("Currency", "Float",
                        "Percent") and d.precision is not None and not (
                            1 <= cint(d.precision) <= 6):
         frappe.throw(_("Precision should be between 1 and 6"))
Example #55
0
def get_auto_serial_nos(serial_no_series, qty):
    serial_nos = []
    for i in range(cint(qty)):
        serial_nos.append(make_autoname(serial_no_series, "Serial No"))

    return "\n".join(serial_nos)
Example #56
0
def get_events(start, end, user=None, for_reminder=False):
    if not user:
        user = frappe.session.user
    roles = frappe.get_roles(user)
    events = frappe.db.sql("""select name, subject, description,
		starts_on, ends_on, owner, all_day, event_type, repeat_this_event, repeat_on,repeat_till,
		monday, tuesday, wednesday, thursday, friday, saturday, sunday
		from tabEvent where ((
			(date(starts_on) between date('%(start)s') and date('%(end)s'))
			or (date(ends_on) between date('%(start)s') and date('%(end)s'))
			or (date(starts_on) <= date('%(start)s') and date(ends_on) >= date('%(end)s'))
		) or (
			date(starts_on) <= date('%(start)s') and ifnull(repeat_this_event,0)=1 and
			ifnull(repeat_till, "3000-01-01") > date('%(start)s')
		))
		%(reminder_condition)s
		and (event_type='Public' or owner='%(user)s'
		or exists(select name from `tabDocShare` where
			tabDocShare.share_doctype="Event" and `tabDocShare`.share_name=tabEvent.name
			and tabDocShare.user='******')
		or exists(select * from `tabEvent Role` where
			`tabEvent Role`.parent=tabEvent.name
			and `tabEvent Role`.role in ('%(roles)s')))
		order by starts_on""" % {
        "start":
        start,
        "end":
        end,
        "reminder_condition":
        "and ifnull(send_reminder,0)=1" if for_reminder else "",
        "user":
        user,
        "roles":
        "', '".join(roles)
    },
                           as_dict=1)

    # process recurring events
    start = start.split(" ")[0]
    end = end.split(" ")[0]
    add_events = []
    remove_events = []

    def add_event(e, date):
        new_event = e.copy()

        enddate = add_days(date,int(date_diff(e.ends_on.split(" ")[0], e.starts_on.split(" ")[0]))) \
         if (e.starts_on and e.ends_on) else date
        new_event.starts_on = date + " " + e.starts_on.split(" ")[1]
        if e.ends_on:
            new_event.ends_on = enddate + " " + e.ends_on.split(" ")[1]
        add_events.append(new_event)

    for e in events:
        if e.repeat_this_event:
            event_start, time_str = e.starts_on.split(" ")
            if e.repeat_till == None or "":
                repeat = "3000-01-01"
            else:
                repeat = e.repeat_till
            if e.repeat_on == "Every Year":
                start_year = cint(start.split("-")[0])
                end_year = cint(end.split("-")[0])
                event_start = "-".join(event_start.split("-")[1:])

                # repeat for all years in period
                for year in range(start_year, end_year + 1):
                    date = str(year) + "-" + event_start
                    if date >= start and date <= end and date <= repeat:
                        add_event(e, date)

                remove_events.append(e)

            if e.repeat_on == "Every Month":
                date = start.split("-")[0] + "-" + start.split(
                    "-")[1] + "-" + event_start.split("-")[2]

                # last day of month issue, start from prev month!
                try:
                    getdate(date)
                except ValueError:
                    date = date.split("-")
                    date = date[0] + "-" + str(cint(date[1]) -
                                               1) + "-" + date[2]

                start_from = date
                for i in xrange(int(date_diff(end, start) / 30) + 3):
                    if date >= start and date <= end and date <= repeat and date >= event_start:
                        add_event(e, date)
                    date = add_months(start_from, i + 1)

                remove_events.append(e)

            if e.repeat_on == "Every Week":
                weekday = getdate(event_start).weekday()
                # monday is 0
                start_weekday = getdate(start).weekday()

                # start from nearest weeday after last monday
                date = add_days(start, weekday - start_weekday)

                for cnt in xrange(int(date_diff(end, start) / 7) + 3):
                    if date >= start and date <= end and date <= repeat and date >= event_start:
                        add_event(e, date)

                    date = add_days(date, 7)

                remove_events.append(e)

            if e.repeat_on == "Every Day":
                for cnt in xrange(date_diff(end, start) + 1):
                    date = add_days(start, cnt)
                    if date >= event_start and date <= end and date <= repeat \
                     and e[weekdays[getdate(date).weekday()]]:
                        add_event(e, date)
                remove_events.append(e)

    for e in remove_events:
        events.remove(e)

    events = events + add_events

    for e in events:
        # remove weekday properties (to reduce message size)
        for w in weekdays:
            del e[w]

    return events
Example #57
0
 def setup_sandbox_env(self, token):
     data = json.loads(
         frappe.db.get_value("Integration Request", token, "data"))
     setattr(self, "use_sandbox", cint(frappe._dict(data).use_sandbox) or 0)
Example #58
0
	def validate_description(self):
		'''Clean HTML description if set'''
		if cint(frappe.db.get_single_value('Stock Settings', 'clean_description_html')):
			self.description = clean_html(self.description)
Example #59
0
def get_item_details(args):
    """
		args = {
			"item_code": "",
			"warehouse": None,
			"customer": "",
			"conversion_rate": 1.0,
			"selling_price_list": None,
			"price_list_currency": None,
			"plc_conversion_rate": 1.0,
			"doctype": "",
			"name": "",
			"supplier": None,
			"transaction_date": None,
			"conversion_rate": 1.0,
			"buying_price_list": None,
			"is_subcontracted": "Yes" / "No",
			"ignore_pricing_rule": 0/1
			"project": ""
		}
	"""
    args = process_args(args)
    item_doc = frappe.get_doc("Item", args.item_code)
    item = item_doc

    validate_item_details(args, item)

    out = get_basic_details(args, item)

    get_party_item_code(args, item_doc, out)

    if out.get("warehouse"):
        out.update(get_bin_details(args.item_code, out.warehouse))

    if frappe.db.exists("Product Bundle", args.item_code):
        valuation_rate = 0.0
        bundled_items = frappe.get_doc("Product Bundle", args.item_code)

        for bundle_item in bundled_items.items:
            valuation_rate += \
             flt(get_valuation_rate(bundle_item.item_code, out.get("warehouse")).get("valuation_rate") \
              * bundle_item.qty)

        out.update({"valuation_rate": valuation_rate})

    else:
        out.update(get_valuation_rate(args.item_code, out.get("warehouse")))

    get_price_list_rate(args, item_doc, out)

    if args.customer and cint(args.is_pos):
        out.update(get_pos_profile_item_details(args.company, args))

    # update args with out, if key or value not exists
    for key, value in out.iteritems():
        if args.get(key) is None:
            args[key] = value

    out.update(get_pricing_rule_for_item(args))

    if args.get("doctype") in ("Sales Invoice", "Delivery Note"):
        if item_doc.has_serial_no == 1 and not args.serial_no:
            out.serial_no = get_serial_nos_by_fifo(args)

    if args.transaction_date and item.lead_time_days:
        out.schedule_date = out.lead_time_date = add_days(
            args.transaction_date, item.lead_time_days)

    if args.get("is_subcontracted") == "Yes":
        out.bom = get_default_bom(args.item_code)

    get_gross_profit(out)

    return out
Example #60
0
def validate_serial_no(sle, item_det):
    serial_nos = get_serial_nos(sle.serial_no) if sle.serial_no else []
    validate_material_transfer_entry(sle)

    if item_det.has_serial_no == 0:
        if serial_nos:
            frappe.throw(
                _("Item {0} is not setup for Serial Nos. Column must be blank"
                  ).format(sle.item_code), SerialNoNotRequiredError)
    elif not sle.is_cancelled:
        if serial_nos:
            if cint(sle.actual_qty) != flt(sle.actual_qty):
                frappe.throw(
                    _("Serial No {0} quantity {1} cannot be a fraction").
                    format(sle.item_code, sle.actual_qty))

            if len(serial_nos) and len(serial_nos) != abs(cint(
                    sle.actual_qty)):
                frappe.throw(
                    _("{0} Serial Numbers required for Item {1}. You have provided {2}."
                      ).format(abs(sle.actual_qty), sle.item_code,
                               len(serial_nos)), SerialNoQtyError)

            if len(serial_nos) != len(set(serial_nos)):
                frappe.throw(
                    _("Duplicate Serial No entered for Item {0}").format(
                        sle.item_code), SerialNoDuplicateError)

            for serial_no in serial_nos:
                if frappe.db.exists("Serial No", serial_no):
                    sr = frappe.db.get_value(
                        "Serial No",
                        serial_no, [
                            "name", "item_code", "batch_no", "sales_order",
                            "delivery_document_no", "delivery_document_type",
                            "warehouse", "purchase_document_type",
                            "purchase_document_no", "company"
                        ],
                        as_dict=1)

                    if sr.item_code != sle.item_code:
                        if not allow_serial_nos_with_different_item(
                                serial_no, sle):
                            frappe.throw(
                                _("Serial No {0} does not belong to Item {1}"
                                  ).format(serial_no, sle.item_code),
                                SerialNoItemError)

                    if cint(sle.actual_qty) > 0 and has_serial_no_exists(
                            sr, sle):
                        doc_name = frappe.bold(
                            get_link_to_form(sr.purchase_document_type,
                                             sr.purchase_document_no))
                        frappe.throw(
                            _("Serial No {0} has already been received in the {1} #{2}"
                              ).format(frappe.bold(serial_no),
                                       sr.purchase_document_type, doc_name),
                            SerialNoDuplicateError)

                    if (sr.delivery_document_no and sle.voucher_type
                            not in ['Stock Entry', 'Stock Reconciliation']
                            and sle.voucher_type == sr.delivery_document_type):
                        return_against = frappe.db.get_value(
                            sle.voucher_type, sle.voucher_no, 'return_against')
                        if return_against and return_against != sr.delivery_document_no:
                            frappe.throw(
                                _("Serial no {0} has been already returned").
                                format(sr.name))

                    if cint(sle.actual_qty) < 0:
                        if sr.warehouse != sle.warehouse:
                            frappe.throw(
                                _("Serial No {0} does not belong to Warehouse {1}"
                                  ).format(serial_no, sle.warehouse),
                                SerialNoWarehouseError)

                        if sle.voucher_type in ("Delivery Note",
                                                "Sales Invoice"):

                            if sr.batch_no and sr.batch_no != sle.batch_no:
                                frappe.throw(
                                    _("Serial No {0} does not belong to Batch {1}"
                                      ).format(serial_no, sle.batch_no),
                                    SerialNoBatchError)

                            if not sle.is_cancelled and not sr.warehouse:
                                frappe.throw(
                                    _("Serial No {0} does not belong to any Warehouse"
                                      ).format(serial_no),
                                    SerialNoWarehouseError)

                            # if Sales Order reference in Serial No validate the Delivery Note or Invoice is against the same
                            if sr.sales_order:
                                if sle.voucher_type == "Sales Invoice":
                                    if not frappe.db.exists(
                                            "Sales Invoice Item", {
                                                "parent": sle.voucher_no,
                                                "item_code": sle.item_code,
                                                "sales_order": sr.sales_order
                                            }):
                                        frappe.throw(
                                            _("Cannot deliver Serial No {0} of item {1} as it is reserved to fullfill Sales Order {2}"
                                              ).format(sr.name, sle.item_code,
                                                       sr.sales_order))
                                elif sle.voucher_type == "Delivery Note":
                                    if not frappe.db.exists(
                                            "Delivery Note Item", {
                                                "parent": sle.voucher_no,
                                                "item_code": sle.item_code,
                                                "against_sales_order":
                                                sr.sales_order
                                            }):
                                        invoice = frappe.db.get_value(
                                            "Delivery Note Item", {
                                                "parent": sle.voucher_no,
                                                "item_code": sle.item_code
                                            }, "against_sales_invoice")
                                        if not invoice or frappe.db.exists(
                                                "Sales Invoice Item",
                                            {
                                                "parent": invoice,
                                                "item_code": sle.item_code,
                                                "sales_order": sr.sales_order
                                            }):
                                            frappe.throw(
                                                _("Cannot deliver Serial No {0} of item {1} as it is reserved to fullfill Sales Order {2}"
                                                  ).format(
                                                      sr.name, sle.item_code,
                                                      sr.sales_order))
                            # if Sales Order reference in Delivery Note or Invoice validate SO reservations for item
                            if sle.voucher_type == "Sales Invoice":
                                sales_order = frappe.db.get_value(
                                    "Sales Invoice Item", {
                                        "parent": sle.voucher_no,
                                        "item_code": sle.item_code
                                    }, "sales_order")
                                if sales_order and get_reserved_qty_for_so(
                                        sales_order, sle.item_code):
                                    validate_so_serial_no(sr, sales_order)
                            elif sle.voucher_type == "Delivery Note":
                                sales_order = frappe.get_value(
                                    "Delivery Note Item", {
                                        "parent": sle.voucher_no,
                                        "item_code": sle.item_code
                                    }, "against_sales_order")
                                if sales_order and get_reserved_qty_for_so(
                                        sales_order, sle.item_code):
                                    validate_so_serial_no(sr, sales_order)
                                else:
                                    sales_invoice = frappe.get_value(
                                        "Delivery Note Item", {
                                            "parent": sle.voucher_no,
                                            "item_code": sle.item_code
                                        }, "against_sales_invoice")
                                    if sales_invoice:
                                        sales_order = frappe.db.get_value(
                                            "Sales Invoice Item", {
                                                "parent": sales_invoice,
                                                "item_code": sle.item_code
                                            }, "sales_order")
                                        if sales_order and get_reserved_qty_for_so(
                                                sales_order, sle.item_code):
                                            validate_so_serial_no(
                                                sr, sales_order)
                elif cint(sle.actual_qty) < 0:
                    # transfer out
                    frappe.throw(
                        _("Serial No {0} not in stock").format(serial_no),
                        SerialNoNotExistsError)
        elif cint(sle.actual_qty) < 0 or not item_det.serial_no_series:
            frappe.throw(
                _("Serial Nos Required for Serialized Item {0}").format(
                    sle.item_code), SerialNoRequiredError)
    elif serial_nos:
        # SLE is being cancelled and has serial nos
        for serial_no in serial_nos:
            check_serial_no_validity_on_cancel(serial_no, sle)