def test_max_continuous_leaves(self):
		employee = get_employee()
		leave_period = get_leave_period()
		frappe.delete_doc_if_exists("Leave Type", "Test Leave Type", force=1)
		leave_type = frappe.get_doc(dict(
			leave_type_name = 'Test Leave Type',
			doctype = 'Leave Type',
			max_leaves_allowed = 15,
			max_continuous_days_allowed = 3
		)).insert()

		date = add_days(nowdate(), -7)

		allocate_leaves(employee, leave_period, leave_type.name, 10)

		leave_application = frappe.get_doc(dict(
			doctype = 'Leave Application',
			employee = employee.name,
			leave_type = leave_type.name,
			from_date = date,
			to_date = add_days(date, 4),
			company = "_Test Company",
			docstatus = 1,
            status = "Approved"
		))

		self.assertRaises(frappe.ValidationError, leave_application.insert)
Beispiel #2
0
	def test_fee_validity(self):
		patient = get_random("Patient")
		physician = get_random("Physician")

		if not patient:
			patient = frappe.new_doc("Patient")
			patient.patient_name = "Test Patient"
			patient.sex = "Male"
			patient.save(ignore_permissions=True)
			patient = patient.name

		if not physician:
			physician = frappe.new_doc("Physician")
			physician.first_name = "Amit Jain"
			physician.save(ignore_permissions=True)
			physician = physician.name

		frappe.db.set_value("Healthcare Settings", None, "max_visit", 2)
		frappe.db.set_value("Healthcare Settings", None, "valid_days", 7)

		appointment = create_appointment(patient, physician, nowdate())
		invoice = frappe.db.get_value("Patient Appointment", appointment.name, "sales_invoice")
		self.assertEqual(invoice, None)
		create_invoice(frappe.defaults.get_global_default("company"), physician, patient, appointment.name, appointment.appointment_date)
		appointment = create_appointment(patient, physician, add_days(nowdate(), 4))
		invoice = frappe.db.get_value("Patient Appointment", appointment.name, "sales_invoice")
		self.assertTrue(invoice)
		appointment = create_appointment(patient, physician, add_days(nowdate(), 5))
		invoice = frappe.db.get_value("Patient Appointment", appointment.name, "sales_invoice")
		self.assertEqual(invoice, None)
		appointment = create_appointment(patient, physician, add_days(nowdate(), 10))
		invoice = frappe.db.get_value("Patient Appointment", appointment.name, "sales_invoice")
		self.assertEqual(invoice, None)
	def validate(self):
		member_name = frappe.get_value('Member', dict(email=frappe.session.user))

		if not member_name:
			user = frappe.get_doc('User', frappe.session.user)
			member = frappe.get_doc(dict(
				doctype='Member',
				email=frappe.session.user,
				member_name=user.get_fullname()
			)).insert(ignore_permissions=True)
			member_name = member.name

		if self.get("__islocal"):
			self.member = member_name

		# get last membership (if active)
		last_membership = foundation.get_last_membership()

		# if person applied for offline membership
		if last_membership and not frappe.session.user == "Administrator":
			# if last membership does not expire in 30 days, then do not allow to renew
			if getdate(add_days(last_membership.to_date, -30)) > getdate(nowdate()) :
				frappe.throw(_('You can only renew if your membership expires within 30 days'))

			self.from_date = add_days(last_membership.to_date, 1)
		elif frappe.session.user == "Administrator":
			self.from_date = self.from_date
		else:
			self.from_date = nowdate()

		self.to_date = add_years(self.from_date, 1)
Beispiel #4
0
def get_start_end_dates(payroll_frequency, start_date=None, company=None):
	'''Returns dict of start and end dates for given payroll frequency based on start_date'''

	if payroll_frequency == "Monthly" or payroll_frequency == "Bimonthly" or payroll_frequency == "":
		fiscal_year = get_fiscal_year(start_date, company=company)[0]
		month = "%02d" % getdate(start_date).month
		m = get_month_details(fiscal_year, month)
		if payroll_frequency == "Bimonthly":
			if getdate(start_date).day <= 15:
				start_date = m['month_start_date']
				end_date = m['month_mid_end_date']
			else:
				start_date = m['month_mid_start_date']
				end_date = m['month_end_date']
		else:
			start_date = m['month_start_date']
			end_date = m['month_end_date']

	if payroll_frequency == "Weekly":
		end_date = add_days(start_date, 6)

	if payroll_frequency == "Fortnightly":
		end_date = add_days(start_date, 13)

	if payroll_frequency == "Daily":
		end_date = start_date

	return frappe._dict({
		'start_date': start_date, 'end_date': end_date
	})
Beispiel #5
0
	def schedule_course(self):
		course_schedules= []
		course_schedules_errors= []
		rescheduled= []
		reschedule_errors= []
		
		self.validate_date()
		
		if self.rechedule:
			rescheduled, reschedule_errors = self.delete_course_schedule(rescheduled, reschedule_errors)
		
		date = self.course_start_date
		while(date < self.course_end_date):
			if self.day == calendar.day_name[getdate(date).weekday()]:
				course_schedule = self.make_course_schedule(date)
				try:
					course_schedule.save()
				except OverlapError:
					course_schedules_errors.append(date)
				else:
					course_schedules.append(course_schedule.name + " on " + date)
				
				date = add_days(date, 7)
			else:
				date = add_days(date, 1)
			
		frappe.local.message_log = []
		if course_schedules:
			frappe.msgprint(_("Course Schedules created:") + "\n" + "\n".join(course_schedules))
		if course_schedules_errors:
			frappe.msgprint(_("There were errors while scheduling course on :") + "\n" + "\n".join(course_schedules_errors))
		if rescheduled:
			frappe.msgprint(_("Course Schedules deleted:") + "\n" + "\n".join(rescheduled))
		if reschedule_errors:
			frappe.msgprint(_("There were errors while deleting following schedules:") + "\n" + "\n".join(reschedule_errors))
Beispiel #6
0
def create_purchase_order(**args):
	po = frappe.new_doc("Purchase Order")
	args = frappe._dict(args)
	if args.transaction_date:
		po.transaction_date = args.transaction_date

	po.schedule_date = add_days(nowdate(), 1)
	po.company = args.company or "_Test Company"
	po.supplier = args.customer or "_Test Supplier"
	po.is_subcontracted = args.is_subcontracted or "No"
	po.currency = args.currency or frappe.get_cached_value('Company',  po.company,  "default_currency")
	po.conversion_factor = args.conversion_factor or 1
	po.supplier_warehouse = args.supplier_warehouse or None

	po.append("items", {
		"item_code": args.item or args.item_code or "_Test Item",
		"warehouse": args.warehouse or "_Test Warehouse - _TC",
		"qty": args.qty or 10,
		"rate": args.rate or 500,
		"schedule_date": add_days(nowdate(), 1),
		"include_exploded_items": args.get('include_exploded_items', 1)
	})
	if not args.do_not_save:
		po.insert()
		if not args.do_not_submit:
			if po.is_subcontracted == "Yes":
				supp_items = po.get("supplied_items")
				for d in supp_items:
					d.reserve_warehouse = args.warehouse or "_Test Warehouse - _TC"
			po.submit()

	return po
Beispiel #7
0
	def test_make_purchase_invoice_with_terms(self):
		po = create_purchase_order(do_not_save=True)

		self.assertRaises(frappe.ValidationError, make_purchase_invoice, po.name)

		po.update(
			{"payment_terms_template": "_Test Payment Term Template"}
		)

		po.save()
		po.submit()

		self.assertEqual(po.payment_schedule[0].payment_amount, 2500.0)
		self.assertEqual(getdate(po.payment_schedule[0].due_date), getdate(po.transaction_date))
		self.assertEqual(po.payment_schedule[1].payment_amount, 2500.0)
		self.assertEqual(getdate(po.payment_schedule[1].due_date), add_days(getdate(po.transaction_date), 30))
		pi = make_purchase_invoice(po.name)
		pi.save()

		self.assertEqual(pi.doctype, "Purchase Invoice")
		self.assertEqual(len(pi.get("items", [])), 1)

		self.assertEqual(pi.payment_schedule[0].payment_amount, 2500.0)
		self.assertEqual(getdate(pi.payment_schedule[0].due_date), getdate(po.transaction_date))
		self.assertEqual(pi.payment_schedule[1].payment_amount, 2500.0)
		self.assertEqual(getdate(pi.payment_schedule[1].due_date), add_days(getdate(po.transaction_date), 30))
def create_purchase_order(**args):
	po = frappe.new_doc("Purchase Order")
	args = frappe._dict(args)
	if args.transaction_date:
		po.transaction_date = args.transaction_date

	po.schedule_date = add_days(nowdate(), 1)
	po.company = args.company or "_Test Company"
	po.supplier = args.customer or "_Test Supplier"
	po.is_subcontracted = args.is_subcontracted or "No"
	po.currency = args.currency or frappe.db.get_value("Company", po.company, "default_currency")
	po.conversion_factor = args.conversion_factor or 1

	po.append("items", {
		"item_code": args.item or args.item_code or "_Test Item",
		"warehouse": args.warehouse or "_Test Warehouse - _TC",
		"qty": args.qty or 10,
		"rate": args.rate or 500,
		"schedule_date": add_days(nowdate(), 1)
	})
	if not args.do_not_save:
		po.insert()
		if not args.do_not_submit:
			po.submit()

	return po
Beispiel #9
0
def get_booking_dates(doc, item, posting_date=None):
	if not posting_date:
		posting_date = add_days(today(), -1)

	last_gl_entry = False

	deferred_account = "deferred_revenue_account" if doc.doctype=="Sales Invoice" else "deferred_expense_account"

	prev_gl_entry = frappe.db.sql('''
		select name, posting_date from `tabGL Entry` where company=%s and account=%s and
		voucher_type=%s and voucher_no=%s and voucher_detail_no=%s
		order by posting_date desc limit 1
	''', (doc.company, item.get(deferred_account), doc.doctype, doc.name, item.name), as_dict=True)

	if prev_gl_entry:
		start_date = getdate(add_days(prev_gl_entry[0].posting_date, 1))
	else:
		start_date = item.service_start_date

	end_date = get_last_day(start_date)
	if end_date >= item.service_end_date:
		end_date = item.service_end_date
		last_gl_entry = True
	elif item.service_stop_date and end_date >= item.service_stop_date:
		end_date = item.service_stop_date
		last_gl_entry = True

	if end_date > getdate(posting_date):
		end_date = posting_date

	if getdate(start_date) <= getdate(end_date):
		return start_date, end_date, last_gl_entry
	else:
		return None, None, None
Beispiel #10
0
	def test_overdue(self):
		task = create_task("Testing Overdue", add_days(nowdate(), -10), add_days(nowdate(), -5))

		from erpnext.projects.doctype.task.task import set_tasks_as_overdue
		set_tasks_as_overdue()

		self.assertEqual(frappe.db.get_value("Task", task.name, "status"), "Overdue")
Beispiel #11
0
	def test_reschedule_dependent_task(self):
		task1 = create_task("_Test Task 1", nowdate(), add_days(nowdate(), 10))

		task2 = create_task("_Test Task 2", add_days(nowdate(), 11), add_days(nowdate(), 15), task1.name)
		task2.get("depends_on")[0].project = "_Test Project"
		task2.save()

		task3 = create_task("_Test Task 3", add_days(nowdate(), 11), add_days(nowdate(), 15), task2.name)
		task3.get("depends_on")[0].project = "_Test Project"
		task3.save()

		task1.update({
			"exp_end_date": add_days(nowdate(), 20)
		})
		task1.save()

		self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_start_date"),
			getdate(add_days(nowdate(), 21)))
		self.assertEqual(frappe.db.get_value("Task", task2.name, "exp_end_date"),
			getdate(add_days(nowdate(), 25)))

		self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_start_date"),
			getdate(add_days(nowdate(), 26)))
		self.assertEqual(frappe.db.get_value("Task", task3.name, "exp_end_date"),
			getdate(add_days(nowdate(), 30)))
