Пример #1
1
def validate_expense_against_budget(args):
	args = frappe._dict(args)
	if frappe.db.get_value("Account", {"name": args.account, "root_type": "Expense"}):
			budget = frappe.db.sql("""
				select bd.budget_allocated, cc.distribution_id
				from `tabCost Center` cc, `tabBudget Detail` bd
				where cc.name=bd.parent and cc.name=%s and account=%s and bd.fiscal_year=%s
			""", (args.cost_center, args.account, args.fiscal_year), as_dict=True)

			if budget and budget[0].budget_allocated:
				yearly_action, monthly_action = frappe.db.get_value("Company", args.company,
					["yearly_bgt_flag", "monthly_bgt_flag"])
				action_for = action = ""

				if monthly_action in ["Stop", "Warn"]:
					budget_amount = get_allocated_budget(budget[0].distribution_id,
						args.posting_date, args.fiscal_year, budget[0].budget_allocated)

					args["month_end_date"] = frappe.db.sql("select LAST_DAY(%s)",
						args.posting_date)[0][0]
					action_for, action = _("Monthly"), monthly_action

				elif yearly_action in ["Stop", "Warn"]:
					budget_amount = budget[0].budget_allocated
					action_for, action = _("Annual"), yearly_action

				if action_for:
					actual_expense = get_actual_expense(args)
					if actual_expense > budget_amount:
						frappe.msgprint(_("{0} budget for Account {1} against Cost Center {2} will exceed by {3}").format(
							_(action_for), args.account, args.cost_center, cstr(actual_expense - budget_amount)))
						if action=="Stop":
							raise BudgetError
Пример #2
0
	def validate_for_items(self, obj):
		items = []
		for d in obj.get("items"):
			if not d.qty:
				if obj.doctype == "Purchase Receipt" and d.rejected_qty:
					continue
				frappe.throw(_("Please enter quantity for Item {0}").format(d.item_code))

			# udpate with latest quantities
			bin = frappe.db.sql("""select projected_qty from `tabBin` where
				item_code = %s and warehouse = %s""", (d.item_code, d.warehouse), as_dict=1)

			f_lst ={'projected_qty': bin and flt(bin[0]['projected_qty']) or 0, 'ordered_qty': 0, 'received_qty' : 0}
			if d.doctype in ('Purchase Receipt Item', 'Purchase Invoice Item'):
				f_lst.pop('received_qty')
			for x in f_lst :
				if d.meta.get_field(x):
					d.set(x, f_lst[x])

			item = frappe.db.sql("""select is_stock_item,
				is_sub_contracted_item, end_of_life, disabled from `tabItem` where name=%s""",
				d.item_code, as_dict=1)[0]

			from erpnext.stock.doctype.item.item import validate_end_of_life
			validate_end_of_life(d.item_code, item.end_of_life, item.disabled)

			# validate stock item
			if item.is_stock_item==1 and d.qty and not d.warehouse:
				frappe.throw(_("Warehouse is mandatory for stock Item {0} in row {1}").format(d.item_code, d.idx))

			items.append(cstr(d.item_code))

		if items and len(items) != len(set(items)) and \
			not cint(frappe.db.get_single_value("Buying Settings", "allow_multiple_items") or 0):
			frappe.msgprint(_("Warning: Same item has been entered multiple times."), alert=True)
Пример #3
0
	def connect(self):
		"""Connect to **Email Account**."""
		try:
			if cint(self.settings.use_ssl):
				self.pop = Timed_POP3_SSL(self.settings.host, timeout=frappe.conf.get("pop_timeout"))
			else:
				self.pop = Timed_POP3(self.settings.host, timeout=frappe.conf.get("pop_timeout"))

			self.pop.user(self.settings.username)
			self.pop.pass_(self.settings.password)

			# connection established!
			return True

		except _socket.error:
			# Invalid mail server -- due to refusing connection
			frappe.msgprint(_('Invalid Mail Server. Please rectify and try again.'))
			raise

		except poplib.error_proto, e:
			if self.is_temporary_system_problem(e):
				return False

			else:
				frappe.msgprint(_('Invalid User Name or Support Password. Please rectify and try again.'))
				raise
Пример #4
0
	def get_pending_raw_materials(self):
		"""
			issue (item quantity) that is pending to issue or desire to transfer,
			whichever is less
		"""
		item_dict = self.get_bom_raw_materials(1)
		issued_item_qty = self.get_issued_qty()

		max_qty = flt(self.pro_doc.qty)
		for item in item_dict:
			pending_to_issue = (max_qty * item_dict[item]["qty"]) - issued_item_qty.get(item, 0)
			desire_to_transfer = flt(self.fg_completed_qty) * item_dict[item]["qty"]

			if desire_to_transfer <= pending_to_issue:
				item_dict[item]["qty"] = desire_to_transfer
			elif pending_to_issue > 0:
				item_dict[item]["qty"] = pending_to_issue
			else:
				item_dict[item]["qty"] = 0

		# delete items with 0 qty
		for item in item_dict.keys():
			if not item_dict[item]["qty"]:
				del item_dict[item]

		# show some message
		if not len(item_dict):
			frappe.msgprint(_("""All items have already been transferred for this Production Order."""))

		return item_dict
def get_shipping_rates(delivery_note, add_shipping_overhead=False):
    """get packages Information from delivery note, create the xml request to fetch the ups rates"""
    try:
        # dn = frappe.get_doc("Delivery Note",delivery_note)
        if isinstance(delivery_note, DeliveryNote):
            dn = delivery_note
        else:
            dn = frappe.get_doc(json.loads(delivery_note))

        if dn.dn_status in ["Draft", "Partialy Packed"]:
            frappe.throw("First create the packing slips")

        params = Helper.get_ups_api_params()
        rating_api = get_rating_service(params)
        request = get_ups_rating_request(dn, params)

        response = rating_api.request(request)
        shipping_rates = parse_xml_response_to_json(response)

        dn.ups_rates = json.dumps(shipping_rates)
        dn.dn_status = "UPS Rates Fetched"

        dn.save(ignore_permissions= True)

        if shipping_rates.get("03"):
            if add_shipping_overhead: add_shipping_charges(dn_name=dn.name, service_code="03")
            # return True
            return shipping_rates
        else:
            frappe.msgprint("UPS Ground rates are not available. Please select other services")
            return shipping_rates
        # return shipping_rates
    except PyUPSException, e:
        """ e is PyUPSException obj returns tuple as structured (message, request, response)"""
        frappe.throw(e[0])
Пример #6
0
def validate_filters(filters):

	if not filters.fiscal_year:
		frappe.throw(_("Fiscal Year {0} is required").format(filters.fiscal_year))

	fiscal_year = frappe.db.get_value("Fiscal Year", filters.fiscal_year, ["year_start_date", "year_end_date"], as_dict=True)
	if not fiscal_year:
		frappe.throw(_("Fiscal Year {0} does not exist").format(filters.fiscal_year))
	else:
		filters.year_start_date = getdate(fiscal_year.year_start_date)
		filters.year_end_date = getdate(fiscal_year.year_end_date)

	if not filters.from_date:
		filters.from_date = filters.year_start_date

	if not filters.to_date:
		filters.to_date = filters.year_end_date

	filters.from_date = getdate(filters.from_date)
	filters.to_date = getdate(filters.to_date)

	if filters.from_date > filters.to_date:
		frappe.throw(_("From Date cannot be greater than To Date"))

	if (filters.from_date < filters.year_start_date) or (filters.from_date > filters.year_end_date):
		frappe.msgprint(_("From Date should be within the Fiscal Year. Assuming From Date = {0}")\
			.format(formatdate(filters.year_start_date)))

		filters.from_date = filters.year_start_date

	if (filters.to_date < filters.year_start_date) or (filters.to_date > filters.year_end_date):
		frappe.msgprint(_("To Date should be within the Fiscal Year. Assuming To Date = {0}")\
			.format(formatdate(filters.year_end_date)))
		filters.to_date = filters.year_end_date
Пример #7
0
def get_data(filters):
	conditions, filters = get_conditions(filters)

        data = frappe.db.sql("""
                select t1.employee, t3.employee_name, t1.designation, t3.passport_number,
                        sum(case when t2.salary_component = 'Basic Pay' then ifnull(t2.amount,0) else 0 end) as basicpay,
                        t3.nppf_number,
                        sum(case when t2.salary_component = 'PF' then ifnull(t2.amount,0) else 0 end) as employeepf,
                        sum(case when t2.salary_component = 'PF' then ifnull(t2.amount,0) else 0 end) as employerpf,
                        sum(case when t2.salary_component = 'PF' then ifnull(t2.amount,0)*2 else 0 end) as total,
                        t1.company, t1.branch, t1.department, t1.division, t1.section,
                        t1.fiscal_year, t1.month
                from `tabSalary Slip` t1, `tabSalary Detail` t2, `tabEmployee` t3
                where t1.docstatus = 1 %s
                and t3.employee = t1.employee
                and t2.parent = t1.name
                and t2.salary_component in ('Basic Pay','PF')
                group by t1.employee, t3.employee_name, t1.designation, t3.passport_number,
                        t3.nppf_number, t1.company, t1.branch, t1.department, t1.division, t1.section,
                        t1.fiscal_year, t1.month
                """ % conditions, filters)
		
	if not data:
		msgprint(_("No Data Found for month: ") + cstr(filters.get("month")) + 
			_(" and year: ") + cstr(filters.get("fiscal_year")), raise_exception=1)
	
	return data
Пример #8
0
	def create_remarks(self):
		r = []
		if self.cheque_no:
			if self.cheque_date:
				r.append(_('Reference #{0} dated {1}').format(self.cheque_no, formatdate(self.cheque_date)))
			else:
				msgprint(_("Please enter Reference date"), raise_exception=frappe.MandatoryError)

		for d in self.get('accounts'):
			if d.reference_type=="Sales Invoice" and d.credit:
				r.append(_("{0} against Sales Invoice {1}").format(fmt_money(flt(d.credit), currency = self.company_currency), \
					d.reference_name))

			if d.reference_type=="Sales Order" and d.credit:
				r.append(_("{0} against Sales Order {1}").format(fmt_money(flt(d.credit), currency = self.company_currency), \
					d.reference_name))

			if d.reference_type == "Purchase Invoice" and d.debit:
				bill_no = frappe.db.sql("""select bill_no, bill_date
					from `tabPurchase Invoice` where name=%s""", d.reference_name)
				if bill_no and bill_no[0][0] and bill_no[0][0].lower().strip() \
						not in ['na', 'not applicable', 'none']:
					r.append(_('{0} against Bill {1} dated {2}').format(fmt_money(flt(d.debit), currency=self.company_currency), bill_no[0][0],
						bill_no[0][1] and formatdate(bill_no[0][1].strftime('%Y-%m-%d'))))

			if d.reference_type == "Purchase Order" and d.debit:
				r.append(_("{0} against Purchase Order {1}").format(fmt_money(flt(d.credit), currency = self.company_currency), \
					d.reference_name))

		if self.user_remark:
			r.append(_("Note: {0}").format(self.user_remark))

		if r:
			self.remark = ("\n").join(r) #User Remarks is not mandatory
Пример #9
0
	def validate_credit_debit_note(self):
		if self.stock_entry:
			if frappe.db.get_value("Stock Entry", self.stock_entry, "docstatus") != 1:
				frappe.throw(_("Stock Entry {0} is not submitted").format(self.stock_entry))

			if frappe.db.exists({"doctype": "Journal Entry", "stock_entry": self.stock_entry, "docstatus":1}):
				frappe.msgprint(_("Warning: Another {0} # {1} exists against stock entry {2}".format(self.voucher_type, self.name, self.stock_entry)))
Пример #10
0
	def get_balance(self):
		if not self.get('accounts'):
			msgprint(_("'Entries' cannot be empty"), raise_exception=True)
		else:
			flag, self.total_debit, self.total_credit = 0, 0, 0
			diff = flt(self.difference, self.precision("difference"))

			# If any row without amount, set the diff on that row
			if diff:
				blank_row = None
				for d in self.get('accounts'):
					if not d.credit_in_account_currency and not d.debit_in_account_currency and diff != 0:
						blank_row = d

				if not blank_row:
					blank_row = self.append('accounts', {})

				blank_row.exchange_rate = 1
				if diff>0:
					blank_row.credit_in_account_currency = diff
					blank_row.credit = diff
				elif diff<0:
					blank_row.debit_in_account_currency = abs(diff)
					blank_row.debit = abs(diff)

			self.validate_total_debit_and_credit()
	def validate_advance_jv(self, advance_table_fieldname, against_order_field):
		order_list = list(set([d.get(against_order_field) for d in self.get("items") if d.get(against_order_field)]))
		if order_list:
			account = self.get("debit_to" if self.doctype=="Sales Invoice" else "credit_to")

			jv_against_order = frappe.db.sql("""select parent, %s as against_order
				from `tabJournal Entry Account`
				where docstatus=1 and account=%s and ifnull(is_advance, 'No') = 'Yes'
				and ifnull(against_sales_order, '') in (%s)
				group by parent, against_sales_order""" %
				("against_" + against_order_field, '%s', ', '.join(['%s']*len(order_list))),
				tuple([account] + order_list), as_dict=1)

			if jv_against_order:
				order_jv_map = {}
				for d in jv_against_order:
					order_jv_map.setdefault(d.against_order, []).append(d.parent)

				advance_jv_against_si = [d.journal_entry for d in self.get(advance_table_fieldname)]

				for order, jv_list in order_jv_map.items():
					for jv in jv_list:
						if not advance_jv_against_si or jv not in advance_jv_against_si:
							frappe.msgprint(_("Journal Entry {0} is linked against Order {1}, check if it should be pulled as advance in this invoice.")
								.format(jv, order))
	def validate_multiple_billing(self, ref_dt, item_ref_dn, based_on, parentfield):
		from erpnext.controllers.status_updater import get_tolerance_for
		item_tolerance = {}
		global_tolerance = None

		for item in self.get("items"):
			if item.get(item_ref_dn):
				ref_amt = flt(frappe.db.get_value(ref_dt + " Item",
					item.get(item_ref_dn), based_on), self.precision(based_on, item))
				if not ref_amt:
					frappe.msgprint(_("Warning: System will not check overbilling since amount for Item {0} in {1} is zero").format(item.item_code, ref_dt))
				else:
					already_billed = frappe.db.sql("""select sum(%s) from `tab%s`
						where %s=%s and docstatus=1 and parent != %s""" %
						(based_on, self.doctype + " Item", item_ref_dn, '%s', '%s'),
						(item.get(item_ref_dn), self.name))[0][0]

					total_billed_amt = flt(flt(already_billed) + flt(item.get(based_on)),
						self.precision(based_on, item))

					tolerance, item_tolerance, global_tolerance = get_tolerance_for(item.item_code,
						item_tolerance, global_tolerance)

					max_allowed_amt = flt(ref_amt * (100 + tolerance) / 100)

					if total_billed_amt - max_allowed_amt > 0.01:
						frappe.throw(_("Cannot overbill for Item {0} in row {1} more than {2}. To allow overbilling, please set in Stock Settings").format(item.item_code, item.idx, max_allowed_amt))
	def validate_inspection(self):
		for d in self.get('purchase_receipt_details'):		 #Enter inspection date for all items that require inspection
			ins_reqd = frappe.db.sql("select inspection_required from `tabItem` where name = %s",
				(d.item_code,), as_dict = 1)
			ins_reqd = ins_reqd and ins_reqd[0]['inspection_required'] or 'No'
			if ins_reqd == 'Yes' and not d.qa_no:
				frappe.msgprint(_("Quality Inspection required for Item {0}").format(d.item_code))