def auto_status_update_ms(doc, method):
	new = add_years(doc.installation_date, doc.guarantee_period)
	validdate_amc1=add_days(new,-1)
	doc.amc_guarantee_valid_upto_date=validdate_amc1
	new = add_days(new, days=-1)
	if doc.guarantee_period==0:
		doc.amc_guarantee_valid_upto_date=""
		doc.amc_status="N/A"
		frappe.throw("Enter The Guarantee Period")
	else:
		doc.amc_guarantee_valid_upto_date = new

	# if doc.transaction_date
	# 	doc.amc_status = "Untraceable"
	# if date_diff(doc.transaction_date,doc.installation_date)<=365*doc.contract_period:
	# 	doc.amc_status = "N/A"
	if doc.amc_guarantee_valid_upto_date>doc.transaction_date:
		doc.amc_status = "Guarantee"
	else:
		doc.amc_status="Expired"
	
	if doc.amc_start_month:
		guarntee=add_years(doc.amc_start_month,doc.contract_period)
		validdate_amc=add_days(guarntee,-1)
		doc.amc_guarantee_valid_upto_date=validdate_amc
		guarntee = add_days(guarntee, days=-1)
		doc.amc_guarantee_valid_upto_date=guarntee
		doc.amc_status = "AMC"

	if getdate(doc.transaction_date) > getdate(doc.installation_date):
		frappe.throw("Installation Date Should be Greater Than Equal To Transaction Date")
Beispiel #13
0
	def get_period_date_ranges(self):
		from dateutil.relativedelta import relativedelta, MO
		from_date, to_date = getdate(self.filters.from_date), getdate(self.filters.to_date)

		increment = {
			"Monthly": 1,
			"Quarterly": 3,
			"Half-Yearly": 6,
			"Yearly": 12
		}.get(self.filters.range, 1)

		if self.filters.range in ['Monthly', 'Quarterly']:
			from_date = from_date.replace(day = 1)
		elif self.filters.range == "Yearly":
			from_date = get_fiscal_year(from_date)[1]
		else:
			from_date = from_date + relativedelta(from_date, weekday=MO(-1))

		self.periodic_daterange = []
		for dummy in range(1, 53):
			if self.filters.range == "Weekly":
				period_end_date = add_days(from_date, 6)
			else:
				period_end_date = add_to_date(from_date, months=increment, days=-1)

			if period_end_date > to_date:
				period_end_date = to_date

			self.periodic_daterange.append(period_end_date)

			from_date = add_days(period_end_date, 1)
			if period_end_date == to_date:
				break
Beispiel #14
0
	def test_future_inactive_signed_contract_status(self):
		self.contract_doc.is_signed = True
		self.contract_doc.start_date = add_days(nowdate(), 1)
		self.contract_doc.end_date = add_days(nowdate(), 2)
		self.contract_doc.insert()

		self.assertEqual(self.contract_doc.status, "Inactive")
Beispiel #15
0
	def test_lapsed_contract_status(self):
		self.contract_doc.contract_term = "_Test Customer Contract with Requirements"
		self.contract_doc.start_date = add_days(nowdate(), -2)
		self.contract_doc.end_date = add_days(nowdate(), 1)
		self.contract_doc.requires_fulfilment = 1
		self.contract_doc.fulfilment_deadline = add_days(nowdate(), -1)
		self.contract_doc.save()

		self.assertEqual(self.contract_doc.fulfilment_status, "Lapsed")
def get_due_date(posting_date, term):
	due_date = None
	if term.due_date_based_on == "Day(s) after invoice date":
		due_date = add_days(posting_date, term.credit_days)
	elif term.due_date_based_on == "Day(s) after the end of the invoice month":
		due_date = add_days(get_last_day(posting_date), term.credit_days)
	elif term.due_date_based_on == "Month(s) after the end of the invoice month":
		due_date = add_months(get_last_day(posting_date), term.credit_months)

	return due_date
Beispiel #17
0
	def test_valid_till(self):
		from erpnext.selling.doctype.quotation.quotation import make_sales_order

		quotation = frappe.copy_doc(test_records[0])
		quotation.valid_till = add_days(quotation.transaction_date, -1)
		self.assertRaises(frappe.ValidationError, quotation.validate)

		quotation.valid_till = add_days(nowdate(), -1)
		quotation.insert()
		quotation.submit()
		self.assertRaises(frappe.ValidationError, make_sales_order, quotation.name)
	def test_create_training_event(self):
		if not frappe.db.get_value("Training Event", "Basic Training Event"):
			frappe.get_doc({
				"doctype": "Training Event",
				"event_name": "Basic Training Event",
				"training_program": "Basic Training",
				"location": "Union Square",
				"start_time": add_days(today(), 5),
				"end_time": add_days(today(), 6),
				"introduction": "Welcome to the Basic Training Event",
				"employees": get_attendees(self.employee, self.employee2)
			}).insert()
Beispiel #19
0
	def reschedule_dependent_tasks(self):
		end_date = self.exp_end_date or self.act_end_date
		if end_date:
			for task_name in frappe.db.sql("select name from `tabTask` as parent where %s in \
				(select task from `tabTask Depends On` as child where parent.name = child.parent )", self.name, as_dict=1):
				task = frappe.get_doc("Task", task_name.name)
				if task.exp_start_date and task.exp_end_date and task.exp_start_date < getdate(end_date) and task.status == "Open" :
					task_duration = date_diff(task.exp_end_date, task.exp_start_date)
					task.exp_start_date = add_days(end_date, 1)
					task.exp_end_date = add_days(task.exp_start_date, task_duration)
					task.flags.ignore_recursion_check = True
					task.save()
Beispiel #20
0
def setup_asset():
	assets = json.loads(open(frappe.get_app_path('erpnext', 'demo', 'data', 'asset.json')).read())
	for d in assets:
		asset = frappe.new_doc('Asset')
		asset.update(d)
		asset.purchase_date = add_days(nowdate(), -random.randint(20, 1500))
		asset.next_depreciation_date = add_days(asset.purchase_date, 30)
		asset.warehouse = "Stores - WPL"
		asset.set_missing_values()
		asset.make_depreciation_schedule()
		asset.flags.ignore_validate = True
		asset.save()
		asset.submit()
Beispiel #21
0
	def reschedule_dependent_tasks(self):
		end_date = self.exp_end_date or self.act_end_date
		if end_date:
			for task_name in frappe.db.sql("""select name from `tabTask` as parent where parent.project = %(project)s and parent.name in \
				(select parent from `tabTask Depends On` as child where child.task = %(task)s and child.project = %(project)s)""",
				{'project': self.project, 'task':self.name }, as_dict=1):

				task = frappe.get_doc("Task", task_name.name)
				if task.exp_start_date and task.exp_end_date and task.exp_start_date < getdate(end_date) and task.status == "Open":
					task_duration = date_diff(task.exp_end_date, task.exp_start_date)
					task.exp_start_date = add_days(end_date, 1)
					task.exp_end_date = add_days(task.exp_start_date, task_duration)
					task.flags.ignore_recursion_check = True
					task.save()
Beispiel #22
0
	def test_fee_validity(self):
		frappe.db.sql("""delete from `tabPatient Appointment`""")
		frappe.db.sql("""delete from `tabFee Validity`""")
		patient = get_random("Patient")
		practitioner = get_random("Healthcare Practitioner")
		department = get_random("Medical Department")

		if not patient:
			patient = frappe.new_doc("Patient")
			patient.patient_name = "_Test Patient"
			patient.sex = "Male"
			patient.save(ignore_permissions=True)
			patient = patient.name

		if not department:
			medical_department = frappe.new_doc("Medical Department")
			medical_department.department = "_Test Medical Department"
			medical_department.save(ignore_permissions=True)
			department = medical_department.name

		if not practitioner:
			practitioner = frappe.new_doc("Healthcare Practitioner")
			practitioner.first_name = "_Test Healthcare Practitioner"
			practitioner.department = department
			practitioner.save(ignore_permissions=True)
			practitioner = practitioner.name



		frappe.db.set_value("Healthcare Settings", None, "max_visit", 2)
		frappe.db.set_value("Healthcare Settings", None, "valid_days", 7)

		appointment = create_appointment(patient, practitioner, nowdate(), department)
		invoiced = frappe.db.get_value("Patient Appointment", appointment.name, "invoiced")
		self.assertEqual(invoiced, 0)

		invoice_appointment(appointment)

		appointment = create_appointment(patient, practitioner, add_days(nowdate(), 4), department)
		invoiced = frappe.db.get_value("Patient Appointment", appointment.name, "invoiced")
		self.assertTrue(invoiced)

		appointment = create_appointment(patient, practitioner, add_days(nowdate(), 5), department)
		invoiced = frappe.db.get_value("Patient Appointment", appointment.name, "invoiced")
		self.assertEqual(invoiced, 0)

		appointment = create_appointment(patient, practitioner, add_days(nowdate(), 10), department)
		invoiced = frappe.db.get_value("Patient Appointment", appointment.name, "invoiced")
		self.assertEqual(invoiced, 0)
def execute():
	leave_app_list = frappe.db.sql("""SELECT name FROM `tabLeave Application` 
		WHERE docstatus = 1 AND status = 'Approved'
		ORDER BY name ASC""", as_list=1)
	for leave_app in leave_app_list:
		print("Checking for Leave Application " + leave_app[0])
		la_doc = frappe.get_doc("Leave Application", leave_app[0])
		att_list = frappe.db.sql("""SELECT name FROM `tabAttendance` 
			WHERE docstatus = 1 AND employee ='%s' AND attendance_date BETWEEN '%s' AND '%s'"""%(la_doc.employee, \
				la_doc.from_date, la_doc.to_date), as_list=1)
		if att_list:
			for att in att_list:
				status = frappe.db.get_value("Attendance", att[0], "status")
				if status != 'On Leave':
					if status == 'Half Day':
						if la_doc.total_leave_days != 0.5:
							print('Half Day Error for ' + att[0] + ' and Leave App ' + leave_app[0])
					else:
						print('Error for ' + att[0] + ' and Leave App ' + leave_app[0])
		else:
			leave_days = la_doc.total_leave_days
			for lday in range(int(leave_days)):
				shift_request = frappe.db.sql("""SELECT name FROM `tabShift Assignment` 
					WHERE employee = '%s' AND docstatus = 1 AND `date` = '%s'"""%\
					(la_doc.employee, add_days(la_doc.from_date, lday)),as_list=1)

				if not shift_request:
					new_sr = frappe.new_doc("Shift Assignment")
					new_sr.employee = la_doc.employee
					new_sr.company = la_doc.company
					new_sr.shift_type = 'General Shift G-Shift With In and Out'
					new_sr.date = add_days(la_doc.from_date, lday)
					new_sr.docstatus = 1
					new_sr.insert()
					print("Added Shift Request " + str(new_sr.name) + " for Employee " + \
						la_doc.employee + " with Name: " + str(la_doc.employee_name))
					frappe.db.commit()

				new_att = frappe.new_doc("Attendance")
				new_att.docstatus = 1
				new_att.employee = la_doc.employee
				new_att.attendance_date = add_days(la_doc.from_date, lday)
				if la_doc.total_leave_days == int(la_doc.total_leave_days):
					new_att.status = 'On Leave'
				new_att.company = la_doc.company
				new_att.department = la_doc.department
				new_att.insert()
				print('Added Attendance for Employee ' + la_doc.employee + ' Name: ' + str(la_doc.employee_name) + ' for Leave Application ' + la_doc.name)
			frappe.db.commit()
Beispiel #24
0
def get_error_report(from_date=None, to_date=None, limit=10):
	from frappe.utils import get_url, now_datetime, add_days

	if not from_date:
		from_date = add_days(now_datetime().date(), -1)
	if not to_date:
		to_date = add_days(now_datetime().date(), -1)

	errors = get_errors(from_date, to_date, limit)

	if errors:
		return 1, _("""<h4>Scheduler Failed Events (max {limit}):</h4>	<p>URL: <a href="{url}" target="_blank">{url}</a></p><hr>{errors}""").format(
			limit=limit, url=get_url(), errors="<hr>".join(errors))
	else:
		return 0, _("<p>Scheduler didn't encounter any problems.</p>")
def make_sales_order(**args):
	so = frappe.new_doc("Sales Order")
	args = frappe._dict(args)
	if args.transaction_date:
		so.transaction_date = args.transaction_date

	so.company = args.company or "_Test Company"
	so.customer = args.customer or "_Test Customer"
	so.delivery_date = add_days(so.transaction_date, 10)
	so.currency = args.currency or "INR"
	if args.selling_price_list:
		so.selling_price_list = args.selling_price_list

	if "warehouse" not in args:
		args.warehouse = "_Test Warehouse - _TC"

	if args.item_list:
		for item in args.item_list:
			so.append("items", item)

	else:
		so.append("items", {
			"item_code": args.item or args.item_code or "_Test Item",
			"warehouse": args.warehouse,
			"qty": args.qty or 10,
			"rate": args.rate or 100,
			"conversion_factor": 1.0,
		})

	if not args.do_not_save:
		so.insert()
		if not args.do_not_submit:
			so.submit()

	return so
Beispiel #26
0
def get_next_dep_date(doc, dep_freq, tot_dep):
	#Next depreciation date shoud be last date of the purchase date if monthly or last date
	#of period of depreciation
	#if monthly depreciation then last day or month, if bi-monthly then last day of month+1
	#if 3 monthly then last day of quarter and not 3 months
	#if 4 monthly then last day of third and not 4 months and so on and so forth
	fy_doc = get_fy_doc(doc)
	r = relativedelta.relativedelta(add_days(fy_doc.year_end_date,1), fy_doc.year_start_date)
	fy_months = r.years*12 + r.months
	dep_in_fy = cint(fy_months)/flt(dep_freq)
	booked_deps_months = (cint(doc.number_of_depreciations_booked)*cint(dep_freq))
	last_day = add_months(get_last_day(doc.purchase_date), booked_deps_months)
	base_last_day = get_last_day(doc.purchase_date)
	base_dep_date = None
	if dep_in_fy >= 1 and dep_in_fy % 1  == 0:
		for i in range(0, cint(tot_dep)):
			dep_date = get_last_day(add_months(fy_doc.year_start_date, (i*dep_freq -1)))
			if base_last_day <= dep_date and base_dep_date is None:
				base_dep_date = dep_date

			if last_day <= dep_date:
				doc.next_depreciation_date = dep_date
				break
			else:
				doc.next_depreciation_date = fy_doc.year_end_date
	elif dep_in_fy % 1  != 0:
		frappe.throw('Frequency Causing Depreciations not to be posted equally in FY, \
			please change the frequency of depreciation')
	else:
		frappe.throw('Months between depreciation cannot be less than 1')
	return base_dep_date
Beispiel #27
0
def make_leave_application():
	allocated_leaves = frappe.get_all("Leave Allocation", fields=['employee', 'leave_type'])
	
	for allocated_leave in allocated_leaves:
		leave_balance = get_leave_balance_on(allocated_leave.employee, allocated_leave.leave_type, frappe.flags.current_date,
			consider_all_leaves_in_the_allocation_period=True)
		if leave_balance != 0:
			if leave_balance == 1:
				to_date = frappe.flags.current_date
			else:
				to_date = add_days(frappe.flags.current_date, random.randint(0, leave_balance-1))
				
			leave_application = frappe.get_doc({
				"doctype": "Leave Application",
				"employee": allocated_leave.employee,
				"from_date": frappe.flags.current_date,
				"to_date": to_date,
				"leave_type": allocated_leave.leave_type,
				"status": "Approved"
			})
			try:
				leave_application.insert()
				leave_application.submit()
				frappe.db.commit()
			except (OverlapError):
				frappe.db.rollback()
Beispiel #28
0
	def validate_schedule_date_for_holiday_list(self, schedule_date, sales_person):
		from erpnext.accounts.utils import get_fiscal_year
		validated = False
		fy_details = ""

		try:
			fy_details = get_fiscal_year(date=schedule_date, verbose=0)
		except Exception:
			pass

		if fy_details and fy_details[0]:
			# check holiday list in employee master
			holiday_list = frappe.db.sql_list("""select h.holiday_date from `tabEmployee` emp,
				`tabSales Person` sp, `tabHoliday` h, `tabHoliday List` hl
				where sp.name=%s and emp.name=sp.employee
				and hl.name=emp.holiday_list and
				h.parent=hl.name and
				hl.fiscal_year=%s""", (sales_person, fy_details[0]))
			if not holiday_list:
				# check global holiday list
				holiday_list = frappe.db.sql("""select h.holiday_date from
					`tabHoliday` h, `tabHoliday List` hl
					where h.parent=hl.name and ifnull(hl.is_default, 0) = 1
					and hl.fiscal_year=%s""", fy_details[0])

			if not validated and holiday_list:
				if schedule_date in holiday_list:
					schedule_date = add_days(schedule_date, -1)
				else:
					validated = True

		return schedule_date
Beispiel #29
0
	def test_make_sales_invoice_with_terms(self):
		so = make_sales_order(do_not_submit=True)

		self.assertRaises(frappe.ValidationError, make_sales_invoice, so.name)

		so.update({"payment_terms_template": "_Test Payment Term Template"})

		so.save()
		so.submit()
		si = make_sales_invoice(so.name)

		self.assertEquals(len(si.get("items")), len(so.get("items")))
		self.assertEquals(len(si.get("items")), 1)

		si.insert()

		self.assertEqual(si.payment_schedule[0].payment_amount, 500.0)
		self.assertEqual(si.payment_schedule[0].due_date, so.transaction_date)
		self.assertEqual(si.payment_schedule[1].payment_amount, 500.0)
		self.assertEqual(si.payment_schedule[1].due_date, add_days(so.transaction_date, 30))

		si.submit()

		si1 = make_sales_invoice(so.name)
		self.assertEquals(len(si1.get("items")), 0)
Beispiel #30
0
def get_item_details(args):
	"""
		args = {
			"item_code": "",
			"warehouse": None,
			"customer": "",
			"conversion_rate": 1.0,
			"selling_price_list": None,
			"price_list_currency": None,
			"plc_conversion_rate": 1.0,
			"parenttype": "",
			"parent": "",
			"supplier": None,
			"transaction_date": None,
			"conversion_rate": 1.0,
			"buying_price_list": None,
			"is_subcontracted": "Yes" / "No",
			"transaction_type": "selling",
			"ignore_pricing_rule": 0/1
			"project_name": ""
		}
	"""
	args = process_args(args)
	item_doc = frappe.get_doc("Item", args.item_code)
	item = item_doc

	validate_item_details(args, item)

	out = get_basic_details(args, item)

	get_party_item_code(args, item_doc, out)

	if out.get("warehouse"):
		out.update(get_available_qty(args.item_code, out.warehouse))
		out.update(get_projected_qty(item.name, out.warehouse))

	get_price_list_rate(args, item_doc, out)

	if args.transaction_type == "selling" and cint(args.is_pos):
		out.update(get_pos_profile_item_details(args.company, args))

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

	out.update(get_pricing_rule_for_item(args))

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

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

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

	return out
Beispiel #31
0
def get_period_list(from_fiscal_year,
                    to_fiscal_year,
                    periodicity,
                    accumulated_values=False,
                    company=None,
                    reset_period_on_fy_change=True):
    """Get a list of dict {"from_date": from_date, "to_date": to_date, "key": key, "label": label}
		Periodicity can be (Yearly, Quarterly, Monthly)"""

    fiscal_year = get_fiscal_year_data(from_fiscal_year, to_fiscal_year)
    validate_fiscal_year(fiscal_year, from_fiscal_year, to_fiscal_year)

    # start with first day, so as to avoid year to_dates like 2-April if ever they occur]
    year_start_date = getdate(fiscal_year.year_start_date)
    year_end_date = getdate(fiscal_year.year_end_date)

    months_to_add = {
        "Yearly": 12,
        "Half-Yearly": 6,
        "Quarterly": 3,
        "Monthly": 1
    }[periodicity]

    period_list = []

    start_date = year_start_date
    months = get_months(year_start_date, year_end_date)

    for i in range(cint(math.ceil(months / months_to_add))):
        period = frappe._dict({"from_date": start_date})

        to_date = add_months(start_date, months_to_add)
        start_date = to_date

        # Subtract one day from to_date, as it may be first day in next fiscal year or month
        to_date = add_days(to_date, -1)

        if to_date <= year_end_date:
            # the normal case
            period.to_date = to_date
        else:
            # if a fiscal year ends before a 12 month period
            period.to_date = year_end_date

        period.to_date_fiscal_year = get_fiscal_year(period.to_date,
                                                     company=company)[0]
        period.from_date_fiscal_year_start_date = get_fiscal_year(
            period.from_date, company=company)[1]

        period_list.append(period)

        if period.to_date == year_end_date:
            break

    # common processing
    for opts in period_list:
        key = opts["to_date"].strftime("%b_%Y").lower()
        if periodicity == "Monthly" and not accumulated_values:
            label = formatdate(opts["to_date"], "MMM YYYY")
        else:
            if not accumulated_values:
                label = get_label(periodicity, opts["from_date"],
                                  opts["to_date"])
            else:
                if reset_period_on_fy_change:
                    label = get_label(periodicity,
                                      opts.from_date_fiscal_year_start_date,
                                      opts["to_date"])
                else:
                    label = get_label(periodicity, period_list[0].from_date,
                                      opts["to_date"])

        opts.update({
            "key": key.replace(" ", "_").replace("-", "_"),
            "label": label,
            "year_start_date": year_start_date,
            "year_end_date": year_end_date
        })

    return period_list
def get_dates(args):
    """get list of dates in between from date and to date"""
    no_of_days = date_diff(add_days(args["to_date"], 1), args["from_date"])
    dates = [add_days(args["from_date"], i) for i in range(0, no_of_days)]
    return dates