Пример #14
0
	def validate_value(self, fieldname, condition, val2, doc=None, raise_exception=None):
		"""Check that value of fieldname should be 'condition' val2
			else throw Exception."""
		error_condition_map = {
			"in": _("one of"),
			"not in": _("none of"),
			"^": _("beginning with"),
		}

		if not doc:
			doc = self

		val1 = doc.get_value(fieldname)

		df = doc.meta.get_field(fieldname)
		val2 = doc.cast(val2, df)

		if not frappe.compare(val1, condition, val2):
			label = doc.meta.get_label(fieldname)
			condition_str = error_condition_map.get(condition, condition)
			if doc.parentfield:
				msg = _("Incorrect value in row {0}: {1} must be {2} {3}".format(doc.idx, label, condition_str, val2))
			else:
				msg = _("Incorrect value: {0} must be {1} {2}".format(label, condition_str, val2))

			# raise passed exception or True
			msgprint(msg, raise_exception=raise_exception or True)
Пример #15
0
	def reconcile(self, args):
		self.get_invoice_entries()
		self.validate_invoice()
		dr_or_cr = "credit" if self.party_type == "Customer" else "debit"
		lst = []
		for e in self.get('payments'):
			if e.invoice_type and e.invoice_number and e.allocated_amount:
				lst.append({
					'voucher_no' : e.journal_entry,
					'voucher_detail_no' : e.voucher_detail_number,
					'against_voucher_type' : e.invoice_type,
					'against_voucher'  : e.invoice_number,
					'account' : self.receivable_payable_account,
					'party_type': self.party_type,
					'party': self.party,
					'is_advance' : e.is_advance,
					'dr_or_cr' : dr_or_cr,
					'unadjusted_amt' : flt(e.amount),
					'allocated_amt' : flt(e.allocated_amount)
				})

		if lst:
			from erpnext.accounts.utils import reconcile_against_document
			reconcile_against_document(lst)
			msgprint(_("Successfully Reconciled"))
			self.get_unreconciled_entries()
Пример #16
0
	def get_items(self):
		so_list = filter(None, [d.sales_order for d in self.get('sales_orders')])
		if not so_list:
			msgprint(_("Please enter sales order in the above table"))
			return []

		item_condition = ""
		if self.fg_item:
			item_condition = ' and so_item.item_code = "' + self.fg_item + '"'

		items = frappe.db.sql("""select distinct parent, item_code, warehouse,
			(qty - ifnull(delivered_qty, 0)) as pending_qty
			from `tabSales Order Item` so_item
			where parent in (%s) and docstatus = 1 and ifnull(qty, 0) > ifnull(delivered_qty, 0)
			and exists (select * from `tabItem` item where item.name=so_item.item_code
				and (item.is_pro_applicable = 1
					or item.is_sub_contracted_item = 1)) %s""" % \
			(", ".join(["%s"] * len(so_list)), item_condition), tuple(so_list), as_dict=1)

		if self.fg_item:
			item_condition = ' and pi.item_code = "' + self.fg_item + '"'

		packed_items = frappe.db.sql("""select distinct pi.parent, pi.item_code, pi.warehouse as warehouse,
			(((so_item.qty - ifnull(so_item.delivered_qty, 0)) * pi.qty) / so_item.qty)
				as pending_qty
			from `tabSales Order Item` so_item, `tabPacked Item` pi
			where so_item.parent = pi.parent and so_item.docstatus = 1
			and pi.parent_item = so_item.item_code
			and so_item.parent in (%s) and ifnull(so_item.qty, 0) > ifnull(so_item.delivered_qty, 0)
			and exists (select * from `tabItem` item where item.name=pi.item_code
				and (item.is_pro_applicable = 1
					or item.is_sub_contracted_item = 1)) %s""" % \
			(", ".join(["%s"] * len(so_list)), item_condition), tuple(so_list), as_dict=1)

		return items + packed_items
Пример #17
0
	def validate_website_image(self):
		"""Validate if the website image is a public file"""
		auto_set_website_image = False
		if not self.website_image and self.image:
			auto_set_website_image = True
			self.website_image = self.image

		if not self.website_image:
			return

		# find if website image url exists as public
		file_doc = frappe.get_all("File", filters={
			"file_url": self.website_image
		}, fields=["name", "is_private"], order_by="is_private asc", limit_page_length=1)


		if file_doc:
			file_doc = file_doc[0]

		if not file_doc:
			if not auto_set_website_image:
				frappe.msgprint(_("Website Image {0} attached to Item {1} cannot be found")
					.format(self.website_image, self.name))

			self.website_image = None

		elif file_doc.is_private:
			if not auto_set_website_image:
				frappe.msgprint(_("Website Image should be a public file or website URL"))

			self.website_image = None
Пример #18
0
def get_exchange_rate(from_currency, to_currency):
	exchange = "%s-%s" % (from_currency, to_currency)
	value = flt(frappe.db.get_value("Currency Exchange", exchange, "exchange_rate"))

	if not value:
		try:
			cache = frappe.cache()
			key = "currency_exchange_rate:{0}:{1}".format(from_currency, to_currency)
			value = cache.get(key)

			if not value:
				import requests
				response = requests.get("http://api.fixer.io/latest", params={
					"base": from_currency,
					"symbols": to_currency
				})
				# expire in 6 hours
				response.raise_for_status()
				value = response.json()["rates"][to_currency]
				cache.setex(key, value, 6 * 60 * 60)

			return flt(value)
		except:
			frappe.msgprint(_("Unable to find exchange rate for {0} to {1}").format(from_currency, to_currency))
			return 0.0
	else:
		return value
Пример #19
0
	def stop_sales_order(self):
		self.check_modified_date()
		frappe.db.set(self, 'status', 'Stopped')
		self.update_reserved_qty()
		frappe.msgprint(_("{0} {1} status is Stopped").format(self.doctype, self.name))
		self.notify_modified()
		clear_doctype_notifications(self)
Пример #20
0
def upload():
	# get record details
	dt = frappe.form_dict.doctype
	dn = frappe.form_dict.docname
	folder = frappe.form_dict.folder
	file_url = frappe.form_dict.file_url
	filename = frappe.form_dict.filename

	if not filename and not file_url:
		frappe.msgprint(_("Please select a file or url"),
			raise_exception=True)

	# save
	if filename:
		filedata = save_uploaded(dt, dn, folder)
	elif file_url:
		filedata = save_url(file_url, dt, dn, folder)

	comment = {}
	if dt and dn:
		comment = frappe.get_doc(dt, dn).add_comment("Attachment",
			_("Added {0}").format("<a href='{file_url}' target='_blank'>{file_name}</a>".format(**filedata.as_dict())))

	return {
		"name": filedata.name,
		"file_name": filedata.file_name,
		"file_url": filedata.file_url,
		"comment": comment.as_dict() if comment else {}
	}
Пример #21
0
def update(doctype, field, value, condition='', limit=500):
	if not limit or cint(limit) > 500:
		limit = 500

	if condition:
		condition = ' where ' + condition

	if ';' in condition:
		frappe.throw(_('; not allowed in condition'))

	items = frappe.db.sql_list('''select name from `tab{0}`{1} limit 0, {2}'''.format(doctype,
		condition, limit), debug=1)
	n = len(items)

	for i, d in enumerate(items):
		doc = frappe.get_doc(doctype, d)
		doc.set(field, value)

		try:
			doc.save()
		except Exception as e:
			frappe.msgprint(_("Validation failed for {0}").format(frappe.bold(doc.name)))
			raise e

		frappe.publish_progress(float(i)*100/n,
			title = _('Updating Records'), doctype='Bulk Update', docname='Bulk Update')

	# clear messages
	frappe.local.message_log = []
	frappe.msgprint(_('{0} records updated').format(n), title=_('Success'), indicator='green')
def get_conditions(filters):
	conditions = ""
	party_accounts = []

	if filters.get("account"):
		party_accounts = [filters["account"]]
	else:
		cond = filters.get("company") and (" and company = '%s'" %
			filters["company"].replace("'", "\'")) or ""

		if filters.get("payment_type") == "Incoming":
			cond += " and master_type = 'Customer'"
		else:
			cond += " and master_type = 'Supplier'"

		party_accounts = frappe.db.sql_list("""select name from `tabAccount`
			where ifnull(master_name, '')!='' and docstatus < 2 %s""" % cond)

	if party_accounts:
		conditions += " and jvd.account in (%s)" % (", ".join(['%s']*len(party_accounts)))
	else:
		msgprint(_("No Customer or Supplier Accounts found"), raise_exception=1)

	if filters.get("from_date"): conditions += " and jv.posting_date >= '%s'" % filters["from_date"]
	if filters.get("to_date"): conditions += " and jv.posting_date <= '%s'" % filters["to_date"]

	return conditions, party_accounts
Пример #23
0
def scrap_asset(asset_name):
	asset = frappe.get_doc("Asset", asset_name)

	if asset.docstatus != 1:
		frappe.throw(_("Asset {0} must be submitted").format(asset.name))
	elif asset.status in ("Cancelled", "Sold", "Scrapped"):
		frappe.throw(_("Asset {0} cannot be scrapped, as it is already {1}").format(asset.name, asset.status))

	depreciation_series = frappe.db.get_value("Company", asset.company, "series_for_depreciation_entry")

	je = frappe.new_doc("Journal Entry")
	je.voucher_type = "Journal Entry"
	je.naming_series = depreciation_series
	je.posting_date = today()
	je.company = asset.company
	je.remark = "Scrap Entry for asset {0}".format(asset_name)

	for entry in get_gl_entries_on_asset_disposal(asset):
		entry.update({
			"reference_type": "Asset",
			"reference_name": asset_name
		})
		je.append("accounts", entry)

	je.flags.ignore_permissions = True
	je.submit()
	
	frappe.db.set_value("Asset", asset_name, "disposal_date", today())
	frappe.db.set_value("Asset", asset_name, "journal_entry_for_scrap", je.name)
	asset.set_status("Scrapped")
	
	frappe.msgprint(_("Asset scrapped via Journal Entry {0}").format(je.name))
Пример #24
0
        def remove_sal_slip(self):
		cond = ''
		for f in ['company', 'branch', 'department', 'division', 'designation', 'employee']:
			if self.get(f):
				cond += " and t1." + f + " = '" + self.get(f).replace("'", "\'") + "'"
                
                ss_list = frappe.db.sql_list("""
                                select t1.name from `tabSalary Slip` as t1
                                where t1.fiscal_year = '%s'
                                and t1.month = '%s'
                                and t1.docstatus = 0
                                %s
                                """ % (self.fiscal_year, self.month, cond))
                                
                if ss_list:
                        frappe.delete_doc("Salary Slip", frappe.db.sql_list("""
                                select t1.name from `tabSalary Slip` as t1
                                where t1.fiscal_year = '%s'
                                and t1.month = '%s'
                                and t1.docstatus = 0
                                %s
                                """ % (self.fiscal_year, self.month, cond)), for_reload=True)
                        frappe.msgprint(_("Un-submitted Salary Slip(s) for the Month:{0} and Year:{1} removed successfully.")\
                                        .format(self.month, self.fiscal_year))
                else:
                        frappe.msgprint(_("No Un-submitted Salary Slip(s) Found."))
Пример #25
0
def get_account_balance_and_party_type(account, date, company, debit=None, credit=None, exchange_rate=None):
	"""Returns dict of account balance and party type to be set in Journal Entry on selection of account."""
	if not frappe.has_permission("Account"):
		frappe.msgprint(_("No Permission"), raise_exception=1)

	company_currency = get_company_currency(company)
	account_details = frappe.db.get_value("Account", account, ["account_type", "account_currency"], as_dict=1)

	if account_details.account_type == "Receivable":
		party_type = "Customer"
	elif account_details.account_type == "Payable":
		party_type = "Supplier"
	else:
		party_type = ""

	grid_values = {
		"balance": get_balance_on(account, date),
		"party_type": party_type,
		"account_type": account_details.account_type,
		"account_currency": account_details.account_currency or company_currency,
		"exchange_rate": get_exchange_rate(account, account_details.account_currency,
			company, debit=debit, credit=credit, exchange_rate=exchange_rate)
	}

	# un-set party if not party type
	if not party_type:
		grid_values["party"] = ""

	return grid_values
Пример #26
0
	def make_thumbnail(self):
		if self.file_url:
			if self.file_url.startswith("/files"):
				try:
					image, filename, extn = get_local_image(self.file_url)
				except IOError:
					return

			else:
				try:
					image, filename, extn = get_web_image(self.file_url)
				except (requests.exceptions.HTTPError, requests.exceptions.SSLError, IOError):
					return

			thumbnail = ImageOps.fit(
				image,
				(300, 300),
				Image.ANTIALIAS
			)

			thumbnail_url = filename + "_small." + extn

			path = os.path.abspath(frappe.get_site_path("public", thumbnail_url.lstrip("/")))

			try:
				thumbnail.save(path)
				self.db_set("thumbnail_url", thumbnail_url)
			except IOError:
				frappe.msgprint("Unable to write file format for {0}".format(path))
				return

			return thumbnail_url