Beispiel #33
0
def create_ts():
    day = add_days(today(), -1)
    # days = ["2018-07-30"]
    # for day in days:
    attendance = frappe.get_all("Attendance",
                                fields=[
                                    'name', 'employee', 'attendance_date',
                                    'out_date', 'in_time', 'out_time',
                                    'total_working_hours'
                                ],
                                filters={'attendance_date': day})
    for doc in attendance:
        if doc.attendance_date and doc.out_date and doc.in_time and doc.out_time:
            employee = frappe.get_doc("Employee", doc.employee)

            if employee.employment_type == 'Operator':
                ot_hours = calculate_hours(doc.attendance_date, doc.out_date,
                                           doc.in_time, doc.out_time,
                                           doc.employee)
                if ot_hours:
                    from_date = doc.attendance_date
                    to_date = doc.out_date
                    from_time = str(from_date) + " " + doc.in_time
                    from_time_f = datetime.strptime(
                        from_time, '%Y-%m-%d %H:%M:%S') + timedelta(hours=(
                            (employee.working_hours).seconds // 3600))
                    to_time = str(to_date) + " " + doc.out_time
                    to_time_f = datetime.strptime(to_time, '%Y-%m-%d %H:%M:%S')
                    ts_id = frappe.db.get_value(
                        "Timesheet", {
                            "employee": doc.employee,
                            "start_date": from_date,
                            "end_date": to_date
                        })
                    if ts_id:
                        ts = frappe.get_doc("Timesheet", ts_id)
                        ts.update({
                            "company": doc.company,
                            "employee": doc.employee,
                            "start_date": from_date,
                            "end_date": to_date,
                        })
                        ts.time_logs[0].activity_type = "OT"
                        ts.time_logs[0].hours = round(flt(ot_hours / 3600.00))
                        ts.time_logs[0].from_time = from_time_f
                        ts.time_logs[0].to_time = to_time_f
                        ts.save(ignore_permissions=True)
                        frappe.db.commit()
                    else:
                        ts = frappe.new_doc("Timesheet")
                        ts.company = doc.company
                        ts.employee = doc.employee
                        ts.start_date = from_date
                        ts.end_date = to_date
                        ts.append(
                            "time_logs", {
                                "activity_type": "OT",
                                "hours": round(flt(ot_hours / 3600.00)),
                                "from_time": from_time_f,
                                "to_time": to_time_f
                            })
                        ts.insert()
                        ts.save(ignore_permissions=True)
                        frappe.db.commit()
	def test_is_dormant(self):
		self.assertTrue(is_dormant(check_time= get_datetime('2100-01-01 00:00:00')))
		self.assertTrue(is_dormant(check_time = add_days(frappe.db.get_last_created('Activity Log'), 5)))
		self.assertFalse(is_dormant(check_time = frappe.db.get_last_created('Activity Log')))
    def test_backdated_stock_reco_qty_reposting(self):
        """
		Test if a backdated stock reco recalculates future qty until next reco.
		-------------------------------------------
		Var		| Doc	|	Qty	| Balance
		-------------------------------------------
		PR5     | PR    |   10  |  10   (posting date: today-4) [backdated]
		SR5		| Reco	|	0	|	8	(posting date: today-4) [backdated]
		PR1		| PR	|	10	|	18	(posting date: today-3)
		PR2		| PR	|	1	|	19	(posting date: today-2)
		SR4		| Reco	|	0	|	6	(posting date: today-1) [backdated]
		PR3		| PR	|	1	|	7	(posting date: today) # can't post future PR
		"""
        item_code = make_item().name
        warehouse = "_Test Warehouse - _TC"

        frappe.flags.dont_execute_stock_reposts = True

        def assertBalance(doc, qty_after_transaction):
            sle_balance = frappe.db.get_value("Stock Ledger Entry", {
                "voucher_no": doc.name,
                "is_cancelled": 0
            }, "qty_after_transaction")
            self.assertEqual(sle_balance, qty_after_transaction)

        pr1 = make_purchase_receipt(item_code=item_code,
                                    warehouse=warehouse,
                                    qty=10,
                                    rate=100,
                                    posting_date=add_days(nowdate(), -3))
        pr2 = make_purchase_receipt(item_code=item_code,
                                    warehouse=warehouse,
                                    qty=1,
                                    rate=100,
                                    posting_date=add_days(nowdate(), -2))
        pr3 = make_purchase_receipt(item_code=item_code,
                                    warehouse=warehouse,
                                    qty=1,
                                    rate=100,
                                    posting_date=nowdate())
        assertBalance(pr1, 10)
        assertBalance(pr3, 12)

        # post backdated stock reco in between
        sr4 = create_stock_reconciliation(item_code=item_code,
                                          warehouse=warehouse,
                                          qty=6,
                                          rate=100,
                                          posting_date=add_days(nowdate(), -1))
        assertBalance(pr3, 7)

        # post backdated stock reco at the start
        sr5 = create_stock_reconciliation(item_code=item_code,
                                          warehouse=warehouse,
                                          qty=8,
                                          rate=100,
                                          posting_date=add_days(nowdate(), -4))
        assertBalance(pr1, 18)
        assertBalance(pr2, 19)
        assertBalance(sr4, 6)  # check if future stock reco is unaffected

        # Make a backdated receipt and check only entries till first SR are affected
        pr5 = make_purchase_receipt(item_code=item_code,
                                    warehouse=warehouse,
                                    qty=10,
                                    rate=100,
                                    posting_date=add_days(nowdate(), -5))
        assertBalance(pr5, 10)
        # check if future stock reco is unaffected
        assertBalance(sr4, 6)
        assertBalance(sr5, 8)

        # cancel backdated stock reco and check future impact
        sr5.cancel()
        assertBalance(pr1, 10)
        assertBalance(pr2, 11)
        assertBalance(sr4, 6)  # check if future stock reco is unaffected
Beispiel #36
0
def create_material_request(material_requests):
    """	Create indent on reaching reorder level	"""
    mr_list = []
    exceptions_list = []

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

        frappe.log_error(frappe.get_traceback())

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

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

                for d in items:
                    d = frappe._dict(d)
                    item = frappe.get_doc("Item", d.item_code)
                    uom = item.stock_uom
                    conversion_factor = 1.0

                    if request_type == 'Purchase':
                        uom = item.purchase_uom or item.stock_uom
                        if uom != item.stock_uom:
                            conversion_factor = frappe.db.get_value(
                                "UOM Conversion Detail", {
                                    'parent': item.name,
                                    'uom': uom
                                }, 'conversion_factor') or 1.0

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

                schedule_dates = [d.schedule_date for d in mr.items]
                mr.schedule_date = max(schedule_dates or [nowdate()])
                mr.flags.ignore_mandatory = True
                mr.insert()
                mr.submit()
                mr_list.append(mr)

            except:
                _log_exception()

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

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

    if exceptions_list:
        notify_errors(exceptions_list)

    return mr_list
Beispiel #37
0
    def test_supplied_qty_against_subcontracted_po(self):
        item_code = "_Test Subcontracted FG Item 5"
        make_item('Sub Contracted Raw Material 4', {
            'is_stock_item': 1,
            'is_sub_contracted_item': 1
        })

        make_subcontracted_item(
            item_code=item_code,
            raw_materials=["Sub Contracted Raw Material 4"])

        update_backflush_based_on("Material Transferred for Subcontract")

        order_qty = 250
        po = create_purchase_order(
            item_code=item_code,
            qty=order_qty,
            is_subcontracted="Yes",
            supplier_warehouse="_Test Warehouse 1 - _TC",
            do_not_save=True)

        # Add same subcontracted items multiple times
        po.append(
            "items", {
                "item_code": item_code,
                "qty": order_qty,
                "schedule_date": add_days(nowdate(), 1),
                "warehouse": "_Test Warehouse - _TC"
            })

        po.set_missing_values()
        po.submit()

        # Material receipt entry for the raw materials which will be send to supplier
        make_stock_entry(target="_Test Warehouse - _TC",
                         item_code="Sub Contracted Raw Material 4",
                         qty=500,
                         basic_rate=100)

        rm_items = [
            {
                "item_code": item_code,
                "rm_item_code": "Sub Contracted Raw Material 4",
                "item_name": "_Test Item",
                "qty": 250,
                "warehouse": "_Test Warehouse - _TC",
                "stock_uom": "Nos",
                "name": po.supplied_items[0].name
            },
            {
                "item_code": item_code,
                "rm_item_code": "Sub Contracted Raw Material 4",
                "item_name": "_Test Item",
                "qty": 250,
                "warehouse": "_Test Warehouse - _TC",
                "stock_uom": "Nos"
            },
        ]

        # Raw Materials transfer entry from stores to supplier's warehouse
        rm_item_string = json.dumps(rm_items)
        se = frappe.get_doc(
            make_subcontract_transfer_entry(po.name, rm_item_string))
        se.submit()

        # Test po_detail field has value or not
        for item_row in se.items:
            self.assertEqual(item_row.po_detail,
                             po.supplied_items[item_row.idx - 1].name)

        po_doc = frappe.get_doc("Purchase Order", po.name)
        for row in po_doc.supplied_items:
            # Valid that whether transferred quantity is matching with supplied qty or not in the purchase order
            self.assertEqual(row.supplied_qty, 250.0)

        update_backflush_based_on("BOM")
Beispiel #38
0
def get_item_details(args):
    """
		args = {
			"item_code": "",
			"warehouse": None,
			"customer": "",
			"conversion_rate": 1.0,
			"selling_price_list": None,
			"price_list_currency": None,
			"plc_conversion_rate": 1.0,
			"doctype": "",
			"name": "",
			"supplier": None,
			"transaction_date": None,
			"conversion_rate": 1.0,
			"buying_price_list": None,
			"is_subcontracted": "Yes" / "No",
			"ignore_pricing_rule": 0/1
			"project": ""
		}
	"""
    args = process_args(args)
    item_doc = frappe.get_doc("Item", args.item_code)
    item = item_doc

    validate_item_details(args, item)

    out = get_basic_details(args, item)

    get_party_item_code(args, item_doc, out)

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

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

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

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

    get_price_list_rate(args, item_doc, out)

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

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

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

    out.update(get_pricing_rule_for_item(args))

    if (args.get("doctype") == "Delivery Note" or
     (args.get("doctype") == "Sales Invoice" and args.get('update_stock'))) \
     and out.warehouse and out.stock_qty > 0:

        if out.has_serial_no:
            out.serial_no = get_serial_no(out, args.serial_no)

        if out.has_batch_no and not args.get("batch_no"):
            out.batch_no = get_batch_no(out.item_code, out.warehouse, out.qty)
            actual_batch_qty = get_batch_qty(out.batch_no, out.warehouse,
                                             out.item_code)
            if actual_batch_qty:
                out.update(actual_batch_qty)

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

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

    get_gross_profit(out)

    return out
Beispiel #39
0
def get_item_details(args,
                     doc=None,
                     for_validate=False,
                     overwrite_warehouse=True):
    """
		args = {
			"item_code": "",
			"warehouse": None,
			"customer": "",
			"conversion_rate": 1.0,
			"selling_price_list": None,
			"price_list_currency": None,
			"plc_conversion_rate": 1.0,
			"doctype": "",
			"name": "",
			"supplier": None,
			"transaction_date": None,
			"conversion_rate": 1.0,
			"buying_price_list": None,
			"is_subcontracted": "Yes" / "No",
			"ignore_pricing_rule": 0/1
			"project": ""
			"set_warehouse": ""
		}
	"""

    args = process_args(args)
    item = frappe.get_cached_doc("Item", args.item_code)
    validate_item_details(args, item)

    out = get_basic_details(args, item, overwrite_warehouse)

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

    if doc and doc.get('doctype') == 'Purchase Invoice':
        args['bill_date'] = doc.get('bill_date')

    if doc:
        args['posting_date'] = doc.get('posting_date')
        args['transaction_date'] = doc.get('transaction_date')

    get_item_tax_template(args, item, out)
    out["item_tax_rate"] = get_item_tax_map(args.company, args.get("item_tax_template") if out.get("item_tax_template") is None \
     else out.get("item_tax_template"), as_json=True)

    get_party_item_code(args, item, out)

    set_valuation_rate(out, args)

    update_party_blanket_order(args, out)

    get_price_list_rate(args, item, out)

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

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

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

    data = get_pricing_rule_for_item(args,
                                     out.price_list_rate,
                                     doc,
                                     for_validate=for_validate)

    out.update(data)

    update_stock(args, out)

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

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

    get_gross_profit(out)
    if args.doctype == 'Material Request':
        out.rate = args.rate or out.price_list_rate
        out.amount = flt(args.qty * out.rate)

    return out
Beispiel #40
0
def send(recipients=None,
         sender=None,
         subject=None,
         message=None,
         text_content=None,
         reference_doctype=None,
         reference_name=None,
         unsubscribe_method=None,
         unsubscribe_params=None,
         unsubscribe_message=None,
         attachments=None,
         reply_to=None,
         cc=[],
         bcc=[],
         message_id=None,
         in_reply_to=None,
         send_after=None,
         expose_recipients=None,
         send_priority=1,
         communication=None,
         now=False,
         read_receipt=None,
         queue_separately=False,
         is_notification=False,
         add_unsubscribe_link=1,
         inline_images=None,
         header=None,
         print_letterhead=False):
    """Add email to sending queue (Email Queue)

	:param recipients: List of recipients.
	:param sender: Email sender.
	:param subject: Email subject.
	:param message: Email message.
	:param text_content: Text version of email message.
	:param reference_doctype: Reference DocType of caller document.
	:param reference_name: Reference name of caller document.
	:param send_priority: Priority for Email Queue, default 1.
	:param unsubscribe_method: URL method for unsubscribe. Default is `/api/method/frappe.email.queue.unsubscribe`.
	:param unsubscribe_params: additional params for unsubscribed links. default are name, doctype, email
	:param attachments: Attachments to be sent.
	:param reply_to: Reply to be captured here (default inbox)
	:param in_reply_to: Used to send the Message-Id of a received email back as In-Reply-To.
	:param send_after: Send this email after the given datetime. If value is in integer, then `send_after` will be the automatically set to no of days from current date.
	:param communication: Communication link to be set in Email Queue record
	:param now: Send immediately (don't send in the background)
	:param queue_separately: Queue each email separately
	:param is_notification: Marks email as notification so will not trigger notifications from system
	:param add_unsubscribe_link: Send unsubscribe link in the footer of the Email, default 1.
	:param inline_images: List of inline images as {"filename", "filecontent"}. All src properties will be replaced with random Content-Id
	:param header: Append header in email (boolean)
	"""
    if not unsubscribe_method:
        unsubscribe_method = "/api/method/frappe.email.queue.unsubscribe"

    if not recipients and not cc:
        return

    if isinstance(recipients, string_types):
        recipients = split_emails(recipients)

    if isinstance(cc, string_types):
        cc = split_emails(cc)

    if isinstance(bcc, string_types):
        bcc = split_emails(bcc)

    if isinstance(send_after, int):
        send_after = add_days(nowdate(), send_after)

    email_account = get_outgoing_email_account(True,
                                               append_to=reference_doctype,
                                               sender=sender)
    if not sender or sender == "Administrator":
        sender = email_account.default_sender

    if not text_content:
        try:
            text_content = html2text(message)
        except HTMLParser.HTMLParseError:
            text_content = "See html attachment"

    recipients = list(set(recipients))
    cc = list(set(cc))

    all_ids = tuple(recipients + cc)

    unsubscribed = frappe.db.sql_list(
        '''
		SELECT
			distinct email
		from
			`tabEmail Unsubscribe`
		where
			email in %(all_ids)s
			and (
				(
					reference_doctype = %(reference_doctype)s
					and reference_name = %(reference_name)s
				)
				or global_unsubscribe = 1
			)
	''', {
            'all_ids': all_ids,
            'reference_doctype': reference_doctype,
            'reference_name': reference_name,
        })

    recipients = [r for r in recipients if r and r not in unsubscribed]

    if cc:
        cc = [r for r in cc if r and r not in unsubscribed]

    if not recipients and not cc:
        # Recipients may have been unsubscribed, exit quietly
        return

    email_text_context = text_content

    should_append_unsubscribe = (add_unsubscribe_link and reference_doctype
                                 and (unsubscribe_message
                                      or reference_doctype == "Newsletter")
                                 and add_unsubscribe_link == 1)

    unsubscribe_link = None
    if should_append_unsubscribe:
        unsubscribe_link = get_unsubscribe_message(unsubscribe_message,
                                                   expose_recipients)
        email_text_context += unsubscribe_link.text

    email_content = get_formatted_html(subject,
                                       message,
                                       email_account=email_account,
                                       header=header,
                                       unsubscribe_link=unsubscribe_link)

    # add to queue
    add(recipients,
        sender,
        subject,
        formatted=email_content,
        text_content=email_text_context,
        reference_doctype=reference_doctype,
        reference_name=reference_name,
        attachments=attachments,
        reply_to=reply_to,
        cc=cc,
        bcc=bcc,
        message_id=message_id,
        in_reply_to=in_reply_to,
        send_after=send_after,
        send_priority=send_priority,
        email_account=email_account,
        communication=communication,
        add_unsubscribe_link=add_unsubscribe_link,
        unsubscribe_method=unsubscribe_method,
        unsubscribe_params=unsubscribe_params,
        expose_recipients=expose_recipients,
        read_receipt=read_receipt,
        queue_separately=queue_separately,
        is_notification=is_notification,
        inline_images=inline_images,
        header=header,
        now=now,
        print_letterhead=print_letterhead)
    def test_payment_days_based_on_attendance(self):
        from erpnext.hr.doctype.attendance.attendance import mark_attendance
        no_of_days = self.get_no_of_days()

        # Payroll based on attendance
        frappe.db.set_value("Payroll Settings", None, "payroll_based_on",
                            "Attendance")
        frappe.db.set_value("Payroll Settings", None,
                            "daily_wages_fraction_for_half_day", 0.75)

        emp_id = make_employee(
            "*****@*****.**")
        frappe.db.set_value("Employee", emp_id, {
            "relieving_date": None,
            "status": "Active"
        })

        frappe.db.set_value("Leave Type", "Leave Without Pay",
                            "include_holiday", 0)

        month_start_date = get_first_day(nowdate())
        month_end_date = get_last_day(nowdate())

        first_sunday = frappe.db.sql(
            """
			select holiday_date from `tabHoliday`
			where parent = 'Salary Slip Test Holiday List'
				and holiday_date between %s and %s
			order by holiday_date
		""", (month_start_date, month_end_date))[0][0]

        mark_attendance(emp_id, first_sunday, 'Absent',
                        ignore_validate=True)  # invalid lwp
        mark_attendance(emp_id,
                        add_days(first_sunday, 1),
                        'Absent',
                        ignore_validate=True)  # counted as absent
        mark_attendance(emp_id,
                        add_days(first_sunday, 2),
                        'Half Day',
                        leave_type='Leave Without Pay',
                        ignore_validate=True)  # valid 0.75 lwp
        mark_attendance(emp_id,
                        add_days(first_sunday, 3),
                        'On Leave',
                        leave_type='Leave Without Pay',
                        ignore_validate=True)  # valid lwp
        mark_attendance(emp_id,
                        add_days(first_sunday, 4),
                        'On Leave',
                        leave_type='Casual Leave',
                        ignore_validate=True)  # invalid lwp
        mark_attendance(emp_id,
                        add_days(first_sunday, 7),
                        'On Leave',
                        leave_type='Leave Without Pay',
                        ignore_validate=True)  # invalid lwp

        ss = make_employee_salary_slip(
            "*****@*****.**", "Monthly",
            "Test Payment Based On Attendence")

        self.assertEqual(ss.leave_without_pay, 1.25)
        self.assertEqual(ss.absent_days, 1)

        days_in_month = no_of_days[0]
        no_of_holidays = no_of_days[1]

        self.assertEqual(ss.payment_days,
                         days_in_month - no_of_holidays - 2.25)

        #Gross pay calculation based on attendances
        gross_pay = 78000 - ((78000 / (days_in_month - no_of_holidays)) *
                             flt(ss.leave_without_pay + ss.absent_days))

        self.assertEqual(ss.gross_pay, gross_pay)

        frappe.db.set_value("Payroll Settings", None, "payroll_based_on",
                            "Leave")
    def test_payment_days(self):
        no_of_days = self.get_no_of_days()
        # Holidays not included in working days
        frappe.db.set_value("Payroll Settings", None,
                            "include_holidays_in_total_working_days", 1)

        # set joinng date in the same month
        make_employee("*****@*****.**")
        if getdate(nowdate()).day >= 15:
            relieving_date = getdate(add_days(nowdate(), -10))
            date_of_joining = getdate(add_days(nowdate(), -10))
        elif getdate(nowdate()).day < 15 and getdate(nowdate()).day >= 5:
            date_of_joining = getdate(add_days(nowdate(), -3))
            relieving_date = getdate(add_days(nowdate(), -3))
        elif getdate(nowdate()).day < 5 and not getdate(nowdate()).day == 1:
            date_of_joining = getdate(add_days(nowdate(), -1))
            relieving_date = getdate(add_days(nowdate(), -1))
        elif getdate(nowdate()).day == 1:
            date_of_joining = getdate(nowdate())
            relieving_date = getdate(nowdate())

        frappe.db.set_value(
            "Employee",
            frappe.get_value("Employee",
                             {"employee_name": "*****@*****.**"},
                             "name"), "date_of_joining", date_of_joining)
        frappe.db.set_value(
            "Employee",
            frappe.get_value("Employee",
                             {"employee_name": "*****@*****.**"},
                             "name"), "relieving_date", None)
        frappe.db.set_value(
            "Employee",
            frappe.get_value("Employee",
                             {"employee_name": "*****@*****.**"},
                             "name"), "status", "Active")

        ss = make_employee_salary_slip("*****@*****.**",
                                       "Monthly", "Test Payment Days")

        self.assertEqual(ss.total_working_days, no_of_days[0])
        self.assertEqual(ss.payment_days,
                         (no_of_days[0] - getdate(date_of_joining).day + 1))

        # set relieving date in the same month
        frappe.db.set_value(
            "Employee",
            frappe.get_value("Employee",
                             {"employee_name": "*****@*****.**"},
                             "name"), "date_of_joining",
            (add_days(nowdate(), -60)))
        frappe.db.set_value(
            "Employee",
            frappe.get_value("Employee",
                             {"employee_name": "*****@*****.**"},
                             "name"), "relieving_date", relieving_date)
        frappe.db.set_value(
            "Employee",
            frappe.get_value("Employee",
                             {"employee_name": "*****@*****.**"},
                             "name"), "status", "Left")
        ss.save()

        self.assertEqual(ss.total_working_days, no_of_days[0])
        self.assertEqual(ss.payment_days, getdate(relieving_date).day)

        frappe.db.set_value(
            "Employee",
            frappe.get_value("Employee",
                             {"employee_name": "*****@*****.**"},
                             "name"), "relieving_date", None)
        frappe.db.set_value(
            "Employee",
            frappe.get_value("Employee",
                             {"employee_name": "*****@*****.**"},
                             "name"), "status", "Active")
    def fetch_transactions(self, from_date=None):
        def update_transactions(transactions, after_date, bank_account):
            trans_ids = frappe.get_all(
                "Bank Transaction",
                filters=[
                    ["creation", ">",
                     add_days(after_date, -1)],
                    ["bank_account", "=", bank_account],
                ],
                fields="transaction_id",
            )
            existing_transactions = [
                item["transaction_id"] for item in trans_ids
            ]
            count = 0
            for transaction in transactions:
                for key in ("Withdrawal", "Deposit", "Closing Balance"):
                    if transaction.get(key):
                        transaction[key] = flt(transaction[key])
                transaction["Cheque/Ref. No."] = str(
                    transaction["Cheque/Ref. No."]).replace('.0', '')

                transaction_id = hashlib.sha224(
                    str(transaction).encode()).hexdigest()

                if transaction_id in existing_transactions:
                    continue

                bank_transaction = frappe.get_doc(
                    {"doctype": "Bank Transaction"})

                bank_transaction.update({
                    "transaction_id":
                    transaction_id,
                    "date":
                    getdate(transaction["Date"]),
                    "description":
                    transaction["Narration"],
                    "debit":
                    flt(transaction["Withdrawal"]),
                    "credit":
                    flt(transaction["Deposit"]),
                    "reference_number":
                    transaction["Cheque/Ref. No."],
                    "closing_balance":
                    flt(transaction["Closing Balance"]),
                    "bank_account":
                    bank_account,
                    "unallocated_amount":
                    abs(
                        flt(transaction["Deposit"]) -
                        flt(transaction["Withdrawal"])),
                })
                bank_transaction.submit()
                count += 1

            frappe.publish_realtime(
                "sync_transactions",
                {
                    "uid": self.uid,
                    "count": count,
                    "after_date": add_days(after_date, -1),
                },
                user=frappe.session.user,
            )

        self.switch_to_frame("main_part")
        self.switch_to_frame("left_menu")
        self.get_element("enquiryatag", selector_type="id", now=True).click()
        self.get_element("SIN_nohref", selector_type="id", now=True).click()

        self.switch_to_frame("main_part")
        self.get_element("selectselAccttype0", "id")
        self.click_option(
            self.get_element("selAccttype", now=True),
            "SCA",
            "Unable to select Account Type",
        )

        self.click_option(
            self.get_element("selAcct", now=True),
            self.data.from_account_no,
            "Please verify account number in Bank Integration Settings",
        )

        prev_valid_date = add_months(add_days(today(), -getdate().day + 1), -1)
        if not frappe.db.count(
                "Bank Transaction",
                filters={
                    "bank_account": self.data.bank_account,
                    "date": [">", prev_valid_date],
                },
        ):
            from_date = prev_valid_date
        else:
            from_date = frappe.get_all(
                "Bank Transaction",
                filters={"bank_account": self.data.bank_account},
                fields="date",
                order_by="creation desc",
                limit=1,
            )[0]["date"]
            if getdate(from_date) <= getdate(prev_valid_date):
                from_date = prev_valid_date
            from_date = add_days(from_date, -1)

        self.br.find_elements_by_class_name("radio")[1].click()

        self.get_element("frmDatePicker", selector_type="id",
                         now=True).send_keys(
                             getdate(from_date).strftime("%d/%m/%Y"))
        self.get_element("toDatePicker", selector_type="id",
                         now=True).send_keys(getdate().strftime("%d/%m/%Y"))
        self.br.execute_script("return formSubmitbytype()")

        transactions = []
        self.br.execute_script("$('.datatable').show()")
        transaction_tables = self.br.find_elements_by_class_name("datatable")

        if not transaction_tables:
            self.throw("No New Transactions found")
            self.logout()
            return

        for transaction_table in transaction_tables:
            transactions += pd.read_html(
                transaction_table.get_attribute("outerHTML"))

        self.logout()

        transactions = pd.concat(transactions)
        transactions = transactions.where(pd.notnull(transactions), None)
        transactions = transactions.to_dict("records")
        transactions.reverse()

        update_transactions(transactions, from_date, self.data.bank_account)
Beispiel #44
0
def get_items(date1):
	object_list=[]
	# item_list=frappe.db.sql("""select distinct si.item_code,si.item_name from `tabSales Order` so inner join `tabSales Order Item` si on so.name=si.parent where si.qty>0 and so.transaction_date between %s and %s""",(date1,add_days(date1,5)))
	# for row in item_list:
	# 	balance_qty = frappe.db.sql("""select sum(qty_after_transaction) from `tabStock Ledger Entry`	
	# 	where item_code=%s and is_cancelled='No' limit 1""", (row[0]))
	# 	if not len(balance_qty):
	# 		b_qty=0
	# 	else:
	# 		b_qty=balance_qty[0][0]

	# 	infinity_sale_qty=frappe.db.sql("""select sum(qty) from `tabSales Order Item` where item_code=%s and delivery_date>=%s""",(row[0],today()))
	# 	if not len(infinity_sale_qty):
	# 		inf_s_qty=0
	# 	else:
	# 		inf_s_qty=infinity_sale_qty[0][0]

	# 	infinity_purchase_qty=frappe.db.sql("""select sum(qty) from `tabPurchase Order Item` where item_code=%s and schedule_date>=%s""",(row[0],today()))
	# 	if not len(infinity_purchase_qty):
	# 		inf_p_qty=0
	# 	else:
	# 		inf_p_qty=infinity_purchase_qty[0][0]

	# 	week_sales_qty=frappe.db.sql("""select sum(qty) from `tabSales Order Item` where item_code=%s and delivery_date between %s and %s""",(row[0],(today()),add_days(today(),5)))
	# 	if not len(week_sales_qty):
	# 		week_s_qty=0
	# 	else:
	# 		week_s_qty=week_sales_qty[0][0]

	# 	week_purchase_qty=frappe.db.sql("""select sum(qty) from `tabPurchase Order Item` where item_code=%s and schedule_date between %s and %s""",(row[0],(today()),add_days(today(),5)))
	# 	if not len(week_purchase_qty):
	# 		week_p_qty=0
	# 	else:
	# 		week_p_qty=week_purchase_qty[0][0]

	
	# 	if b_qty==None:
	# 		b_qty=0
	# 	if inf_s_qty==None:
	# 		inf_s_qty=0
	# 	if inf_p_qty==None:
	# 		inf_p_qty=0
	# 	if week_s_qty==None:
	# 		week_s_qty=0
	# 	if week_p_qty==None:
	# 		week_p_qty=0
			
			
	# 	d1 = collections.OrderedDict()
	# 	d1['item_code']=row[0]
	# 	d1['item_name']=row[1]
	# 	d1['balance_qty']=b_qty
	# 	d1['infinity_sales_qty']=inf_s_qty
	# 	d1['infinity_purchase_qty']=inf_p_qty
	# 	d1['week_sales_qty']=week_s_qty
	# 	d1['week_purchase_qty']=week_p_qty
	# 	object_list.append(d1)
		




	item_list1=frappe.db.sql("""select distinct si.item_code,si.item_name from `tabSales Order` so inner join `tabSales Order Item` si on so.name=si.parent where si.qty>0  and so.transaction_date>=%s and so.docstatus=0""",date1)
	for row in item_list1:
		balance_qty = frappe.db.sql("""select qty_after_transaction from `tabStock Ledger Entry`	
		where item_code=%s and is_cancelled='No' order by posting_date desc, posting_time desc, name desc limit 1""", (row[0]))
		if not len(balance_qty):
			b_qty=0
		else:
			b_qty=balance_qty[0][0]

		infinity_sale_qty=frappe.db.sql("""select sum(si.qty) from  `tabSales Order` so inner join `tabSales Order Item` si on so.name=si.parent where si.item_code=%s and so.delivery_date>=%s and so.docstatus=0""",(row[0],date1))
		if not len(infinity_sale_qty):
			inf_s_qty=0
		else:
			inf_s_qty=infinity_sale_qty[0][0]

		infinity_purchase_qty=frappe.db.sql("""select sum(qty) from `tabPurchase Order Item` where item_code=%s and schedule_date>=%s and docstatus=0""",(row[0],date1))
		if not len(infinity_purchase_qty):
			inf_p_qty=0
		else:
			inf_p_qty=infinity_purchase_qty[0][0]

		week_sales_qty=frappe.db.sql("""select sum(si.qty) from  `tabSales Order` as so inner join `tabSales Order Item` as si on so.name=si.parent  where si.item_code=%s and so.docstatus=0 and so.delivery_date between %s and %s group by si.item_code""",(row[0],date1,add_days(date1,4)))
		#return week_sales_qty
		if not len(week_sales_qty):
			week_s_qty=0
		else:
			week_s_qty=week_sales_qty[0][0]

		week_purchase_qty=frappe.db.sql("""select sum(qty) from `tabPurchase Order Item` where item_code=%s and schedule_date between %s and %s and docstatus=0""",(row[0],(date1),add_days(date1,5)))
		if not len(week_purchase_qty):
			week_p_qty=0
		else:
			week_p_qty=week_purchase_qty[0][0]

	
		if b_qty==None:
			b_qty=0
		if inf_s_qty==None:
			inf_s_qty=0
		if inf_p_qty==None:
			inf_p_qty=0
		if week_s_qty==None:
			week_s_qty=0
		if week_p_qty==None:
			week_p_qty=0

		dayname=getdate(date1).strftime("%A")
		first1=frappe.db.sql("""select sum(si.qty) from `tabSales Order` as so inner join `tabSales Order Item` as si on so.name=si.parent where si.item_code=%s and so.delivery_date=%s and so.docstatus=0""",(row[0],date1))
		second1=frappe.db.sql("""select sum(si.qty) from `tabSales Order` as so inner join `tabSales Order Item` as si on so.name=si.parent where si.item_code=%s and so.delivery_date=%s and so.docstatus=0""",(row[0],add_days(date1,1)))
		third1=frappe.db.sql("""select sum(si.qty) from `tabSales Order` as so inner join `tabSales Order Item` as si on so.name=si.parent where si.item_code=%s and so.delivery_date=%s and so.docstatus=0""",(row[0],add_days(date1,2)))
		four1=frappe.db.sql("""select sum(si.qty) from `tabSales Order` as so inner join `tabSales Order Item` as si on so.name=si.parent where si.item_code=%s and so.delivery_date=%s and so.docstatus=0""",(row[0],add_days(date1,3)))
		five1=frappe.db.sql("""select sum(si.qty) from `tabSales Order` as so inner join `tabSales Order Item` as si on so.name=si.parent where si.item_code=%s and so.delivery_date=%s and so.docstatus=0""",(row[0],add_days(date1,4)))
		
		if not first1[0][0]==None:
			first=first1[0][0]
		else:
			first=0

		if not second1[0][0]==None:
			second=second1[0][0]
		else:
			second=0

		if not third1[0][0]==None:
			third=third1[0][0]
		else:
			third=0

		if not four1[0][0]==None:
			four=four1[0][0]
		else:
			four=0

		if not five1[0][0]==None:
			five=five1[0][0]
		else:
			five=0

			
		d1 = collections.OrderedDict()
		d1['item_code']=row[0]
		d1['item_name']=row[1]
		d1['balance_qty']=b_qty
		d1['infinity_sales_qty']=inf_s_qty
		d1['infinity_purchase_qty']=inf_p_qty
		d1['week_sales_qty']=week_s_qty
		d1['week_purchase_qty']=week_p_qty
		d1['dayname']=dayname
		d1['first_date']=date1
		d1['second_date']=add_days(date1,1)
		d1['third_date']=add_days(date1,2)
		d1['four_date']=add_days(date1,3)
		d1['five_date']=add_days(date1,4)
		d1['first']=first
		d1['second']=second
		d1['third']=third
		d1['four']=four
		d1['five']=five
		object_list.append(d1)
		
		
		
		
	return object_list
Beispiel #45
0
def get_exchange_rate(from_currency,
                      to_currency,
                      transaction_date=None,
                      args=None):
    if not (from_currency and to_currency):
        # manqala 19/09/2016: Should this be an empty return or should it throw and exception?
        return
    if from_currency == to_currency:
        return 1

    if not transaction_date:
        transaction_date = nowdate()
    currency_settings = frappe.get_doc("Accounts Settings").as_dict()
    allow_stale_rates = currency_settings.get("allow_stale")

    filters = [["date", "<=", get_datetime_str(transaction_date)],
               ["from_currency", "=", from_currency],
               ["to_currency", "=", to_currency]]

    if args == "for_buying":
        filters.append(["for_buying", "=", "1"])
    elif args == "for_selling":
        filters.append(["for_selling", "=", "1"])

    if not allow_stale_rates:
        stale_days = currency_settings.get("stale_days")
        checkpoint_date = add_days(transaction_date, -stale_days)
        filters.append(["date", ">", get_datetime_str(checkpoint_date)])

    # cksgb 19/09/2016: get last entry in Currency Exchange with from_currency and to_currency.
    entries = frappe.get_all("Currency Exchange",
                             fields=["exchange_rate"],
                             filters=filters,
                             order_by="date desc",
                             limit=1)
    if entries:
        return flt(entries[0].exchange_rate)

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

        if not value:
            import requests
            api_url = "https://frankfurter.erpnext.org/{0}".format(
                transaction_date)
            response = requests.get(api_url,
                                    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} for key date {2}. Please create a Currency Exchange record manually"
              ).format(from_currency, to_currency, transaction_date))
        return 0.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,
                    "requested_by": frappe.session.user,
                    '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,
             "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="#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"))