Пример #27
0
	def validate_fixed_asset_account(self):
		"""Validate Fixed Asset and whether Income Account Entered Exists"""
		for d in self.get('items'):
			is_asset_item = frappe.db.get_value("Item", d.item_code, "is_asset_item")
			account_type = frappe.db.get_value("Account", d.income_account, "account_type")
			if is_asset_item == 1 and account_type != 'Fixed Asset':
				msgprint(_("Account {0} must be of type 'Fixed Asset' as Item {1} is an Asset Item").format(d.income_account, d.item_code), raise_exception=True)
Пример #28
0
	def update_rfq_supplier_status(self, include_me):
		rfq_list = set([])
		for item in self.items:
			if item.request_for_quotation:
				rfq_list.add(item.request_for_quotation)
		for rfq in rfq_list:
			doc = frappe.get_doc('Request for Quotation', rfq)
			doc_sup = frappe.get_all('Request for Quotation Supplier', filters=
				{'parent': doc.name, 'supplier': self.supplier}, fields=['name', 'quote_status'])[0]

			quote_status = _('Received')
			for item in doc.items:
				sqi_count = frappe.db.sql("""
					SELECT
						COUNT(sqi.name) as count
					FROM
						`tabSupplier Quotation Item` as sqi,
						`tabSupplier Quotation` as sq
					WHERE sq.supplier = %(supplier)s
						AND sqi.docstatus = 1
						AND sq.name != %(me)s
						AND sqi.request_for_quotation_item = %(rqi)s
						AND sqi.parent = sq.name""",
					{"supplier": self.supplier, "rqi": item.name, 'me': self.name}, as_dict=1)[0]
				self_count = sum(my_item.request_for_quotation_item == item.name
					for my_item in self.items) if include_me else 0
				if (sqi_count.count + self_count) == 0:
					quote_status = _('Pending')
			if quote_status == _('Received') and doc_sup.quote_status == _('No Quote'):
				frappe.msgprint(_("{0} indicates that {1} will not provide a quotation, but all items \
					have been quoted. Updating the RFQ quote status.").format(doc.name, self.supplier))
				frappe.db.set_value('Request for Quotation Supplier', doc_sup.name, 'quote_status', quote_status)
				frappe.db.set_value('Request for Quotation Supplier', doc_sup.name, 'no_quote', 0)
			elif doc_sup.quote_status != _('No Quote'):
				frappe.db.set_value('Request for Quotation Supplier', doc_sup.name, 'quote_status', quote_status)
Пример #29
0
def export_customizations(module, doctype, sync_on_migrate=0, with_permissions=0):
	"""Export Custom Field and Property Setter for the current document to the app folder.
		This will be synced with bench migrate"""
	if not frappe.get_conf().developer_mode:
		raise Exception('Not developer mode')

	custom = {'custom_fields': [], 'property_setters': [], 'custom_perms': [],
		'doctype': doctype, 'sync_on_migrate': 1}

	def add(_doctype):
		custom['custom_fields'] += frappe.get_all('Custom Field',
			fields='*', filters={'dt': _doctype})
		custom['property_setters'] += frappe.get_all('Property Setter',
			fields='*', filters={'doc_type': _doctype})

	add(doctype)

	if with_permissions:
		custom['custom_perms'] = frappe.get_all('Custom DocPerm',
			fields='*', filters={'parent': doctype})

	# also update the custom fields and property setters for all child tables
	for d in frappe.get_meta(doctype).get_table_fields():
		export_customizations(module, d.options, sync_on_migrate, with_permissions)

	if custom["custom_fields"] or custom["property_setters"] or custom["custom_perms"]:
		folder_path = os.path.join(get_module_path(module), 'custom')
		if not os.path.exists(folder_path):
			os.makedirs(folder_path)

		path = os.path.join(folder_path, scrub(doctype)+ '.json')
		with open(path, 'w') as f:
			f.write(frappe.as_json(custom))

		frappe.msgprint(_('Customizations for <b>{0}</b> exported to:<br>{1}').format(doctype,path))
def get_conditions(filters):
    if not (filters.get("month") and filters.get("fiscal_year")):
        msgprint(_("Please select month and year"), raise_exception=1)

    filters["month"] = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"].index(
        filters["month"]
    ) + 1

    from frappe.model.document import Document

    fiscal_years = frappe.get_doc("Fiscal Year", filters["fiscal_year"])
    import datetime

    year_start = fiscal_years.year_start_date.strftime("%Y")
    year_end = fiscal_years.year_end_date.strftime("%Y")
    dt_test = datetime.datetime.strptime(year_end + "-" + str(100 + int(filters["month"]))[2:3] + "-01", "%Y-%m-%d")
    date_test = datetime.date(dt_test.year, dt_test.month, dt_test.day)
    if date_test > fiscal_years.year_end_date:
        year_target = year_start
    else:
        year_target = year_end

    from calendar import monthrange

    filters["total_days_in_month"] = monthrange(cint(year_target), filters["month"])[1]

    conditions = " and month(att_date) = %(month)s and fiscal_year = %(fiscal_year)s"

    # if filters.get("company"): conditions += " and company = %(company)s"
    if filters.get("employee"):
        conditions += " and employee = %(employee)s"

    return conditions, filters
Пример #31
0
    def get_gl_entries(self, warehouse_account=None):
        from erpnext.accounts.general_ledger import process_gl_map

        stock_rbnb = self.get_company_default("stock_received_but_not_billed")
        expenses_included_in_valuation = self.get_company_default(
            "expenses_included_in_valuation")

        gl_entries = []
        warehouse_with_no_account = []
        negative_expense_to_be_booked = 0.0
        stock_items = self.get_stock_items()
        for d in self.get("items"):
            if d.item_code in stock_items and flt(d.valuation_rate) and flt(
                    d.qty):
                if warehouse_account.get(d.warehouse):
                    stock_value_diff = frappe.db.get_value(
                        "Stock Ledger Entry", {
                            "voucher_type": "Purchase Receipt",
                            "voucher_no": self.name,
                            "voucher_detail_no": d.name
                        }, "stock_value_difference")
                    if not stock_value_diff:
                        continue
                    gl_entries.append(
                        self.get_gl_dict(
                            {
                                "account":
                                warehouse_account[d.warehouse]["name"],
                                "against":
                                stock_rbnb,
                                "cost_center":
                                d.cost_center,
                                "remarks":
                                self.get("remarks")
                                or _("Accounting Entry for Stock"),
                                "debit":
                                stock_value_diff
                            }, warehouse_account[d.warehouse]
                            ["account_currency"]))

                    # stock received but not billed
                    stock_rbnb_currency = get_account_currency(stock_rbnb)
                    gl_entries.append(self.get_gl_dict({
                     "account": stock_rbnb,
                     "against": warehouse_account[d.warehouse]["name"],
                     "cost_center": d.cost_center,
                     "remarks": self.get("remarks") or _("Accounting Entry for Stock"),
                     "credit": flt(d.base_net_amount, d.precision("base_net_amount")),
                     "credit_in_account_currency": flt(d.base_net_amount, d.precision("base_net_amount")) \
                      if stock_rbnb_currency==self.company_currency else flt(d.net_amount, d.precision("net_amount"))
                    }, stock_rbnb_currency))

                    negative_expense_to_be_booked += flt(d.item_tax_amount)

                    # Amount added through landed-cost-voucher
                    if flt(d.landed_cost_voucher_amount):
                        gl_entries.append(
                            self.get_gl_dict({
                                "account":
                                expenses_included_in_valuation,
                                "against":
                                warehouse_account[d.warehouse]["name"],
                                "cost_center":
                                d.cost_center,
                                "remarks":
                                self.get("remarks")
                                or _("Accounting Entry for Stock"),
                                "credit":
                                flt(d.landed_cost_voucher_amount),
                                "project":
                                d.project
                            }))

                    # sub-contracting warehouse
                    if flt(d.rm_supp_cost) and warehouse_account.get(
                            self.supplier_warehouse):
                        gl_entries.append(
                            self.get_gl_dict(
                                {
                                    "account":
                                    warehouse_account[
                                        self.supplier_warehouse]["name"],
                                    "against":
                                    warehouse_account[d.warehouse]["name"],
                                    "cost_center":
                                    d.cost_center,
                                    "remarks":
                                    self.get("remarks")
                                    or _("Accounting Entry for Stock"),
                                    "credit":
                                    flt(d.rm_supp_cost)
                                }, warehouse_account[self.supplier_warehouse]
                                ["account_currency"]))

                    # divisional loss adjustment
                    valuation_amount_as_per_doc = flt(d.base_net_amount, d.precision("base_net_amount")) + \
                     flt(d.landed_cost_voucher_amount) + flt(d.rm_supp_cost) + flt(d.item_tax_amount)

                    divisional_loss = flt(
                        valuation_amount_as_per_doc - stock_value_diff,
                        d.precision("base_net_amount"))

                    if divisional_loss:
                        if self.is_return or flt(d.item_tax_amount):
                            loss_account = expenses_included_in_valuation
                        else:
                            loss_account = stock_rbnb

                        gl_entries.append(
                            self.get_gl_dict(
                                {
                                    "account":
                                    loss_account,
                                    "against":
                                    warehouse_account[d.warehouse]["name"],
                                    "cost_center":
                                    d.cost_center,
                                    "remarks":
                                    self.get("remarks")
                                    or _("Accounting Entry for Stock"),
                                    "debit":
                                    divisional_loss,
                                    "project":
                                    d.project
                                }, stock_rbnb_currency))

                elif d.warehouse not in warehouse_with_no_account or \
                 d.rejected_warehouse not in warehouse_with_no_account:
                    warehouse_with_no_account.append(d.warehouse)

        # Cost center-wise amount breakup for other charges included for valuation
        valuation_tax = {}
        for tax in self.get("taxes"):
            if tax.category in ("Valuation", "Valuation and Total") and flt(
                    tax.base_tax_amount_after_discount_amount):
                if not tax.cost_center:
                    frappe.throw(
                        _("Cost Center is required in row {0} in Taxes table for type {1}"
                          ).format(tax.idx, _(tax.category)))
                valuation_tax.setdefault(tax.cost_center, 0)
                valuation_tax[tax.cost_center] += \
                 (tax.add_deduct_tax == "Add" and 1 or -1) * flt(tax.base_tax_amount_after_discount_amount)

        if negative_expense_to_be_booked and valuation_tax:
            # Backward compatibility:
            # If expenses_included_in_valuation account has been credited in against PI
            # and charges added via Landed Cost Voucher,
            # post valuation related charges on "Stock Received But Not Billed"

            negative_expense_booked_in_pi = frappe.db.sql(
                """select name from `tabPurchase Invoice Item` pi
				where docstatus = 1 and purchase_receipt=%s
				and exists(select name from `tabGL Entry` where voucher_type='Purchase Invoice'
					and voucher_no=pi.parent and account=%s)""",
                (self.name, expenses_included_in_valuation))

            if negative_expense_booked_in_pi:
                expenses_included_in_valuation = stock_rbnb

            against_account = ", ".join(
                [d.account for d in gl_entries if flt(d.debit) > 0])
            total_valuation_amount = sum(valuation_tax.values())
            amount_including_divisional_loss = negative_expense_to_be_booked
            i = 1
            for cost_center, amount in valuation_tax.items():
                if i == len(valuation_tax):
                    applicable_amount = amount_including_divisional_loss
                else:
                    applicable_amount = negative_expense_to_be_booked * (
                        amount / total_valuation_amount)
                    amount_including_divisional_loss -= applicable_amount

                gl_entries.append(
                    self.get_gl_dict({
                        "account":
                        expenses_included_in_valuation,
                        "cost_center":
                        cost_center,
                        "credit":
                        applicable_amount,
                        "remarks":
                        self.remarks or _("Accounting Entry for Stock"),
                        "against":
                        against_account
                    }))

                i += 1

        if warehouse_with_no_account:
            frappe.msgprint(
                _("No accounting entries for the following warehouses") +
                ": \n" + "\n".join(warehouse_with_no_account))

        return process_gl_map(gl_entries)
Пример #32
0
 def validate_delivery_note(self):
     for d in self.get("items"):
         if d.delivery_note:
             msgprint(_("Stock cannot be updated against Delivery Note {0}"
                        ).format(d.delivery_note),
                      raise_exception=1)
Пример #33
0
def save_data_to_Excel(month, company, year):

    filename = "PAYE.xlsm"
    Month = datetime.date(1900, int(month), 1).strftime('%B')
    Abbr = frappe.db.get_value("Company", company, "abbr")
    tin = frappe.db.get_value("Company", company, "tax_id")

    new_filename = Abbr + "-PAYE-" + Month + "-" + year + ".xlsm"

    save_path = 'fwcedu.org/private/files/'
    file_name = os.path.join(save_path, filename)
    new_file_name = os.path.join(save_path, new_filename)

    ferp = frappe.new_doc("File")
    ferp.file_name = new_filename
    ferp.folder = "Home/PAYE_TAX"
    ferp.is_private = 0
    ferp.file_url = "/private/files/PAYE_TAX/" + new_filename

    #	ferp.folder = "Home"
    #	ferp.is_private = 1
    #	ferp.file_url = "/private/files/Form_7/"+new_filename

    paye_data = []
    paye_data = get_paye_data(month, year, company)

    df = pd.DataFrame(paye_data)

    df = df.drop('emp_id', axis=1)

    #	frappe.msgprint(_("Data {0}").format(df))
    workbook1 = openpyxl.load_workbook(file_name,
                                       read_only=False,
                                       keep_vba=True)
    workbook1.template = True
    sheetname = workbook1.get_sheet_by_name('PAYE')
    sheetname['C5'] = str(tin)
    sheetname['C7'] = str(Month)
    sheetname['E7'] = str(year)
    sheetname['C9'] = str(company)

    writer = pd.ExcelWriter(new_file_name, engine='openpyxl')
    writer.book = workbook1
    writer.sheets = dict((ws.title, ws) for ws in workbook1.worksheets)

    df.to_excel(writer,
                sheet_name='PAYE',
                index=False,
                header=False,
                startrow=12,
                startcol=2)

    #	with pd.ExcelWriter(file_name) as writer:
    #		writer.book = openpyxl.load_workbook(file_name, read_only=False, keep_vba= True)
    #		df.to_excel(writer, sheet_name=sheetname, index=False, header=False, startrow=13, startcol=1)

    writer.save()
    ferp.save()
    frappe.db.sql(
        '''UPDATE `tabFile` SET file_url = %s WHERE file_name = %s''',
        ("/files/" + new_filename, new_filename),
        as_dict=True)
    frappe.msgprint(_("File created - {0}").format(new_filename))