Beispiel #47
0
def get_period_list(fiscal_year, periodicity, from_beginning=False):
    """Get a list of dict {"to_date": to_date, "key": key, "label": label}
		Periodicity can be (Yearly, Quarterly, Monthly)"""

    fy_start_end_date = frappe.db.get_value(
        "Fiscal Year", fiscal_year, ["year_start_date", "year_end_date"])
    if not fy_start_end_date:
        frappe.throw(_("Fiscal Year {0} not found.").format(fiscal_year))

    start_date = getdate(fy_start_end_date[0])
    end_date = getdate(fy_start_end_date[1])

    if periodicity == "Yearly":
        period_list = [
            _dict({
                "to_date": end_date,
                "key": fiscal_year,
                "label": fiscal_year
            })
        ]
    else:
        months_to_add = {
            "Half-yearly": 6,
            "Quarterly": 3,
            "Monthly": 1
        }[periodicity]

        period_list = []

        # start with first day, so as to avoid year to_dates like 2-April if ever they occur
        to_date = get_first_day(start_date)

        for i in xrange(12 / months_to_add):
            to_date = add_months(to_date, months_to_add)

            if to_date == get_first_day(to_date):
                # if to_date is the first day, get the last day of previous month
                to_date = add_days(to_date, -1)
            else:
                # to_date should be the last day of the new to_date's month
                to_date = get_last_day(to_date)

            if to_date <= end_date:
                # the normal case
                period_list.append(_dict({"to_date": to_date}))

                # if it ends before a full year
                if to_date == end_date:
                    break

            else:
                # if a fiscal year ends before a 12 month period
                period_list.append(_dict({"to_date": end_date}))
                break

    # common processing
    for opts in period_list:
        key = opts["to_date"].strftime("%b_%Y").lower()
        label = formatdate(opts["to_date"], "MMM YYYY")
        opts.update({
            "key": key.replace(" ", "_").replace("-", "_"),
            "label": label,
            "year_start_date": start_date,
            "year_end_date": end_date
        })

        if from_beginning:
            # set start date as None for all fiscal periods, used in case of Balance Sheet
            opts["from_date"] = None
        else:
            opts["from_date"] = start_date

    return period_list
Beispiel #48
0
def create_material_request(material_requests):
    """	Create indent on reaching reorder level	"""
    mr_list = []
    exceptions_list = []

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

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

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

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

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

            except:
                _log_exception()

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

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

    if exceptions_list:
        notify_errors(exceptions_list)

    return mr_list
Beispiel #49
0
def update_attendance_time(employee, attendance_date, in_time, out_time):
    twh = ''
    if attendance_date:
        attendance_date = out_date = datetime.strptime(attendance_date,
                                                       '%Y-%m-%d')
        if in_time and out_time:
            in_time_f = datetime.strptime(in_time, '%H:%M:%S').time()
            out_time_f = datetime.strptime(out_time, '%H:%M:%S').time()
            if out_time_f < in_time_f:
                out_date = (add_days(attendance_date, 1)).date()
            in_time = datetime.strptime(in_time, '%H:%M:%S').time()
            in_time = datetime.combine(attendance_date, in_time)
            out_time = datetime.strptime(out_time, '%H:%M:%S').time()
            out_time = datetime.combine(out_date, out_time)

            twh = out_time - in_time
            status = 'Absent'
            if twh > timedelta(hours=4):
                status = 'Half Day'
            if twh >= timedelta(hours=8):
                status = 'Present'
            if twh:
                twh_seconds = twh.total_seconds()
                minutes = twh_seconds // 60
                hours = minutes // 60
                twh = "%02d hr %02d min" % (hours, minutes % 60)
            if frappe.db.exists("Attendance", {
                    "employee": employee,
                    "attendance_date": attendance_date
            }):
                att = frappe.db.get_value("Attendance", {
                    "employee": employee,
                    "attendance_date": attendance_date
                }, "name")
                # frappe.errprint(att)
                exist_att = frappe.get_doc("Attendance", att)
                if not exist_att.in_time or not exist_att.out_time:
                    exist_att.update({
                        "biometric_id": employee,
                        "attendance_date": attendance_date,
                        "status": status,
                        "in_time": in_time,
                        "out_time": out_time,
                        "total_working_hours": twh,
                        "modified_status": "Miss Punch"
                    })
                    exist_att.save(ignore_permissions=True)
                    frappe.db.commit()
            else:
                exist_att = frappe.new_doc("Attendance")
                exist_att.update({
                    "employee": employee,
                    "biometric_id": employee,
                    "attendance_date": attendance_date,
                    "in_time": in_time,
                    "status": status,
                    "out_time": out_time,
                    "total_working_hours": twh,
                    "modified_status": "Miss Punch"
                })
                exist_att.save(ignore_permissions=True)
                exist_att.submit()
                frappe.db.commit()
        return "Ok"