Пример #34
0
def _execute(filters=None,
             additional_table_columns=None,
             additional_query_columns=None):
    if not filters: filters = {}

    invoice_list = get_invoices(filters, additional_query_columns)
    columns, expense_accounts, tax_accounts = get_columns(
        invoice_list, additional_table_columns)

    if not invoice_list:
        msgprint(_("No record found"))
        return columns, invoice_list

    invoice_expense_map = get_invoice_expense_map(invoice_list)
    invoice_expense_map, invoice_tax_map = get_invoice_tax_map(
        invoice_list, invoice_expense_map, expense_accounts)
    invoice_po_pr_map = get_invoice_po_pr_map(invoice_list)
    suppliers = list(set([d.supplier for d in invoice_list]))
    supplier_details = get_supplier_details(suppliers)

    company_currency = frappe.get_cached_value('Company', filters.company,
                                               "default_currency")

    data = []
    for inv in invoice_list:
        # invoice details
        purchase_order = list(
            set(invoice_po_pr_map.get(inv.name, {}).get("purchase_order", [])))
        purchase_receipt = list(
            set(
                invoice_po_pr_map.get(inv.name,
                                      {}).get("purchase_receipt", [])))
        project = list(
            set(invoice_po_pr_map.get(inv.name, {}).get("project", [])))

        row = [inv.name, inv.posting_date, inv.supplier, inv.supplier_name]

        if additional_query_columns:
            for col in additional_query_columns:
                row.append(inv.get(col))

        row += [
            supplier_details.get(inv.supplier),  # supplier_group
            inv.tax_id,
            inv.credit_to,
            inv.mode_of_payment,
            ", ".join(project),
            inv.bill_no,
            inv.bill_date,
            inv.remarks,
            ", ".join(purchase_order),
            ", ".join(purchase_receipt),
            company_currency
        ]

        # map expense values
        base_net_total = 0
        for expense_acc in expense_accounts:
            expense_amount = flt(
                invoice_expense_map.get(inv.name, {}).get(expense_acc))
            base_net_total += expense_amount
            row.append(expense_amount)

        # net total
        row.append(base_net_total or inv.base_net_total)

        # tax account
        total_tax = 0
        for tax_acc in tax_accounts:
            if tax_acc not in expense_accounts:
                tax_amount = flt(
                    invoice_tax_map.get(inv.name, {}).get(tax_acc))
                total_tax += tax_amount
                row.append(tax_amount)

        # total tax, grand total, outstanding amount & rounded total
        row += [
            total_tax, inv.base_grand_total,
            flt(inv.base_grand_total, 2), inv.outstanding_amount
        ]
        data.append(row)

    return columns, data
Пример #35
0
def get_orders():
    """Returns a list of recent orders from the eBay TradingAPI.

    This list is NOT filtered by a siteid as the API call does not filter
    by siteid.
    """

    num_days = frappe.db.get_value('eBay Manager Settings',
                                   filters=None,
                                   fieldname='ebay_sync_days')

    try:
        if num_days < 1:
            frappe.msgprint('Invalid number of days: ' + str(num_days))
    except TypeError:
        raise ValueError('Invalid type in ebay_sync_days')

    orders = []
    page = 1

    try:
        # Initialize TradingAPI; default timeout is 20.

        # Always use the US site for GetOrders as it returns fields we need
        # (which the UK site, for example, doesn't) and it doesn't filter by
        # siteID anyway
        api = Trading(config_file=PATH_TO_YAML,
                      siteid=0,
                      warnings=True,
                      timeout=20)

        while True:
            # TradingAPI results are paginated, so loop until
            # all pages have been obtained
            api.execute(
                'GetOrders', {
                    'NumberOfDays': num_days,
                    'Pagination': {
                        'EntriesPerPage': 50,
                        'PageNumber': page
                    }
                })

            orders_api = api.response.dict()
            test_for_message(orders_api)

            n_orders = int(orders_api['ReturnedOrderCountActual'])
            if n_orders > 0:
                if not isinstance(orders_api['OrderArray']['Order'], list):
                    raise AssertionError('Invalid type in get_orders!')
                orders.extend(orders_api['OrderArray']['Order'])
            if orders_api['HasMoreOrders'] == 'false':
                break
            page += 1

    except ConnectionError as e:
        handle_ebay_error(e)

    if six.PY2:
        # Convert all strings to unicode
        orders = convert_to_unicode(orders)

    return orders, num_days
Пример #36
0
def execute(filters=None):
    if not filters: filters = {}

    invoice_list = get_invoices(filters)
    columns, income_accounts, tax_accounts = get_columns(invoice_list)

    if not invoice_list:
        msgprint(_("No record found"))
        return columns, invoice_list

    invoice_income_map = get_invoice_income_map(invoice_list)
    invoice_income_map, invoice_tax_map = get_invoice_tax_map(
        invoice_list, invoice_income_map, income_accounts)

    invoice_so_dn_map = get_invoice_so_dn_map(invoice_list)
    customer_map = get_customer_details(invoice_list)
    company_currency = frappe.db.get_value("Company", filters.company,
                                           "default_currency")
    mode_of_payments = get_mode_of_payments([inv.name for inv in invoice_list])

    data = []
    for inv in invoice_list:
        # invoice details
        sales_order = list(
            set(invoice_so_dn_map.get(inv.name, {}).get("sales_order", [])))
        delivery_note = list(
            set(invoice_so_dn_map.get(inv.name, {}).get("delivery_note", [])))

        row = [
            inv.name, inv.posting_date, inv.customer, inv.customer_name,
            customer_map.get(inv.customer, {}).get("customer_group"),
            customer_map.get(inv.customer, {}).get("territory"), inv.debit_to,
            ", ".join(mode_of_payments.get(inv.name,
                                           [])), inv.project, inv.remarks,
            ", ".join(sales_order), ", ".join(delivery_note), company_currency
        ]

        # map income values
        base_net_total = 0
        for income_acc in income_accounts:
            income_amount = flt(
                invoice_income_map.get(inv.name, {}).get(income_acc))
            base_net_total += income_amount
            row.append(income_amount)

        # net total
        row.append(base_net_total or inv.base_net_total)

        # tax account
        total_tax = 0
        for tax_acc in tax_accounts:
            if tax_acc not in income_accounts:
                tax_amount = flt(
                    invoice_tax_map.get(inv.name, {}).get(tax_acc))
                total_tax += tax_amount
                row.append(tax_amount)

        # total tax, grand total, outstanding amount & rounded total
        row += [
            total_tax, inv.base_grand_total, inv.base_rounded_total,
            inv.outstanding_amount
        ]

        data.append(row)

    return columns, data
Пример #37
0
 def check_warrant_number(self):
     if not self.custom_warrant:
         frappe.msgprint(_("Custom Warrant Number is Required"),
                         raise_exception=True)
Пример #38
0
 def validate_write_off_account(self):
     if flt(self.write_off_amount) and not self.write_off_account:
         msgprint(_("Please enter Write Off Account"), raise_exception=1)
Пример #39
0
def makeBackOrder(so,method):
	frappe.msgprint("Test")
	for row in so.items:
		if row.projected_qty<0:
			available=row.qty
		else:
			available=row.qty-row.projected_qty

		if row.projected_qty<row.qty:
			data=frappe.get_doc({
					"docstatus": 0,
					"doctype": "Back Order",
					"name": "New Back Order 1",
					"__islocal": 1,
					"__unsaved": 1,
					"naming_series": "SO-",
					"transaction_date": so.transaction_date,
					"items": [{
					"docstatus": 0,
					"doctype": "Back Order Item",
					"name": "New Back Order Item 1",
					"__islocal": 1,
					"__unsaved": 1,
					"owner":str(frappe.session.user),
					"parent": "New Back Order 1",
					"parentfield": "items",
					"parenttype": "Back Order",
					"customer": so.customer,
					"item_code": row.item_code,
					"order_qty": row.qty,
					"available_qty": row.projected_qty,
					"back_qty": available,
					"sales_order_number":so.name
					}]
				})
			doc=data.insert()

	so=frappe.get_doc("Sales Order",str(so.name))
	# si = make_sales_invoice(so.name)
	# for item in so.items:
	# 		if not item.projected_qty<0:
	# 			if item.qty>item.projected_qty:
	# 				item.qty=item.projected_qty
	# 			else:
	# 				item.qty=item.qty
	# 		else:
	# 				frappe.delete_doc("Sales Invoice Item",item.name)

	# si.save()
	dt = getdate(add_days(today(),1))
	po_date=str(dt.month)+"-"+str(dt.day)+"-"+str(dt.year)
	data=frappe.get_doc({
						"docstatus": 0,
						"doctype": "Sales Invoice",
						"name": "New Sales Invoice 1",
						"__islocal": 1,
						"__unsaved": 1,
						"owner": str(frappe.session.user),
						"naming_series": "SINV-",
						"posting_date":str(po_date),
						"items": [],
						"customer_name": so.customer_name,
						"customer": so.customer,
						"address_display": so.address_display,
						"due_date": add_days(today(),1),
						"taxes_and_charges": so.taxes_and_charges,
						"customer_address": so.customer_address,
					})
	sinv_doc=data.insert()
	# if sinv_doc:
	for item in so.items:
		if not item.projected_qty<0:
			if item.qty>item.projected_qty:
				save_invoice_item(item.item_code,sinv_doc.name,item.projected_qty,item.conversion_factor,item.rate,item.price_list_rate,item.uom,item.base_price_list_rate,so.name)
			else:
				save_invoice_item(item.item_code,sinv_doc.name,item.qty,item.conversion_factor,item.rate,item.price_list_rate,item.uom,item.base_price_list_rate,so.name)



	sales_invoice_data=frappe.get_doc("Sales Invoice",sinv_doc.name)
	final=sales_invoice_data.save()
	d1=frappe.get_doc("Sales Invoice",final.name)
	arr_len=len(final.items)
	if arr_len==0:
			frappe.delete_doc("Sales Invoice",final.name)
	else:		
		sales_invoice_data.docstatus=1
		sales_invoice_data.update_stock=1
		sales_invoice_data.taxes_and_charges=so.taxes_and_charges
		final1=sales_invoice_data.save()
Пример #40
0
 def validate_item_code(self):
     for d in self.get('items'):
         if not d.item_code:
             msgprint(_("Item Code required at Row No {0}").format(d.idx),
                      raise_exception=True)