Beispiel #50
0
def get_order_details_week(item,date1):
	data=frappe.db.sql("""select so.name,so.customer,si.item_code,si.item_name,si.qty from `tabSales Order` as so inner join `tabSales Order Item` as si on so.name=si.parent where si.item_code=%s and so.docstatus=0 and si.delivery_date between %s and %s""",(item,date1,add_days(date1,4)),as_dict=True)
	if len(data):
		return data
	else:
		return _(False)
Beispiel #51
0
    def test_gle_with_cwip_toggling(self):
        # TEST: purchase an asset with cwip enabled and then disable cwip and try submitting the asset
        frappe.db.set_value("Asset Category", "Computers",
                            "enable_cwip_accounting", 1)

        pr = make_purchase_receipt(item_code="Macbook Pro",
                                   qty=1,
                                   rate=5000,
                                   do_not_submit=True,
                                   location="Test Location")
        pr.set('taxes', [{
            'category': 'Total',
            'add_deduct_tax': 'Add',
            'charge_type': 'On Net Total',
            'account_head': '_Test Account Service Tax - _TC',
            'description': '_Test Account Service Tax',
            'cost_center': 'Main - _TC',
            'rate': 5.0
        }, {
            'category': 'Valuation and Total',
            'add_deduct_tax': 'Add',
            'charge_type': 'On Net Total',
            'account_head': '_Test Account Shipping Charges - _TC',
            'description': '_Test Account Shipping Charges',
            'cost_center': 'Main - _TC',
            'rate': 5.0
        }])
        pr.submit()
        expected_gle = (("Asset Received But Not Billed - _TC", 0.0, 5250.0),
                        ("CWIP Account - _TC", 5250.0, 0.0))
        pr_gle = frappe.db.sql(
            """select account, debit, credit from `tabGL Entry`
			where voucher_type='Purchase Receipt' and voucher_no = %s
			order by account""", pr.name)
        self.assertEqual(pr_gle, expected_gle)

        pi = make_invoice(pr.name)
        pi.submit()
        expected_gle = (
            ("_Test Account Service Tax - _TC", 250.0, 0.0),
            ("_Test Account Shipping Charges - _TC", 250.0, 0.0),
            ("Asset Received But Not Billed - _TC", 5250.0, 0.0),
            ("Creditors - _TC", 0.0, 5500.0),
            ("Expenses Included In Asset Valuation - _TC", 0.0, 250.0),
        )
        pi_gle = frappe.db.sql(
            """select account, debit, credit from `tabGL Entry`
			where voucher_type='Purchase Invoice' and voucher_no = %s
			order by account""", pi.name)
        self.assertEqual(pi_gle, expected_gle)

        asset = frappe.db.get_value('Asset', {
            'purchase_receipt': pr.name,
            'docstatus': 0
        }, 'name')
        asset_doc = frappe.get_doc('Asset', asset)
        month_end_date = get_last_day(nowdate())
        asset_doc.available_for_use_date = nowdate(
        ) if nowdate() != month_end_date else add_days(nowdate(), -15)
        self.assertEqual(asset_doc.gross_purchase_amount, 5250.0)
        asset_doc.append(
            "finance_books", {
                "expected_value_after_useful_life": 200,
                "depreciation_method": "Straight Line",
                "total_number_of_depreciations": 3,
                "frequency_of_depreciation": 10,
                "depreciation_start_date": month_end_date
            })

        # disable cwip and try submitting
        frappe.db.set_value("Asset Category", "Computers",
                            "enable_cwip_accounting", 0)
        asset_doc.submit()
        # asset should have gl entries even if cwip is disabled
        expected_gle = (("_Test Fixed Asset - _TC", 5250.0, 0.0),
                        ("CWIP Account - _TC", 0.0, 5250.0))
        gle = frappe.db.sql(
            """select account, debit, credit from `tabGL Entry`
			where voucher_type='Asset' and voucher_no = %s
			order by account""", asset_doc.name)
        self.assertEqual(gle, expected_gle)

        frappe.db.set_value("Asset Category", "Computers",
                            "enable_cwip_accounting", 1)
def get_item_details(args):
    """
		args = {
			"item_code": "",
			"warehouse": None,
			"customer": "",
			"conversion_rate": 1.0,
			"selling_price_list": None,
			"price_list_currency": None,
			"plc_conversion_rate": 1.0,
			"doctype": "",
			"name": "",
			"supplier": None,
			"transaction_date": None,
			"conversion_rate": 1.0,
			"buying_price_list": None,
			"is_subcontracted": "Yes" / "No",
			"ignore_pricing_rule": 0/1
			"project": ""
			"set_warehouse": ""
		}
	"""
    args = process_args(args)
    item = frappe.get_cached_doc("Item", args.item_code)
    validate_item_details(args, item)

    out = get_basic_details(args, item)

    get_party_item_code(args, item, out)

    set_valuation_rate(out, args)

    update_party_blanket_order(args, out)

    get_price_list_rate(args, item, out)

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

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

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

    out.update(get_pricing_rule_for_item(args))

    update_stock(args, out)

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

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

    get_gross_profit(out)
    if args.doctype == 'Material Request':
        out.rate = args.rate or out.price_list_rate
        out.amount = flt(args.qty * out.rate)

    return out
Beispiel #53
0
def get_events(start, end, user=None, for_reminder=False, filters=None):
    if not user:
        user = frappe.session.user

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

    filter_condition = get_filters_cond('Event', filters, [])

    tables = ["`tabEvent`"]
    if "`tabEvent Participants`" in filter_condition:
        tables.append("`tabEvent Participants`")

    events = frappe.db.sql("""
		SELECT `tabEvent`.name,
				`tabEvent`.subject,
				`tabEvent`.description,
				`tabEvent`.color,
				`tabEvent`.starts_on,
				`tabEvent`.ends_on,
				`tabEvent`.owner,
				`tabEvent`.all_day,
				`tabEvent`.event_type,
				`tabEvent`.repeat_this_event,
				`tabEvent`.repeat_on,
				`tabEvent`.repeat_till,
				`tabEvent`.monday,
				`tabEvent`.tuesday,
				`tabEvent`.wednesday,
				`tabEvent`.thursday,
				`tabEvent`.friday,
				`tabEvent`.saturday,
				`tabEvent`.sunday
		FROM {tables}
		WHERE (
				(
					(date(`tabEvent`.starts_on) BETWEEN date(%(start)s) AND date(%(end)s))
					OR (date(`tabEvent`.ends_on) BETWEEN date(%(start)s) AND date(%(end)s))
					OR (
						date(`tabEvent`.starts_on) <= date(%(start)s)
						AND date(`tabEvent`.ends_on) >= date(%(end)s)
					)
				)
				OR (
					date(`tabEvent`.starts_on) <= date(%(start)s)
					AND `tabEvent`.repeat_this_event=1
					AND coalesce(`tabEvent`.repeat_till, '3000-01-01') > date(%(start)s)
				)
			)
		{reminder_condition}
		{filter_condition}
		AND (
				`tabEvent`.event_type='Public'
				OR `tabEvent`.owner=%(user)s
				OR EXISTS(
					SELECT `tabDocShare`.name
					FROM `tabDocShare`
					WHERE `tabDocShare`.share_doctype='Event'
						AND `tabDocShare`.share_name=`tabEvent`.name
						AND `tabDocShare`.user=%(user)s
				)
			)
		AND `tabEvent`.status='Open'
		ORDER BY `tabEvent`.starts_on""".format(
        tables=", ".join(tables),
        filter_condition=filter_condition,
        reminder_condition="AND coalesce(`tabEvent`.send_reminder, 0)=1"
        if for_reminder else ""), {
            "start": start,
            "end": end,
            "user": user,
        },
                           as_dict=1)

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

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

        enddate = add_days(date,int(date_diff(e.ends_on.split(" ")[0], e.starts_on.split(" ")[0]))) \
         if (e.starts_on and e.ends_on) else date

        new_event.starts_on = date + " " + e.starts_on.split(" ")[1]
        new_event.ends_on = new_event.ends_on = enddate + " " + e.ends_on.split(
            " ")[1] if e.ends_on else None

        add_events.append(new_event)

    for e in events:
        if e.repeat_this_event:
            e.starts_on = get_datetime_str(e.starts_on)
            e.ends_on = get_datetime_str(e.ends_on) if e.ends_on else None

            event_start, time_str = get_datetime_str(e.starts_on).split(" ")

            repeat = "3000-01-01" if cstr(
                e.repeat_till) == "" else e.repeat_till

            if e.repeat_on == "Yearly":
                start_year = cint(start.split("-")[0])
                end_year = cint(end.split("-")[0])

                # creates a string with date (27) and month (07) eg: 07-27
                event_start = "-".join(event_start.split("-")[1:])

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

                remove_events.append(e)

            if e.repeat_on == "Monthly":
                # creates a string with date (27) and month (07) and year (2019) eg: 2019-07-27
                date = start.split("-")[0] + "-" + start.split(
                    "-")[1] + "-" + event_start.split("-")[2]

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

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

                    date = add_months(start_from, i + 1)
                remove_events.append(e)

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

                remove_events.append(e)

            if e.repeat_on == "Daily":
                for cnt in range(date_diff(end, start) + 1):
                    date = add_days(start, cnt)
                    if getdate(date) >= getdate(event_start) and getdate(
                            date) <= getdate(end) and getdate(date) <= getdate(
                                repeat):
                        add_event(e, date)

                remove_events.append(e)

    for e in remove_events:
        events.remove(e)

    events = events + add_events

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

    return events
    def validate_fields(self):
        if self.export_or_import == 'Export':
            if self.reference_doctype != 'Sales Invoice':
                frappe.throw('Only Sales Invoice is Allowed for Exports')

            #Allow only Sales Invoices with Sales Taxes marked as export and shipping country outside India.
            ref_doc = frappe.get_doc(self.reference_doctype,
                                     self.reference_name)
            stct_doc = frappe.get_doc("Sales Taxes and Charges Template",
                                      ref_doc.taxes_and_charges)
            ship_add_doc = frappe.get_doc("Address",
                                          ref_doc.shipping_address_name)
            bill_add_doc = frappe.get_doc("Address", ref_doc.customer_address)
            if ref_doc.docstatus != 1:
                frappe.throw("Only Submitted Documents are Allowed")
            if self.reference_doctype == 'Sales Invoice':
                ship_country = frappe.db.get_value(
                    "Address", ref_doc.shipping_address_name, "country")
                if stct_doc.is_export != 1:
                    frappe.throw(
                        "Only Sales Invoices Marked as Exports are Allowed")
                if ship_country == "India":
                    frappe.throw("Only Invoices shipped outside India allowed")

                self.reference_date = ref_doc.posting_date
                self.reference_currency = ref_doc.currency
                self.customer_or_supplier = 'Customer'
                self.customer_or_supplier_name = ref_doc.customer
                self.iec_number = stct_doc.iec_code
                self.bill_to_country = bill_add_doc.country
                self.ship_to_country = ship_add_doc.country
                self.grand_total = ref_doc.grand_total
                self.grand_total_inr = ref_doc.base_grand_total

            if self.pan_number:
                validate_pan(self.pan_number)

            if self.shipping_bill_number:
                if self.fob_value == 0:
                    frappe.throw(("Enter FOB Value in {0}").format(
                        self.reference_currency))
                else:
                    if self.fob_value > self.grand_total:
                        frappe.throw(
                            ("FOB Value has to be less than {0}").format(
                                self.grand_total))
                if len(str(self.shipping_bill_number)) != 7:
                    frappe.throw("Shipping Bill Number is Exactly 7 Digits")
                p = re.compile("[0-9]{7}")
                if not p.match(str(self.shipping_bill_number)):
                    frappe.throw("Invalid Shipping Bill Number")
                if not self.shipping_bill_date:
                    frappe.throw(
                        'Shipping Bill Date is Mandatory for Shipping Bill')

            if self.shipping_bill_date:
                self.submission_date_deadline = add_days(
                    self.shipping_bill_date, 21)
                diff = getdate(self.shipping_bill_date) - getdate(
                    self.reference_date)
                if diff.days > 20 or diff.days < -20:
                    frappe.throw(
                        'Out of Range Difference, Contact [email protected]')

                if self.bank_ifsc_code:
                    validate_ifsc_code(self.bank_ifsc_code)
            else:
                self.submission_date_deadline = add_days(
                    self.reference_date, 21)

            if self.brc_number:
                if not self.brc_date:
                    frappe.throw("BRC Date is Mandatory for BRC Number")
                else:
                    if self.brc_date < add_days(self.shipping_bill_date, 15):
                        frappe.throw("BRC Date is NOT VALID")
                if not self.bank_ifsc_code:
                    frappe.throw("Bank IFSC is Mandatory for BRC Number")
                if not self.brc_bill_id:
                    frappe.throw(
                        "BRC Bill ID is mandatory and is different from BRC Number \
						goto DGFT site and enter only IEC Code for Bill ID")
                else:
                    if self.brc_bill_id == self.brc_number:
                        frappe.throw(
                            "BRC Number and Bill ID should be different")
                validate_brc_no(self.brc_number, self.bank_ifsc_code)
                self.brc_status = 'BRC Issued'
            else:
                self.brc_status = 'BRC Pending'

        else:
            frappe.throw("Import Related Tracking Is Not Implemented Yet.")
            if self.reference_doctype != 'Purchase Invoice':
                frappe.throw('Only Purchase Invoice is Allowed for Imports')
            #If IMPORT RELATED TRACKING
            isimport = frappe.db.get_value(
                "Purchase Taxes and Charges Template",
                ref_doc.taxes_and_charges, "is_import")
            if isimport != 1:
                frappe.throw(
                    "Only Purchase Invoices Marked as Import are allowed here")
            self.customer_or_supplier = 'Supplier'
            self.customer_or_supplier_name = ref_doc.supplier
        ship_country = frappe.db.get_value("Address", )
Beispiel #55
0
    def test_make_time_log(self):
        from erpnext.projects.doctype.time_log.test_time_log import make_time_log_test_record
        prod_order = make_prod_order_test_record(item="_Test FG Item 2",
                                                 planned_start_date=now(),
                                                 qty=1,
                                                 do_not_save=True)

        prod_order.set_production_order_operations()
        prod_order.insert()
        prod_order.submit()

        d = prod_order.operations[0]

        d.completed_qty = flt(d.completed_qty)

        time_log = make_time_log_test_record(hours=1,
                                             production_order=prod_order.name,
                                             operation=d.operation,
                                             completed_qty=prod_order.qty -
                                             d.completed_qty,
                                             operation_id=d.name,
                                             for_manufacturing=1,
                                             simulate=True)

        self.assertEqual(prod_order.name, time_log.production_order)
        self.assertEqual((prod_order.qty - d.completed_qty),
                         time_log.completed_qty)
        self.assertEqual(
            time_diff_in_hours(d.planned_end_time, d.planned_start_time),
            time_log.hours)

        manufacturing_settings = frappe.get_doc({
            "doctype":
            "Manufacturing Settings",
            "allow_production_on_holidays":
            0
        })

        manufacturing_settings.save()

        prod_order.load_from_db()
        self.assertEqual(prod_order.operations[0].status, "Completed")
        self.assertEqual(prod_order.operations[0].completed_qty,
                         prod_order.qty)

        self.assertEqual(prod_order.operations[0].actual_operation_time, 60)
        self.assertEqual(prod_order.operations[0].actual_operating_cost, 100)

        time_log.cancel()

        prod_order.load_from_db()
        self.assertEqual(prod_order.operations[0].status, "Pending")
        self.assertEqual(flt(prod_order.operations[0].completed_qty), 0)

        self.assertEqual(flt(prod_order.operations[0].actual_operation_time),
                         0)
        self.assertEqual(flt(prod_order.operations[0].actual_operating_cost),
                         0)

        time_log2 = make_time_log_test_record(from_time=add_days(
            time_log.to_time, 1),
                                              production_order=prod_order.name,
                                              operation=d.operation,
                                              completed_qty=5,
                                              operation_id=d.name,
                                              for_manufacturing=1,
                                              do_not_save=True)

        self.assertRaises(OverProductionLoggedError, time_log2.save)
def execute(filters=None):
    filters.day_before_from_date = add_days(filters.from_date, -1)
    columns, data = get_columns(filters), get_data(filters)
    return columns, data
Beispiel #57
0
    def test_validate_start_date_before_end_date(self):
        self.contract_doc.start_date = nowdate()
        self.contract_doc.end_date = add_days(nowdate(), -1)

        self.assertRaises(frappe.ValidationError, self.contract_doc.insert)
Beispiel #58
0
	def set_end_date(self):
		if self.loan_start_date and self.loan_period:
			self.loan_end_date = add_days(self.loan_start_date, self.loan_period)
    def test_payment_days_based_on_leave_application(self):
        no_of_days = self.get_no_of_days()

        # Payroll based on attendance
        frappe.db.set_value("Payroll Settings", None, "payroll_based_on",
                            "Leave")

        emp_id = make_employee(
            "*****@*****.**")
        frappe.db.set_value("Employee", emp_id, {
            "relieving_date": None,
            "status": "Active"
        })

        frappe.db.set_value("Leave Type", "Leave Without Pay",
                            "include_holiday", 0)

        month_start_date = get_first_day(nowdate())
        month_end_date = get_last_day(nowdate())

        first_sunday = frappe.db.sql(
            """
			select holiday_date from `tabHoliday`
			where parent = 'Salary Slip Test Holiday List'
				and holiday_date between %s and %s
			order by holiday_date
		""", (month_start_date, month_end_date))[0][0]

        make_leave_application(emp_id, first_sunday, add_days(first_sunday, 3),
                               "Leave Without Pay")

        leave_type_ppl = create_leave_type(
            leave_type_name="Test Partially Paid Leave", is_ppl=1)
        leave_type_ppl.save()

        alloc = create_leave_allocation(employee=emp_id,
                                        from_date=add_days(first_sunday, 4),
                                        to_date=add_days(first_sunday, 10),
                                        new_leaves_allocated=3,
                                        leave_type="Test Partially Paid Leave")
        alloc.save()
        alloc.submit()

        #two day leave ppl with fraction_of_daily_salary_per_leave = 0.5 equivalent to single day lwp
        make_leave_application(emp_id, add_days(first_sunday, 4),
                               add_days(first_sunday, 5),
                               "Test Partially Paid Leave")

        ss = make_employee_salary_slip(
            "*****@*****.**",
            "Monthly", "Test Payment Based On Leave Application")

        self.assertEqual(ss.leave_without_pay, 4)

        days_in_month = no_of_days[0]
        no_of_holidays = no_of_days[1]

        self.assertEqual(ss.payment_days, days_in_month - no_of_holidays - 4)

        frappe.db.set_value("Payroll Settings", None, "payroll_based_on",
                            "Leave")
        def update_transactions(transactions, after_date, bank_account):
            trans_ids = frappe.get_all(
                "Bank Transaction",
                filters=[
                    ["creation", ">",
                     add_days(after_date, -1)],
                    ["bank_account", "=", bank_account],
                ],
                fields="transaction_id",
            )
            existing_transactions = [
                item["transaction_id"] for item in trans_ids
            ]
            count = 0
            for transaction in transactions:
                for key in ("Withdrawal", "Deposit", "Closing Balance"):
                    if transaction.get(key):
                        transaction[key] = flt(transaction[key])
                transaction["Cheque/Ref. No."] = str(
                    transaction["Cheque/Ref. No."]).replace('.0', '')

                transaction_id = hashlib.sha224(
                    str(transaction).encode()).hexdigest()

                if transaction_id in existing_transactions:
                    continue

                bank_transaction = frappe.get_doc(
                    {"doctype": "Bank Transaction"})

                bank_transaction.update({
                    "transaction_id":
                    transaction_id,
                    "date":
                    getdate(transaction["Date"]),
                    "description":
                    transaction["Narration"],
                    "debit":
                    flt(transaction["Withdrawal"]),
                    "credit":
                    flt(transaction["Deposit"]),
                    "reference_number":
                    transaction["Cheque/Ref. No."],
                    "closing_balance":
                    flt(transaction["Closing Balance"]),
                    "bank_account":
                    bank_account,
                    "unallocated_amount":
                    abs(
                        flt(transaction["Deposit"]) -
                        flt(transaction["Withdrawal"])),
                })
                bank_transaction.submit()
                count += 1

            frappe.publish_realtime(
                "sync_transactions",
                {
                    "uid": self.uid,
                    "count": count,
                    "after_date": add_days(after_date, -1),
                },
                user=frappe.session.user,
            )