Пример #41
0
    def allow_property_change(self, prop, meta_df, df):
        if prop == "fieldtype":
            self.validate_fieldtype_change(df, meta_df[0].get(prop),
                                           df.get(prop))

        elif prop == "length":
            old_value_length = cint(meta_df[0].get(prop))
            new_value_length = cint(df.get(prop))

            if new_value_length and (old_value_length > new_value_length):
                self.check_length_for_fieldtypes.append({
                    'df':
                    df,
                    'old_value':
                    meta_df[0].get(prop)
                })
                self.validate_fieldtype_length()
            else:
                self.flags.update_db = True

        elif prop == "allow_on_submit" and df.get(prop):
            if not frappe.db.get_value("DocField", {
                    "parent": self.doc_type,
                    "fieldname": df.fieldname
            }, "allow_on_submit"):
                frappe.msgprint(_("Row {0}: Not allowed to enable Allow on Submit for standard fields")\
                 .format(df.idx))
                return False

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

        elif prop == "in_list_view" and df.get(prop) \
         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))
            return False

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

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

        elif (prop == "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))
            return False

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

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

        elif (prop == 'in_global_search'
              and df.in_global_search != meta_df[0].get("in_global_search")):
            self.flags.rebuild_doctype_for_global_search = True

        return True
Пример #42
0
def package_buy(doc, method):
    customer = doc.customer
    tday = today()
    flag = False
    # frappe.errprint(package)

    pacakage_list = frappe.db.sql("select package_name from tabMembership",
                                  as_list=1)
    pl = [x[0] for x in pacakage_list]
    frappe.errprint([pacakage_list, pl])

    for p in doc.get("items"):
        frappe.errprint([p.item_code, pl])
        if p.item_code in pl:
            frappe.errprint("successfull match")
            mem = frappe.get_doc("Membership", p.item_code)
            if mem.is_enabled:
                flag = True
                for it in mem.get("services"):
                    frappe.errprint("iteration in progress")
                    cp = frappe.new_doc("Customer wise package")
                    cp.customer = customer
                    cp.package = p.item_code
                    cp.services = it.services
                    cp.quantity_issued = it.number_of_services
                    cp.valid_from = datetime.strptime(tday, "%Y-%m-%d")
                    cp.valid_to = cp.valid_from + timedelta(days=it.validity)
                    cp.used_qty = 0
                    cp.insert(ignore_permissions=True)
                    cp.submit()
                    frappe.errprint("successfull submission ")
            else:
                frappe.errprint("not enabled")
                frappe.msgprint("Package inactive")
        cwp = frappe.db.sql("select * from `tabCustomer wise package",
                            as_list=1)
        check = [x[0] for x in cwp]
        frappe.errprint(check)

        for c in check:
            cp = frappe.get_doc("Customer wise package", c)
            # frappe.errprint(cp)
            # frappe.errprint(cp.customer)
            # frappe.errprint(p.item_code)
            # frappe.errprint(customer)
            # frappe.errprint(cp.services)
            aaj = date.today().strftime('%Y-%m-%d')
            end_date = date.strftime(cp.valid_to, '%Y-%m-%d')
            if aaj < end_date:
                frappe.errprint(cp.valid_to)
            if customer == cp.customer and p.item_code == cp.services and cp.quantity_issued != cp.used_qty and aaj < end_date:
                # frappe.errprint(p.amount)
                frappe.errprint(doc.outstanding_amount)
                frappe.errprint("in package with " + cp.services + "for " +
                                cp.package)
                p.rate = 0
                p.amount = 0
                #calculate_taxes_and_totals.calculate_totals()
                #calculate_net_total()
                doc.package_name = cp.package
                cp.used_qty = cp.used_qty + 1
                cp.save
                flag = True
                break
        if not flag:
            frappe.msgprint("no package available")
Пример #43
0
def get_columns(filters, tempColoumn):
	columns = []
	# tempColoumn = []
	frappe.msgprint(len(tempColoumn))
	if filters.get("presentation_currency"):
		currency = filters["presentation_currency"]
	else:
		if filters.get("company"):
			currency = get_company_currency(filters["company"])
		else:
			company = get_default_company()
			currency = get_company_currency(company)

	columns = [
		{
			"label": _("Jv Ref"),
			"fieldname": "voucher_no",
			"fieldtype": "Dynamic Link",
			"options": "voucher_type",
			"width": 180
		},
		{
			"label": _("Posting Date"),
			"fieldname": "posting_date",
			"fieldtype": "Date",
			"width": 90
		},
		{
			"label": _("Particulars"),
			"fieldname": "particulars",
			"width": 120
		},
		{
			"label": _("Party Name"),
			"fieldname": "party_name",
			"width": 100
		},
		{
			"label": _("Party"),
			"fieldname": "party_type",
			"width": 100
		},
		{
			"label": _("Company"),
			"fieldname": "company",
			"width": 180
		},
		{
			"label": _("Voucher Type"),
			"fieldname": "voucher_type",
			"width": 120
		},
		{
			"label": _("Bill No"),
			"fieldname": "bill_no",
			"width": 100
		},
		{
			"label": _("Bill Date"),
			"fieldname": "bill_date",
			"fieldtype": "Date",
			"width": 90
		},
		{
			"label": _("Remarks"),
			"fieldname": "remark",
			"width": 400
		},
		{
			"label": _("Ref No."),
			"fieldname": "bill_no",
			"width": 100
		},
		{
			"label": _("Ref Date"),
			"fieldname": "bill_date",
			"fieldtype": "Date",
			"width": 90
		},
		{
			"label": _("Is Advance"),
			"fieldname": "is_advance",
			"width": 90
		},
		{
			"label": _("Is Opening"),
			"fieldname": "is_opening",
			"width": 90
		},
		{
			"label": _("Created by whom"),
			"fieldname": "created_by_whom",
			"width": 90
		},
		{
			"label": _("Modified by whom"),
			"fieldname": "modified_by_whom",
			"width": 90
		},
		{
			"label": _("Gross ({0})".format(currency)),
			"fieldname": "gross",
			"fieldtype": "Float",
			"width": 100
		}
	]

	if tempColoumn:
		for i in tempColoumn:
			columns.append(i)

	return columns
Пример #44
0
def get_fiscal_years(transaction_date=None,
                     fiscal_year=None,
                     label="Date",
                     verbose=1,
                     company=None,
                     as_dict=False):
    fiscal_years = frappe.cache().hget("fiscal_years", company) or []

    if not fiscal_years:
        # if year start date is 2012-04-01, year end date should be 2013-03-31 (hence subdate)
        cond = ""
        if fiscal_year:
            cond += " and fy.name = {0}".format(frappe.db.escape(fiscal_year))
        if company:
            cond += """
				and (not exists (select name
					from `tabFiscal Year Company` fyc
					where fyc.parent = fy.name)
				or exists(select company
					from `tabFiscal Year Company` fyc
					where fyc.parent = fy.name
					and fyc.company=%(company)s)
				)
			"""

        fiscal_years = frappe.db.sql("""
			select
				fy.name, fy.year_start_date, fy.year_end_date
			from
				`tabFiscal Year` fy
			where
				disabled = 0 {0}
			order by
				fy.year_start_date desc""".format(cond), {"company": company},
                                     as_dict=True)

        frappe.cache().hset("fiscal_years", company, fiscal_years)

    if transaction_date:
        transaction_date = getdate(transaction_date)

    for fy in fiscal_years:
        matched = False
        if fiscal_year and fy.name == fiscal_year:
            matched = True

        if (transaction_date
                and getdate(fy.year_start_date) <= transaction_date
                and getdate(fy.year_end_date) >= transaction_date):
            matched = True

        if matched:
            if as_dict:
                return (fy, )
            else:
                return ((fy.name, fy.year_start_date, fy.year_end_date), )

    error_msg = _("""{0} {1} not in any active Fiscal Year.""").format(
        label, formatdate(transaction_date))
    if verbose == 1: frappe.msgprint(error_msg)
    raise FiscalYearError(error_msg)
Пример #45
0
 def get_gl_entries(self):
     gl_entry = []
     if self.is_return:
         gl_entry.append(
             self.get_gl_dict(
                 {
                     "posting_date":
                     self.posting_date,
                     "account":
                     self.payment_account
                     if self.type != 'Employee' else frappe.db.get_value(
                         "Account", {
                             "parent_account": self.payment_account,
                             "account_currency": self.currency
                         }, "name"),
                     "account_currency":
                     self.currency,
                     "credit":
                     self.base_amount,
                     "credit_in_account_currency":
                     self.amount,
                     "conversion_rate":
                     self.conversion_rate,
                     "against":
                     self.from_account,
                     "party_type":
                     '' if self.type != 'Employee' else 'Employee Account',
                     "party":
                     '' if self.type != 'Employee' else frappe.db.get_value(
                         "Employee Account", {
                             "employee": self.employee,
                             "currency": self.currency
                         }, "name"),
                     "against_voucher_type":
                     self.doctype,
                     "against_voucher":
                     self.name,
                     "remarks":
                     self.user_remark,
                     "cost_center":
                     self.cost_center
                 },
                 item=self))
         gl_entry.append(
             self.get_gl_dict(
                 {
                     "posting_date":
                     self.posting_date,
                     "account":
                     self.from_account,
                     "account_currency":
                     self.currency,
                     "debit":
                     self.base_amount,
                     "debit_in_account_currency":
                     self.amount,
                     "conversion_rate":
                     self.conversion_rate,
                     "against":
                     self.payment_account
                     if self.type != 'Employee' else frappe.db.get_value(
                         "Account", {
                             "parent_account": self.payment_account,
                             "account_currency": self.currency
                         }, "name"),
                     "remarks":
                     self.user_remark,
                     "cost_center":
                     self.cost_center
                 },
                 item=self))
     else:
         party_type = ''
         party = ''
         if self.type == 'Employee':
             party_type == 'Employee Account'
             party = frappe.db.get_value("Employee Account", {
                 "employee": self.employee,
                 "currency": self.currency
             }, "name")
         elif self.type == 'Supplier':
             frappe.msgprint("test")
             party_type == self.type
             ##frappe.msgprint("{0}".format(self.type))
             ##frappe.msgprint("party_type={0}".format(party_type))
             party = self.supplier
         ##frappe.msgprint("{0}-{1}".format(party_type,party))
         ##frappe.msgprint("{0}-{1}".format(self.type,self.supplier))
         ##frappe.msgprint("{0}".format(self))
         gl_entry.append(
             self.get_gl_dict(
                 {
                     "posting_date":
                     self.posting_date,
                     "account":
                     self.payment_account
                     if self.type != 'Employee' else frappe.db.get_value(
                         "Account", {
                             "parent_account": self.payment_account,
                             "account_currency": self.currency
                         }, "name"),
                     "account_currency":
                     self.currency,
                     "debit":
                     self.base_amount,
                     "debit_in_account_currency":
                     self.amount,
                     "conversion_rate":
                     self.conversion_rate,
                     "against":
                     self.from_account,
                     "party_type":
                     'Supplier' if self.type == 'Supplier' else
                     ('Employee Account'
                      if self.type == 'Employee' else ''),
                     "party":
                     party,
                     "remarks":
                     self.user_remark,
                     "cost_center":
                     self.cost_center
                 },
                 item=self))
         gl_entry.append(
             self.get_gl_dict(
                 {
                     "posting_date":
                     self.posting_date,
                     "account":
                     self.from_account,
                     "account_currency":
                     self.currency,
                     "credit":
                     self.base_amount,
                     "credit_in_account_currency":
                     self.amount,
                     "conversion_rate":
                     self.conversion_rate,
                     "against":
                     self.payment_account
                     if self.type != 'Employee' else frappe.db.get_value(
                         "Account", {
                             "parent_account": self.payment_account,
                             "account_currency": self.currency
                         }, "name"),
                     "remarks":
                     self.user_remark,
                     "cost_center":
                     self.cost_center
                 },
                 item=self))
     return gl_entry
Пример #46
0
 def validate_items_mandatory(self):
     rows = [d.item_code for d in self.get("items")]
     if not rows:
         frappe.msgprint(_("No Items to pack"), raise_exception=1)
Пример #47
0
def get_items_for_material_requests(doc, warehouses=None):
    if isinstance(doc, string_types):
        doc = frappe._dict(json.loads(doc))

    warehouse_list = []
    if warehouses:
        if isinstance(warehouses, string_types):
            warehouses = json.loads(warehouses)

        for row in warehouses:
            child_warehouses = frappe.db.get_descendants(
                'Warehouse', row.get("warehouse"))
            if child_warehouses:
                warehouse_list.extend(child_warehouses)
            else:
                warehouse_list.append(row.get("warehouse"))

    if warehouse_list:
        warehouses = list(set(warehouse_list))

        if doc.get("for_warehouse") and doc.get("for_warehouse") in warehouses:
            warehouses.remove(doc.get("for_warehouse"))

        warehouse_list = None

    doc['mr_items'] = []

    po_items = doc.get('po_items') if doc.get('po_items') else doc.get('items')
    # Check for empty table or empty rows
    if not po_items or not [
            row.get('item_code') for row in po_items if row.get('item_code')
    ]:
        frappe.throw(_(
            "Items to Manufacture are required to pull the Raw Materials associated with it."
        ),
                     title=_("Items Required"))

    company = doc.get('company')
    ignore_existing_ordered_qty = doc.get('ignore_existing_ordered_qty')
    include_safety_stock = doc.get('include_safety_stock')

    so_item_details = frappe._dict()
    for data in po_items:
        planned_qty = data.get('required_qty') or data.get('planned_qty')
        ignore_existing_ordered_qty = data.get(
            'ignore_existing_ordered_qty') or ignore_existing_ordered_qty
        warehouse = doc.get('for_warehouse')

        item_details = {}
        if data.get("bom") or data.get("bom_no"):
            if data.get('required_qty'):
                bom_no = data.get('bom')
                include_non_stock_items = 1
                include_subcontracted_items = 1 if data.get(
                    'include_exploded_items') else 0
            else:
                bom_no = data.get('bom_no')
                include_subcontracted_items = doc.get(
                    'include_subcontracted_items')
                include_non_stock_items = doc.get('include_non_stock_items')

            if not planned_qty:
                frappe.throw(
                    _("For row {0}: Enter Planned Qty").format(
                        data.get('idx')))

            if bom_no:
                if data.get('include_exploded_items'
                            ) and include_subcontracted_items:
                    # fetch exploded items from BOM
                    item_details = get_exploded_items(item_details,
                                                      company,
                                                      bom_no,
                                                      include_non_stock_items,
                                                      planned_qty=planned_qty)
                else:
                    item_details = get_subitems(doc,
                                                data,
                                                item_details,
                                                bom_no,
                                                company,
                                                include_non_stock_items,
                                                include_subcontracted_items,
                                                1,
                                                planned_qty=planned_qty)
        elif data.get('item_code'):
            item_master = frappe.get_doc('Item', data['item_code']).as_dict()
            purchase_uom = item_master.purchase_uom or item_master.stock_uom
            conversion_factor = 0
            for d in item_master.get("uoms"):
                if d.uom == purchase_uom:
                    conversion_factor = d.conversion_factor

            item_details[item_master.name] = frappe._dict({
                'item_name':
                item_master.item_name,
                'default_bom':
                doc.bom,
                'purchase_uom':
                purchase_uom,
                'default_warehouse':
                item_master.default_warehouse,
                'min_order_qty':
                item_master.min_order_qty,
                'default_material_request_type':
                item_master.default_material_request_type,
                'qty':
                planned_qty or 1,
                'is_sub_contracted':
                item_master.is_subcontracted_item,
                'item_code':
                item_master.name,
                'description':
                item_master.description,
                'stock_uom':
                item_master.stock_uom,
                'conversion_factor':
                conversion_factor,
                'safety_stock':
                item_master.safety_stock
            })

        sales_order = doc.get("sales_order")

        for item_code, details in iteritems(item_details):
            so_item_details.setdefault(sales_order, frappe._dict())
            if item_code in so_item_details.get(sales_order, {}):
                so_item_details[sales_order][item_code][
                    'qty'] = so_item_details[sales_order][item_code].get(
                        "qty", 0) + flt(details.qty)
            else:
                so_item_details[sales_order][item_code] = details

    mr_items = []
    for sales_order, item_code in iteritems(so_item_details):
        item_dict = so_item_details[sales_order]
        for details in item_dict.values():
            bin_dict = get_bin_details(details, doc.company, warehouse)
            bin_dict = bin_dict[0] if bin_dict else {}

            if details.qty > 0:
                items = get_material_request_items(
                    details, sales_order, company, ignore_existing_ordered_qty,
                    include_safety_stock, warehouse, bin_dict)
                if items:
                    mr_items.append(items)

    if not ignore_existing_ordered_qty and warehouses:
        new_mr_items = []
        for item in mr_items:
            get_materials_from_other_locations(item, warehouses, new_mr_items,
                                               company)

        mr_items = new_mr_items

    if not mr_items:
        to_enable = frappe.bold(_("Ignore Existing Projected Quantity"))
        warehouse = frappe.bold(doc.get('for_warehouse'))
        message = _(
            "As there are sufficient raw materials, Material Request is not required for Warehouse {0}."
        ).format(warehouse) + "<br><br>"
        message += _("If you still want to proceed, please enable {0}."
                     ).format(to_enable)

        frappe.msgprint(message, title=_("Note"))

    return mr_items
Пример #48
0
    def make_accrual_jv_entry(self):
        journal_entry = frappe.new_doc('Journal Entry')

        journal_entry.voucher_type = 'Journal Entry'
        journal_entry.user_remark = self.user_remark
        journal_entry.cheque_date = self.posting_date
        journal_entry.cheque_no = self.name
        journal_entry.company = self.company
        journal_entry.posting_date = nowdate()
        journal_entry.multi_currency = 1
        accounts = []
        ##
        if self.is_return:
            accounts.append({
                "account":
                self.payment_account
                if self.type != 'Employee' else frappe.db.get_value(
                    "Account", {
                        "parent_account": self.payment_account,
                        "account_currency": self.currency
                    }, "name"),
                "account_currency":
                self.currency,
                "credit":
                self.base_amount,
                "credit_in_account_currency":
                self.amount,
                "conversion_rate":
                self.conversion_rate,
                "against":
                self.from_account,
                "party_type":
                '' if self.type != 'Employee' else 'Employee Account',
                "party":
                '' if self.type != 'Employee' else frappe.db.get_value(
                    "Employee Account", {
                        "employee": self.employee,
                        "currency": self.currency
                    }, "name"),
                "against_voucher_type":
                self.doctype,
                "against_voucher":
                self.name,
                "remarks":
                self.user_remark,
                "cost_center":
                self.cost_center,
                "reference_type":
                self.doctype,
                "reference_name":
                self.name
            })
            accounts.append({
                "account":
                self.from_account,
                "account_currency":
                self.currency,
                "debit":
                self.base_amount,
                "debit_in_account_currency":
                self.amount,
                "conversion_rate":
                self.conversion_rate,
                "against":
                self.payment_account
                if self.type != 'Employee' else frappe.db.get_value(
                    "Account", {
                        "parent_account": self.payment_account,
                        "account_currency": self.currency
                    }, "name"),
                "remarks":
                self.user_remark,
                "cost_center":
                self.cost_center,
                "reference_type":
                self.doctype,
                "reference_name":
                self.name
            })
        else:
            party_type = ''
            party = ''
            if self.type == 'Employee':
                party_type == 'Employee Account'
                party = frappe.db.get_value("Employee Account", {
                    "employee": self.employee,
                    "currency": self.currency
                }, "name")
            elif self.type == 'Supplier':
                frappe.msgprint("test")
                party_type == self.type
                party = self.supplier
            accounts.append({
                "account":
                self.payment_account
                if self.type != 'Employee' else frappe.db.get_value(
                    "Account", {
                        "parent_account": self.payment_account,
                        "account_currency": self.currency
                    }, "name"),
                "account_currency":
                self.currency,
                "debit":
                self.base_amount,
                "debit_in_account_currency":
                self.amount,
                "conversion_rate":
                self.conversion_rate,
                "against":
                self.from_account,
                "party_type":
                'Supplier' if self.type == 'Supplier' else
                ('Employee Account' if self.type == 'Employee' else ''),
                "party":
                party,
                "remarks":
                self.user_remark,
                "cost_center":
                self.cost_center,
                "reference_type":
                self.doctype,
                "reference_name":
                self.name
            })
            accounts.append({
                "account":
                self.from_account,
                "account_currency":
                self.currency,
                "credit":
                self.base_amount,
                "credit_in_account_currency":
                self.amount,
                "conversion_rate":
                self.conversion_rate,
                "against":
                self.payment_account
                if self.type != 'Employee' else frappe.db.get_value(
                    "Account", {
                        "parent_account": self.payment_account,
                        "account_currency": self.currency
                    }, "name"),
                "remarks":
                self.user_remark,
                "cost_center":
                self.cost_center,
                "reference_type":
                self.doctype,
                "reference_name":
                self.name
            })
        ##
        journal_entry.set("accounts", accounts)
        journal_entry.title = self.purpose
        try:
            journal_entry.save()
        except Exception as e:
            frappe.msgprint(e)

        self.jv_created = 1
        self.save()
        frappe.msgprint(
            _("Journal Entry Created for Currenct Document {0} ").format(
                journal_entry.name))

        self.reload()
        return journal_entry
Пример #49
0
    def validate(self):
        """Check if change in varchar length isn't truncating the columns"""
        if self.is_new():
            return

        self.setup_table_columns()

        columns = [
            frappe._dict({
                "fieldname": f,
                "fieldtype": "Data"
            }) for f in frappe.db.STANDARD_VARCHAR_COLUMNS
        ]
        columns += self.columns.values()

        for col in columns:
            if len(col.fieldname) >= 64:
                frappe.throw(
                    _("Fieldname is limited to 64 characters ({0})").format(
                        frappe.bold(col.fieldname)))

            if 'varchar' in frappe.db.type_map.get(col.fieldtype, ()):

                # validate length range
                new_length = cint(col.length) or cint(frappe.db.VARCHAR_LEN)
                if not (1 <= new_length <= 1000):
                    frappe.throw(
                        _("Length of {0} should be between 1 and 1000").format(
                            col.fieldname))

                current_col = self.current_columns.get(col.fieldname, {})
                if not current_col:
                    continue
                current_type = self.current_columns[col.fieldname]["type"]
                current_length = re.findall(r'varchar\(([\d]+)\)',
                                            current_type)
                if not current_length:
                    # case when the field is no longer a varchar
                    continue
                current_length = current_length[0]
                if cint(current_length) != cint(new_length):
                    try:
                        # check for truncation
                        max_length = frappe.db.sql(
                            """SELECT MAX(CHAR_LENGTH(`{fieldname}`)) FROM `tab{doctype}`"""
                            .format(fieldname=col.fieldname,
                                    doctype=self.doctype))

                    except frappe.db.InternalError as e:
                        if frappe.db.is_missing_column(e):
                            # Unknown column 'column_name' in 'field list'
                            continue
                        raise

                    if max_length and max_length[0][
                            0] and max_length[0][0] > new_length:
                        if col.fieldname in self.columns:
                            self.columns[col.fieldname].length = current_length
                        info_message = _("Reverting length to {0} for '{1}' in '{2}'. Setting the length as {3} will cause truncation of data.") \
                         .format(current_length, col.fieldname, self.doctype, new_length)
                        frappe.msgprint(info_message)
Пример #50
0
    def make_material_request(self):
        '''Create Material Requests grouped by Sales Order and Material Request Type'''
        material_request_list = []
        material_request_map = {}

        for item in self.mr_items:
            item_doc = frappe.get_cached_doc('Item', item.item_code)

            material_request_type = item.material_request_type or item_doc.default_material_request_type

            # key for Sales Order:Material Request Type:Customer
            key = '{}:{}:{}'.format(item.sales_order, material_request_type,
                                    item_doc.customer or '')
            schedule_date = add_days(nowdate(), cint(item_doc.lead_time_days))

            if not key in material_request_map:
                # make a new MR for the combination
                material_request_map[key] = frappe.new_doc("Material Request")
                material_request = material_request_map[key]
                material_request.update({
                    "transaction_date": nowdate(),
                    "status": "Draft",
                    "company": self.company,
                    'material_request_type': material_request_type,
                    'customer': item_doc.customer or ''
                })
                material_request_list.append(material_request)
            else:
                material_request = material_request_map[key]

            # add item
            material_request.append("items", {
             "item_code": item.item_code,
             "from_warehouse": item.from_warehouse,
             "qty": item.quantity,
             "schedule_date": schedule_date,
             "warehouse": item.warehouse,
             "sales_order": item.sales_order,
             'production_plan': self.name,
             'material_request_plan_item': item.name,
             "project": frappe.db.get_value("Sales Order", item.sales_order, "project") \
              if item.sales_order else None
            })

        for material_request in material_request_list:
            # submit
            material_request.flags.ignore_permissions = 1
            material_request.run_method("set_missing_values")

            if self.get('submit_material_request'):
                material_request.submit()
            else:
                material_request.save()

        frappe.flags.mute_messages = False

        if material_request_list:
            material_request_list = ["""<a href="/app/Form/Material Request/{0}">{1}</a>""".format(m.name, m.name) \
             for m in material_request_list]
            msgprint(_("{0} created").format(comma_and(material_request_list)))
        else:
            msgprint(_("No material request created"))
Пример #51
0
def send_one(email, smtpserver=None, auto_commit=True, now=False, from_test=False):
	'''Send Email Queue with given smtpserver'''

	email = frappe.db.sql('''select
			name, status, communication, message, sender, reference_doctype,
			reference_name, unsubscribe_param, unsubscribe_method, expose_recipients,
			show_as_cc, add_unsubscribe_link, attachments, retry
		from
			`tabEmail Queue`
		where
			name=%s
		for update''', email, as_dict=True)[0]

	recipients_list = frappe.db.sql('''select name, recipient, status from
		`tabEmail Queue Recipient` where parent=%s''',email.name,as_dict=1)

	if frappe.are_emails_muted():
		frappe.msgprint(_("Emails are muted"))
		return

	if cint(frappe.defaults.get_defaults().get("hold_queue"))==1 :
		return

	if email.status not in ('Not Sent','Partially Sent') :
		# rollback to release lock and return
		frappe.db.rollback()
		return

	frappe.db.sql("""update `tabEmail Queue` set status='Sending', modified=%s where name=%s""",
		(now_datetime(), email.name), auto_commit=auto_commit)

	if email.communication:
		frappe.get_doc('Communication', email.communication).set_delivery_status(commit=auto_commit)

	try:
		if not frappe.flags.in_test:
			if not smtpserver: smtpserver = SMTPServer()
			smtpserver.setup_email_account(email.reference_doctype, sender=email.sender)

		for recipient in recipients_list:
			if recipient.status != "Not Sent":
				continue

			message = prepare_message(email, recipient.recipient, recipients_list)
			if not frappe.flags.in_test:
				smtpserver.sess.sendmail(email.sender, recipient.recipient, encode(message))

			recipient.status = "Sent"
			frappe.db.sql("""update `tabEmail Queue Recipient` set status='Sent', modified=%s where name=%s""",
				(now_datetime(), recipient.name), auto_commit=auto_commit)

		#if all are sent set status
		if any("Sent" == s.status for s in recipients_list):
			frappe.db.sql("""update `tabEmail Queue` set status='Sent', modified=%s where name=%s""",
				(now_datetime(), email.name), auto_commit=auto_commit)
		else:
			frappe.db.sql("""update `tabEmail Queue` set status='Error', error=%s
				where name=%s""", ("No recipients to send to", email.name), auto_commit=auto_commit)
		if frappe.flags.in_test:
			frappe.flags.sent_mail = message
			return
		if email.communication:
			frappe.get_doc('Communication', email.communication).set_delivery_status(commit=auto_commit)

	except (smtplib.SMTPServerDisconnected,
			smtplib.SMTPConnectError,
			smtplib.SMTPHeloError,
			smtplib.SMTPAuthenticationError,
			JobTimeoutException):

		# bad connection/timeout, retry later

		if any("Sent" == s.status for s in recipients_list):
			frappe.db.sql("""update `tabEmail Queue` set status='Partially Sent', modified=%s where name=%s""",
				(now_datetime(), email.name), auto_commit=auto_commit)
		else:
			frappe.db.sql("""update `tabEmail Queue` set status='Not Sent', modified=%s where name=%s""",
				(now_datetime(), email.name), auto_commit=auto_commit)

		if email.communication:
			frappe.get_doc('Communication', email.communication).set_delivery_status(commit=auto_commit)

		# no need to attempt further
		return

	except Exception as e:
		frappe.db.rollback()

		if email.retry < 3:
			frappe.db.sql("""update `tabEmail Queue` set status='Not Sent', modified=%s, retry=retry+1 where name=%s""",
				(now_datetime(), email.name), auto_commit=auto_commit)
		else:
			if any("Sent" == s.status for s in recipients_list):
				frappe.db.sql("""update `tabEmail Queue` set status='Partially Errored', error=%s where name=%s""",
					(text_type(e), email.name), auto_commit=auto_commit)
			else:
				frappe.db.sql("""update `tabEmail Queue` set status='Error', error=%s
					where name=%s""", (text_type(e), email.name), auto_commit=auto_commit)

		if email.communication:
			frappe.get_doc('Communication', email.communication).set_delivery_status(commit=auto_commit)

		if now:
			print(frappe.get_traceback())
			raise e

		else:
			# log to Error Log
			log('frappe.email.queue.flush', text_type(e))
Пример #52
0
def run_cron_create_xml():
    """
    # NOTE Should run sync ebay_ids before running anything else so database is up to date

    If is_auction then specify a startingBid which switches on auction mode
    """

    frappe.msgprint("Exporting all listings in QC Passed status")

    #Before doing anything sync the ebay_id to Erpnext
    update_ebay_data(multiple_error_sites=['UK'])

    design = "Pro: Classic"
    layout = "thumb gallery"
    #decline = 0.9
    #accept = 0.1
    duration = 10  # GTC = 1000
    handling_time = 1

    root = ET.Element("items")

    records = get_item_records_by_item_status()

    for r in records:
        item_code = r.name

        post_code = "NP4 0HZ"
        if is_scotland(item_code):
            post_code = "DG1 3PH"

        is_auction = False

        quantity = r.actual_qty + r.unsubmitted_prec_qty - get_draft_sales(
            item_code)

        # Don't run if quantity not matching stock locations qty
        # Items only come through if ebay_id is Null or blank - no need to exclude e.g Awaiting
        # Garagesale (see sql query)
        #if quantity > 0.0 and quantity == r.sum_sl: FUDGE THIS FOR THE MOMENT
        if quantity > 0.0 and r.sum_sl > 0.0:
            if r.sum_sl < quantity:
                quantity = r.sum_sl

            title = ""
            title += r.item_name
            category = lookup_category(r.item_group, r.item_group_ebay)

            # if an item_price use that otherwise try item.standard_rate (either case ifnull=0)
            if r.item_price == 0.0:
                ebay_price = r.price * ugssettings.VAT
            else:
                ebay_price = r.item_price * ugssettings.VAT

            #resize_images(item_code)
            #image = r.image
            ws_image = r.website_image
            ss_images_list = get_slideshow_records(r.slideshow)

            pounds, ounces = kg_to_imperial(r.net_weight)

            version = 0

            body = "<![CDATA[<br></br>"
            body += jtemplate(version, r.description, r.function_grade,
                              r.grade_details, r.condition, r.tech_details,
                              r.delivery_type, r.accessories_extras,
                              r.power_cable_included, r.power_supply_included,
                              r.remote_control_included, r.case_included,
                              r.warranty_period)

            body += footer
            body += """<br><br>sku: {}""".format(item_code)
            #body += """<br>approx (unit) weight: {}""".format(r.weight_per_unit)
            #body += """<br>approx l x w x h: {} x {} x {}""".format(r.length, r.width, r.height)
            body += "]]"

            doc = ET.SubElement(root, "item")

            ET.SubElement(doc, "bestOffer").text = "true"
            #ET.SubElement(doc, "bestOfferAutoAcceptPrice").text = str(price - (price * accept))
            #ET.SubElement(doc, "bestOfferAutoDeclinePrice").text = str(price - (price * decline))
            ET.SubElement(doc, "buyItNowPrice").text = str(ebay_price)
            ET.SubElement(doc, "category").text = category
            #ET.SubElement(doc, "category2").text =

            condition_desc, condition_id = lookup_condition(
                r.condition, r.function_grade)
            ET.SubElement(doc, "condition").text = str(condition_desc)
            ET.SubElement(doc, "conditionDescription").text = r.grade_details

            ET.SubElement(doc, "convertDescriptionToHTML").text = "false"
            ET.SubElement(doc, "convertMarkdownToHTML").text = "false"
            ET.SubElement(doc, "description").text = body
            ET.SubElement(doc, "design").text = design

            # Ensure that blank brands are set as unbranded
            if r.brand == '':
                brand = 'Unbranded'
            else:
                brand = frappe.db.escape(r.brand)

            try:
                st = """<customSpecific> <specificName>Brand</specificName> <specificValue>{}</specificValue></customSpecific>""".format(
                    brand)
                brand_xml = ET.fromstring(st)
                doc.append(brand_xml)
            except Exception:
                print('Problem with this brand: ', brand)

            if r.delivery_type == 'Pallet':
                ET.SubElement(doc,
                              "shippingProfile").text = 'B. Pallet Shipping'
            if r.delivery_type == 'Standard Parcel':
                pounds, ounces = kg_to_imperial(29)
                ET.SubElement(doc,
                              "shippingProfile").text = 'A. Standard Parcel'
            if r.delivery_type == 'Collection Only':
                ET.SubElement(doc,
                              "shippingProfile").text = 'Collection in person.'

            ET.SubElement(doc, "duration").text = str(duration)
            ET.SubElement(doc, "handlingTime").text = str(handling_time)

            if USE_SERVER_IMAGES:
                for ssi in ss_images_list:
                    print(ssi)
                    if ssi.image:  # and exists(images_url + ssi.image):
                        ET.SubElement(doc,
                                      "imageURL").text = images_url + ssi.image
                        '''''
                            # IF there is no slideshow then try the ws_image
                            if not ssi:
                                if r.website_image != 'NULL':
                                    ET.SubElement(doc, "imageURL").text = images_url + ws_image
                        '''

            ET.SubElement(doc, "layout").text = layout
            #ET.SubElement(doc, "lotSize").text = "1"
            if r.height:
                ET.SubElement(doc, "packageDepth").text = str(r.height)
            if r.length:
                ET.SubElement(doc, "packageLength").text = str(r.length)
            ET.SubElement(doc, "packageOunces").text = str(ounces)
            ET.SubElement(doc, "packagePounds").text = str(pounds)
            if r.width:
                ET.SubElement(doc, "packageWidth").text = str(r.width)
            #ET.SubElement(doc, "paymentInstructions").text = ""
            ET.SubElement(doc, "privateAuction").text = "false"
            ET.SubElement(doc, "quantity").text = str(quantity)

            if r.warranty_period == "45" or r.warranty_period == "None":
                ET.SubElement(
                    doc, "returnPolicyDescription"
                ).text = "Buy with confidence. If you wish to return the item, for whatever reason, you may do so within 45 days."
            else:
                ET.SubElement(doc, "returnPolicyDescription").text = "".join([
                    """Buy with confidence. If you wish to return the item, """,
                    """for whatever reason, you may do so within 45 days. """,
                    """This item also includes our Limited Warranty """,
                    """(please see our terms and conditions for details)."""
                ])
                # TODO This item also includes our " + r.warranty_period + " Day Limited Warranty
                # (please see our terms and conditions for details)."

            ET.SubElement(doc, "returnsAccepted").text = "true"
            ET.SubElement(doc, "returnsWithinDays").text = "45"

            #ET.SubElement(doc, "reservePrice").text = ""
            #ET.SubElement(doc, "siteName").text = ""
            ET.SubElement(doc, "SKU").text = item_code
            if is_auction:
                ET.SubElement(doc, "startingBid").text = str(ebay_price)
            #ET.SubElement(doc, ****storCategory).text = ""
            #ET.SubElement(doc, "subTitle").text = sub_title
            ET.SubElement(doc, "title").text = title
            #ET.SubElement(doc, "variation").text = ""
            ET.SubElement(doc, "zipCode").text = post_code

            tree = ET.ElementTree(root)
            file_name = (os.path.join(
                os.sep, garage_xml_path,
                str(date.today()) + "_garageimportfile.xml"))
            # must create xml directory for this to work
            tree.write(file_name)

            # Update ebay_id to 'Awaiting Garagesale' marker
            frappe.db.set_value('Item', item_code, 'ebay_id',
                                ugssettings.AWAITING_GARAGESALE_STATUS)

    # Xml file created now download it (does not work properly)
    #download_xml(site_url + '/files/xml/' + str(date.today()) + "_garageimportfile.xml",
    #             str(date.today()) + "_garageimportfile.xml")

    frappe.msgprint("Export completed.")
def guardar_factura_electronica(datos_recibidos, serie_fact, tiempo_envio):
    '''Guarda los datos recibidos de infile en la tabla Envios Facturas Electronicas de la base de datos ERPNext'''
    try:
        # es-GT: documento: con la libreria xmltodict, se convierte de XML a Diccionario, para acceder a los datos atraves de sus llaves.
        # es-GT: Se asigna a la variable 'documento'

        # en-US: documento: with the xmltodict library, it is converted from XML to Dictionary, to access the data through the dictionary keys
        # en-US: All this is assigned to the 'document' variable.
        respuestaINFILE = xmltodict.parse(datos_recibidos)

        # es-GT: Crea un nuevo record de Envios Facturas Electronica en la base de datos.
        # en-US: Creates a new Electronic Invoice Sent record in the database
        tabFacturaElectronica = frappe.new_doc("Envios Facturas Electronicas")

        # es-GT: Obtiene y Guarda la serie de factura.
        # en-US: Obtains and Saves the invoice series.
        tabFacturaElectronica.serie_factura_original = serie_fact

        # es-GT: Obtiene y Guarda el CAE (Codigo de Autorización Electronico)
        # en-US: Obtains and Saves the CAE or literally translated: "Code of Electronic Authorization"
        tabFacturaElectronica.cae = str(
            respuestaINFILE['S:Envelope']['S:Body']['ns2:registrarDteResponse']
            ['return']['cae'])
        cae_dato = str(respuestaINFILE['S:Envelope']['S:Body']
                       ['ns2:registrarDteResponse']['return']['cae'])

        # es-GT: Obtiene y Guarda el Numero de Documento que quedo registrada ante el Generador de Factura Electronica y la SAT
        # en-US: Obtains and Saves the Document Number that was registered with the Electronic Invoice Generator and SAT
        tabFacturaElectronica.numero_documento = str(
            respuestaINFILE['S:Envelope']['S:Body']['ns2:registrarDteResponse']
            ['return']['numeroDocumento'])

        # es-GT: Obtiene y Guarda el Estado según GFACE (GFACE = Generador de Factura Electronica)
        # en-US: Obtains and Saves the current State of the document as per GFACE (Electronic Invoice Generator)
        tabFacturaElectronica.estado = str(
            respuestaINFILE['S:Envelope']['S:Body']['ns2:registrarDteResponse']
            ['return']['estado'])

        # es-GT: Obtiene y Guarda las Anotaciones segun GFACE
        # en-US: Obtains and Saves the Annotations as per GFACE
        tabFacturaElectronica.anotaciones = str(
            respuestaINFILE['S:Envelope']['S:Body']['ns2:registrarDteResponse']
            ['return']['anotaciones'])

        # es-GT: Obtiene y Guarda la Descripcion: En este campo estan todas las descripciones de errores y mensaje de generacion correcta
        # en-US: Obtains and Saves the Description: This field contains all the descriptions of errors and correct generation messages
        tabFacturaElectronica.descripcion = str(
            respuestaINFILE['S:Envelope']['S:Body']['ns2:registrarDteResponse']
            ['return']['descripcion'])

        # es-GT: Obtiene y Guarda la Validez del documento
        # en-US: Obtains and Saves the Validity state of the document
        tabFacturaElectronica.valido = str(
            respuestaINFILE['S:Envelope']['S:Body']['ns2:registrarDteResponse']
            ['return']['valido'])

        # es-GT: Obtiene y Guarda el Numero DTE
        # en-US: Obtains and Saves the DTE Number
        tabFacturaElectronica.numero_dte = str(
            respuestaINFILE['S:Envelope']['S:Body']['ns2:registrarDteResponse']
            ['return']['numeroDte'])
        # numeroDTEINFILE: Guarda el numero DTE, sera utilizado para renombrar la serie original de la factura que lo origino
        numeroDTEINFILE = str(
            respuestaINFILE['S:Envelope']['S:Body']['ns2:registrarDteResponse']
            ['return']['numeroDte'])

        # es-GT: Obtiene y Guarda el Rango Final Autorizado
        # en-US: Obtains and Saves the Authorized Final Range
        tabFacturaElectronica.rango_final_autorizado = str(
            respuestaINFILE['S:Envelope']['S:Body']['ns2:registrarDteResponse']
            ['return']['rangoFinalAutorizado'])

        # es-GT: Obtiene y Guarda el Rango Inicial Autorizado
        # en-US: Obtains and Saves the Initial Authorized Range
        tabFacturaElectronica.rango_inicial_autorizado = str(
            respuestaINFILE['S:Envelope']['S:Body']['ns2:registrarDteResponse']
            ['return']['rangoInicialAutorizado'])

        # es-GT: Obtiene y Guarda el Regimen de impuestos
        # en-US: Obtains and Saves the Legal Tax Structure, aka 'Regimen'
        tabFacturaElectronica.regimen = str(
            respuestaINFILE['S:Envelope']['S:Body']['ns2:registrarDteResponse']
            ['return']['regimen'])

        # es-GT: Obtiene y Guarda el tiempo en que se recibieron los datos de INFILE
        # en-US: Obtains and Saves the timestamp of data reception from INFILE
        tabFacturaElectronica.recibido = datetime.now()

        # es-GT: Obtiene y Guarda el tiempo en que se enviaron los datos a INFILE
        # es-GT: Estos datos de tiempo se obtienen para poder monitorear el tiempo de transacción
        # en-US: Obtains and Saves the timestamp the data was sent to INFILE
        # en-US: These timestamps are obtained to keep track of transaction time
        tabFacturaElectronica.enviado = tiempo_envio

        # es-GT: Guarda todos los datos en la tabla llamada 'FACTURAS ELECTRONICAS' de la base de datos de ERPNext
        # en-US: Saves all the data in the table called 'ELECTRONIC INVOICES' of the ERPNext database
        tabFacturaElectronica.save()
        # es-GT: Al terminar de guardar el registro en la base de datos, retorna el CAE
        # en-US: When done saving the records to the database, it returns de CAE

        # return cae_dato
        # frappe.msgprint(_("Factura Electronica Generada!"))
    except:
        # es-GT: Si algo falla, muestra el error en el navegador.
        # es-GT: Este mensaje solo indica que no se guardo la confirmacion de la factura electronica.
        # en-US: If something fails, the exception shows this message in the browser
        # en-US: This message simply states that the Electronic Invoice Confirmation was not saved.
        frappe.msgprint(
            _("""Error: No se guardo correctamente la Factura Electronica. Por favor vuelva a presionar el
                             boton de Factura Electronica"""))
    else:
        # Si los datos se Guardan correctamente, se retornara el cae generado, que sera capturado por api.py
        # Puede utlizar para futuros cambios en el codigo
        return cae_dato
Пример #54
0
    def get_gl_entries(self,
                       warehouse_account=None,
                       default_expense_account=None,
                       default_cost_center=None):

        if not warehouse_account:
            warehouse_account = get_warehouse_account()

        sle_map = self.get_stock_ledger_details()
        voucher_details = self.get_voucher_details(default_expense_account,
                                                   default_cost_center,
                                                   sle_map)

        gl_list = []
        warehouse_with_no_account = []
        for detail in voucher_details:
            sle_list = sle_map.get(detail.name)
            if sle_list:
                for sle in sle_list:
                    if warehouse_account.get(sle.warehouse):
                        # from warehouse account

                        self.check_expense_account(detail)

                        gl_list.append(
                            self.get_gl_dict({
                                "account":
                                warehouse_account[sle.warehouse],
                                "against":
                                detail.expense_account,
                                "cost_center":
                                detail.cost_center,
                                "remarks":
                                self.get("remarks")
                                or "Accounting Entry for Stock",
                                "debit":
                                flt(sle.stock_value_difference, 2)
                            }))

                        # to target warehouse / expense account
                        gl_list.append(
                            self.get_gl_dict({
                                "account":
                                detail.expense_account,
                                "against":
                                warehouse_account[sle.warehouse],
                                "cost_center":
                                detail.cost_center,
                                "remarks":
                                self.get("remarks")
                                or "Accounting Entry for Stock",
                                "credit":
                                flt(sle.stock_value_difference, 2)
                            }))
                    elif sle.warehouse not in warehouse_with_no_account:
                        warehouse_with_no_account.append(sle.warehouse)

        if warehouse_with_no_account:
            msgprint(
                _("No accounting entries for the following warehouses") +
                ": \n" + "\n".join(warehouse_with_no_account))

        return process_gl_map(gl_list)
Пример #55
0
def validate_employee_role(doc, method):
	# called via User hook
	if "Employee" in [d.role for d in doc.get("roles")]:
		if not frappe.db.get_value("Employee", {"user_id": doc.name}):
			frappe.msgprint(_("Please set User ID field in an Employee record to set Employee Role"))
			doc.get("roles").remove(doc.get("roles", {"role": "Employee"})[0])
Пример #56
0
def add_bank_accounts(response, bank, company):
    try:
        response = json.loads(response)
    except TypeError:
        pass

    bank = json.loads(bank)
    result = []

    default_gl_account = get_default_bank_cash_account(company, "Bank")
    if not default_gl_account:
        frappe.throw(
            _("Please setup a default bank account for company {0}").format(
                company))

    for account in response["accounts"]:
        acc_type = frappe.db.get_value("Bank Account Type", account["type"])
        if not acc_type:
            add_account_type(account["type"])

        acc_subtype = frappe.db.get_value("Bank Account Subtype",
                                          account["subtype"])
        if not acc_subtype:
            add_account_subtype(account["subtype"])

        if not frappe.db.exists("Bank Account",
                                dict(integration_id=account["id"])):
            try:
                new_account = frappe.get_doc({
                    "doctype":
                    "Bank Account",
                    "bank":
                    bank["bank_name"],
                    "account":
                    default_gl_account.account,
                    "account_name":
                    account["name"],
                    "account_type":
                    account["type"] or "",
                    "account_subtype":
                    account["subtype"] or "",
                    "mask":
                    account["mask"] or "",
                    "integration_id":
                    account["id"],
                    "is_company_account":
                    1,
                    "company":
                    company
                })
                new_account.insert()

                result.append(new_account.name)
            except frappe.UniqueValidationError:
                frappe.msgprint(
                    _("Bank account {0} already exists and could not be created again"
                      ).format(account["name"]))
            except Exception:
                frappe.throw(frappe.get_traceback())

        else:
            result.append(
                frappe.db.get_value("Bank Account",
                                    dict(integration_id=account["id"]),
                                    "name"))

    return result
def actualizarTablas(serieOriginalFac):
    """Funcion permite actualizar tablas en la base de datos, despues de haber generado
    la factura electronica"""
    # Verifica que exista un documento en la tabla Envios Facturas Electronicas con el nombre de la serie original
    if frappe.db.exists('Envios Facturas Electronicas',
                        {'serie_factura_original': serieOriginalFac}):
        factura_guardada = frappe.db.get_values(
            'Envios Facturas Electronicas',
            filters={'serie_factura_original': serieOriginalFac},
            fieldname=['numero_dte', 'cae', 'serie_factura_original'],
            as_dict=1)
        # Esta seccion se encarga de actualizar la serie, con una nueva que es el numero de DTE
        # buscara en las tablas donde exista una coincidencia actualizando con la nueva serie
        try:
            # serieDte: guarda el numero DTE retornado por INFILE, se utilizara para reemplazar el nombre de la serie de la
            # factura que lo generó.
            serieDte = str(factura_guardada[0]['numero_dte'])
            # serie_fac_original: Guarda la serie original de la factura.
            serie_fac_original = serieOriginalFac

            # Actualizacion de tablas que son modificadas directamente.
            # 01 - tabSales Invoice
            frappe.db.sql(
                '''UPDATE `tabSales Invoice`
                             SET name=%(name)s,
                                 cae_factura_electronica=%(cae_correcto)s,
                                 serie_original_del_documento=%(serie_orig_correcta)s
                            WHERE name=%(serieFa)s
                            ''', {
                    'name': serieDte,
                    'cae_correcto': factura_guardada[0]['cae'],
                    'serie_orig_correcta': serie_fac_original,
                    'serieFa': serie_fac_original
                })

            # 02 - tabSales Invoice Item
            frappe.db.sql(
                '''UPDATE `tabSales Invoice Item` SET parent=%(name)s
                            WHERE parent=%(serieFa)s''', {
                    'name': serieDte,
                    'serieFa': serie_fac_original
                })

            # 03 - tabGL Entry
            frappe.db.sql(
                '''UPDATE `tabGL Entry` SET voucher_no=%(name)s, against_voucher=%(name)s
                            WHERE voucher_no=%(serieFa)s AND against_voucher=%(serieFa)s''',
                {
                    'name': serieDte,
                    'serieFa': serie_fac_original
                })

            frappe.db.sql(
                '''UPDATE `tabGL Entry` SET voucher_no=%(name)s, docstatus=1
                            WHERE voucher_no=%(serieFa)s AND against_voucher IS NULL''',
                {
                    'name': serieDte,
                    'serieFa': serie_fac_original
                })

            # Actualizacion de tablas que pueden ser modificadas desde Sales Invoice
            # Verificara tabla por tabla en busca de un valor existe, en caso sea verdadero actualizara,
            # en caso no encuentre nada no hara nada
            # 04 - tabSales Taxes and Charges
            if frappe.db.exists('Sales Taxes and Charges',
                                {'parent': serie_fac_original}):
                frappe.db.sql(
                    '''UPDATE `tabSales Taxes and Charges` SET parent=%(name)s
                                WHERE parent=%(serieFa)s''', {
                        'name': serieDte,
                        'serieFa': serie_fac_original
                    })

            if frappe.db.exists('Otros Impuestos Factura Electronica',
                                {'parent': serie_fac_original}):
                frappe.db.sql(
                    '''UPDATE `tabOtros Impuestos Factura Electronica` SET parent=%(name)s
                                WHERE parent=%(serieFa)s''', {
                        'name': serieDte,
                        'serieFa': serie_fac_original
                    })

            # else:
            #     frappe.msgprint(_('No hay registro en Sales Taxes and Charges'))

            # Pago programado
            # 05 - tabPayment Schedule
            if frappe.db.exists('Payment Schedule',
                                {'parent': serie_fac_original}):
                frappe.db.sql(
                    '''UPDATE `tabPayment Schedule` SET parent=%(name)s
                                WHERE parent=%(serieFa)s''', {
                        'name': serieDte,
                        'serieFa': serie_fac_original
                    })
            # else:
            #     frappe.msgprint(_('No hay registro en Payment Schedule'))

            # subscripcion
            # 06 - tabSubscription
            if frappe.db.exists('Subscription',
                                {'reference_document': serie_fac_original}):
                frappe.db.sql(
                    '''UPDATE `tabSubscription` SET reference_document=%(name)s
                                WHERE reference_document=%(serieFa)s''', {
                        'name': serieDte,
                        'serieFa': serie_fac_original
                    })
            # else:
            #     frappe.msgprint(_('No hay registro en Subscription'))

            # Entrada del libro mayor de inventarios
            # 07 - tabStock Ledger Entry
            if frappe.db.exists('Stock Ledger Entry',
                                {'voucher_no': serie_fac_original}):
                frappe.db.sql(
                    '''UPDATE `tabStock Ledger Entry` SET voucher_no=%(name)s
                                WHERE voucher_no=%(serieFa)s''', {
                        'name': serieDte,
                        'serieFa': serie_fac_original
                    })
            # else:
            #     frappe.msgprint(_('No hay registro en Stock Ledger Entry'))

            # Hoja de tiempo de factura de ventas
            # 08 - tabSales Invoice Timesheet
            if frappe.db.exists('Sales Invoice Timesheet',
                                {'parent': serie_fac_original}):
                frappe.db.sql(
                    '''UPDATE `tabSales Invoice Timesheet` SET parent=%(name)s
                                WHERE parent=%(serieFa)s''', {
                        'name': serieDte,
                        'serieFa': serie_fac_original
                    })
            # else:
            #     frappe.msgprint(_('No hay registro en Sales Invoice Timesheet'))

            # Equipo Ventas
            # 09 - tabSales Team
            if frappe.db.exists('Sales Team', {'parent': serie_fac_original}):
                frappe.db.sql(
                    '''UPDATE `tabSales Team` SET parent=%(name)s
                                WHERE parent=%(serieFa)s''', {
                        'name': serieDte,
                        'serieFa': serie_fac_original
                    })
            # else:
            #     frappe.msgprint(_('No hay registro en Sales Team'))

            # Packed Item
            # 10 - tabPacked Item
            if frappe.db.exists('Packed Item', {'parent': serie_fac_original}):
                frappe.db.sql(
                    '''UPDATE `tabPacked Item` SET parent=%(name)s
                                WHERE parent=%(serieFa)s''', {
                        'name': serieDte,
                        'serieFa': serie_fac_original
                    })
            # else:
            #     frappe.msgprint(_('No hay registro en tabPackedItem))

            # Sales Invoice Advance - Anticipos a facturas
            # 11 - tabSales Invoice Advance
            if frappe.db.exists('Sales Invoice Advance',
                                {'parent': serie_fac_original}):
                frappe.db.sql(
                    '''UPDATE `tabSales Invoice Advance` SET parent=%(name)s
                                WHERE parent=%(serieFa)s''', {
                        'name': serieDte,
                        'serieFa': serie_fac_original
                    })
            # else:
            #     frappe.msgprint(_('No hay registro en tabSales Invoice Advance))

            # Sales Invoice Payment - Pagos sobre a facturas
            # 12 - tabSales Invoice Payment
            if frappe.db.exists('Sales Invoice Payment',
                                {'parent': serie_fac_original}):
                frappe.db.sql(
                    '''UPDATE `tabSales Invoice Payment` SET parent=%(name)s
                                WHERE parent=%(serieFa)s''', {
                        'name': serieDte,
                        'serieFa': serie_fac_original
                    })
            # else:
            #     frappe.msgprint(_('No hay registro en tabSales Invoice Payment))

            # Payment Entry Reference -
            # 13 - tabPayment Entry Reference
            if frappe.db.exists('Payment Entry Reference',
                                {'parent': serie_fac_original}):
                frappe.db.sql(
                    '''UPDATE `tabSales Invoice Payment` SET parent=%(name)s
                                WHERE parent=%(serieFa)s''', {
                        'name': serieDte,
                        'serieFa': serie_fac_original
                    })
            # else:
            #     frappe.msgprint(_('No hay registro en tabPayment Entry Reference))

            # Sales Order
            # 15 - tabSales Order
            if frappe.db.exists('Sales Order', {'parent': serie_fac_original}):
                frappe.db.sql(
                    '''UPDATE `tabSales Order` SET parent=%(name)s
                                WHERE parent=%(serieFa)s''', {
                        'name': serieDte,
                        'serieFa': serie_fac_original
                    })
            # else:
            #     frappe.msgprint(_('No hay registro en tabSales Order))

            # Parece que este no enlaza directamente con sales invoice es el sales invoice que enlaza con este.
            # Delivery Note
            # 16 - tabDelivery Note
            if frappe.db.exists('Delivery Note',
                                {'parent': serie_fac_original}):
                frappe.db.sql(
                    '''UPDATE `tabDelivery Note` SET parent=%(name)s
                                WHERE parent=%(serieFa)s''', {
                        'name': serieDte,
                        'serieFa': serie_fac_original
                    })
            # else:
            #     frappe.msgprint(_('No hay registro en tabSales Order))

            frappe.db.commit()

            # Posible modifacadas
            # # Artículo empaquetado
            # if frappe.db.exists('Packed Item', {'': }): # ?
            # # Avance de Factura de Ventas
            # if frappe.db.exists('Sales Invoice Advance', {'': }): # ?
            # # Pago de factura de ventas
            # if frappe.db.exists('Sales Invoice Payment', {'': }): # ?
            # # Entrada de Diario
            # if frappe.db.exists('Journal Entry', {'': }): # ?
            # # hoja de tiempo
            # if frappe.db.exists('Timesheet', {'': }): # No hay registro
        except:
            # En caso exista un error al renombrar la factura retornara el mensaje con el error
            frappe.msgprint(
                _('Error al renombrar Factura. Por favor intente de nuevo presionando el boton Factura Electronica'
                  ))
        else:
            # Si los datos se Guardan correctamente, se retornara el Numero Dte generado, que sera capturado por api.py
            # para luego ser capturado por javascript, se utilizara para recargar la url con los cambios correctos
            return str(factura_guardada[0]['numero_dte'])
Пример #58
0
def rename_doc(
	doctype,
	old,
	new,
	force=False,
	merge=False,
	ignore_permissions=False,
	ignore_if_exists=False,
	show_alert=True,
	rebuild_search=True
):
	"""Rename a doc(dt, old) to doc(dt, new) and update all linked fields of type "Link"."""
	if not frappe.db.exists(doctype, old):
		return

	if ignore_if_exists and frappe.db.exists(doctype, new):
		return

	if old==new:
		frappe.msgprint(_('Please select a new name to rename'))
		return

	force = cint(force)
	merge = cint(merge)
	meta = frappe.get_meta(doctype)

	# call before_rename
	old_doc = frappe.get_doc(doctype, old)
	out = old_doc.run_method("before_rename", old, new, merge) or {}
	new = (out.get("new") or new) if isinstance(out, dict) else (out or new)

	if doctype != "DocType":
		new = validate_rename(doctype, new, meta, merge, force, ignore_permissions)

	if not merge:
		rename_parent_and_child(doctype, old, new, meta)

	# update link fields' values
	link_fields = get_link_fields(doctype)
	update_link_field_values(link_fields, old, new, doctype)

	rename_dynamic_links(doctype, old, new)

	# save the user settings in the db
	update_user_settings(old, new, link_fields)

	if doctype=='DocType':
		rename_doctype(doctype, old, new, force)
		update_customizations(old, new)

	update_attachments(doctype, old, new)

	rename_versions(doctype, old, new)

	# call after_rename
	new_doc = frappe.get_doc(doctype, new)

	# copy any flags if required
	new_doc._local = getattr(old_doc, "_local", None)

	new_doc.run_method("after_rename", old, new, merge)

	if not merge:
		rename_password(doctype, old, new)

	# update user_permissions
	frappe.db.sql("""UPDATE `tabDefaultValue` SET `defvalue`=%s WHERE `parenttype`='User Permission'
		AND `defkey`=%s AND `defvalue`=%s""", (new, doctype, old))

	if merge:
		new_doc.add_comment('Edit', _("merged {0} into {1}").format(frappe.bold(old), frappe.bold(new)))
	else:
		new_doc.add_comment('Edit', _("renamed from {0} to {1}").format(frappe.bold(old), frappe.bold(new)))

	if merge:
		frappe.delete_doc(doctype, old)

	frappe.clear_cache()
	if rebuild_search:
		frappe.enqueue('frappe.utils.global_search.rebuild_for_doctype', doctype=doctype)

	if show_alert:
		frappe.msgprint(_('Document renamed from {0} to {1}').format(bold(old), bold(new)), alert=True, indicator='green')

	return new
Пример #59
0
	def validate_inspection(self):
		for d in self.get('items'):		 #Enter inspection date for all items that require inspection
			if frappe.db.get_value("Item", d.item_code, "inspection_required") and not d.qa_no:
				frappe.msgprint(_("Quality Inspection required for Item {0}").format(d.item_code))
				if self.docstatus==1:
					raise frappe.ValidationError
Пример #60
0
	def validate_prefered_email(self):
		if self.prefered_contact_email and not self.get(scrub(self.prefered_contact_email)):
			frappe.msgprint(_("Please enter " + self.prefered_contact_email))