示例#1
0
def get_due_date(posting_date, customer):
	"""
	referenced from erpnext.accounts.party
	"""		
	if not customer or not posting_date:
		return
	
	customer_group = frappe.get_value("Customer", filters={"name": customer}, fieldname="customer_group")
	credit_days_based_on, credit_months, credit_days = frappe.db.get_value("Customer Group", customer_group, ["credit_days_based_on", "consoleerp_credit_months", "consoleerp_credit_days"])
	
	if not credit_months:
		credit_months = 0
	if not credit_days:
		credit_days = 0
	
	due_date = None
	if credit_days_based_on == "Custom Day of Custom Month":
		"""
		frappe.util.data.get_first_day(dt_string, d_years=0, d_months=0):
			Returns the first day of the month for the date specified by date object
			Also adds `d_years` and `d_months` if specified
		"""
		# referenced from get_due_date in party.py
		due_date = (get_first_day(posting_date, 0, credit_months) +
					relativedelta.relativedelta(days=credit_days - 1)).strftime("%Y-%m-%d")
		
	return due_date
def execute(filters=None):
	if not filters: filters = {}

	from_date = get_first_day(filters["month"] + '-' + filters["year"])
	to_date = get_last_day(filters["month"] + '-' + filters["year"])
	total_days_in_month = date_diff(to_date, from_date) +1
	columns = get_columns(total_days_in_month)
	students = get_student_group_students(filters.get("student_group"),1)
	students_list = get_students_list(students)
	att_map = get_attendance_list(from_date, to_date, filters.get("student_group"), students_list)
	data = []
	for stud in students:
		row = [stud.student, stud.student_name]
		student_status = frappe.db.get_value("Student", stud.student, "enabled")
		date = from_date
		total_p = total_a = 0.0
		for day in range(total_days_in_month):
			status="None"
			if att_map.get(stud.student):
				status = att_map.get(stud.student).get(date, "None")
			elif not student_status:
				status = "Inactive"
			else:
				status = "None"
			status_map = {"Present": "P", "Absent": "A", "None": "", "Inactive":"-"}
			row.append(status_map[status])
			if status == "Present":
				total_p += 1
			elif status == "Absent":
				total_a += 1
			date = add_days(date, 1)
		row += [total_p, total_a]
		data.append(row)
	return columns, data
示例#3
0
def make_new_invoice(ref_wrapper, posting_date):
	from erpnext.accounts.utils import get_fiscal_year
	new_invoice = frappe.copy_doc(ref_wrapper)

	mcount = month_map[ref_wrapper.recurring_type]

	invoice_period_from_date = get_next_date(ref_wrapper.invoice_period_from_date, mcount)

	# get last day of the month to maintain period if the from date is first day of its own month
	# and to date is the last day of its own month
	if (cstr(get_first_day(ref_wrapper.invoice_period_from_date)) == \
			cstr(ref_wrapper.invoice_period_from_date)) and \
		(cstr(get_last_day(ref_wrapper.invoice_period_to_date)) == \
			cstr(ref_wrapper.invoice_period_to_date)):
		invoice_period_to_date = get_last_day(get_next_date(ref_wrapper.invoice_period_to_date,
			mcount))
	else:
		invoice_period_to_date = get_next_date(ref_wrapper.invoice_period_to_date, mcount)

	new_invoice.update({
		"posting_date": posting_date,
		"aging_date": posting_date,
		"due_date": add_days(posting_date, cint(date_diff(ref_wrapper.due_date,
			ref_wrapper.posting_date))),
		"invoice_period_from_date": invoice_period_from_date,
		"invoice_period_to_date": invoice_period_to_date,
		"fiscal_year": get_fiscal_year(posting_date)[0],
		"owner": ref_wrapper.owner,
	})

	new_invoice.submit()

	return new_invoice
示例#4
0
def make_new_document(ref_wrapper, date_field, posting_date):
	from erpnext.accounts.utils import get_fiscal_year
	new_document = frappe.copy_doc(ref_wrapper)
	mcount = month_map[ref_wrapper.recurring_type]

	from_date = get_next_date(ref_wrapper.from_date, mcount)

	# get last day of the month to maintain period if the from date is first day of its own month
	# and to date is the last day of its own month
	if (cstr(get_first_day(ref_wrapper.from_date)) == cstr(ref_wrapper.from_date)) and \
		(cstr(get_last_day(ref_wrapper.to_date)) == cstr(ref_wrapper.to_date)):
			to_date = get_last_day(get_next_date(ref_wrapper.to_date, mcount))
	else:
		to_date = get_next_date(ref_wrapper.to_date, mcount)

	new_document.update({
		date_field: posting_date,
		"from_date": from_date,
		"to_date": to_date,
		"fiscal_year": get_fiscal_year(posting_date)[0],
		"owner": ref_wrapper.owner,
	})

	if ref_wrapper.doctype == "Sales Order":
		new_document.update({
			"delivery_date": get_next_date(ref_wrapper.delivery_date, mcount,
				cint(ref_wrapper.repeat_on_day_of_month))
	})

	new_document.submit()

	return new_document
示例#5
0
	def get_employee_holidays(self):
		first_day = get_first_day(self.att_date)
		last_day = get_last_day(self.att_date)
		
		holidays = frappe.db.sql("""select t1.holiday_date from `tabHoliday` t1, tabEmployee t2 where 
			t1.parent = t2.holiday_list and t2.name = %s and t1.holiday_date between %s and %s""",(self.employee, first_day, last_day))
		holidays = [cstr(i[0]) for i in holidays]

		if self.status in ('Weekly Off', 'Public Holiday') and self.att_date not in holidays:
			frappe.throw(_("This date not present in Holiday list.Please select correct date.."))
示例#6
0
文件: party.py 项目: ArchitW/erpnext
def get_due_date(posting_date, party_type, party, company):
	"""Set Due Date = Posting Date + Credit Days"""
	due_date = None
	if posting_date and party:
		due_date = posting_date
		credit_days_based_on, credit_days = get_credit_days(party_type, party, company)
		if credit_days_based_on == "Fixed Days" and credit_days:
			due_date = add_days(posting_date, credit_days)
		elif credit_days_based_on == "Last Day of the Next Month":
			due_date = (get_first_day(posting_date, 0, 2) + datetime.timedelta(-1)).strftime("%Y-%m-%d")

	return due_date
def make_new_document(ref_wrapper, date_field, posting_date):
	from erpnext.accounts.utils import get_fiscal_year
	new_document = frappe.copy_doc(ref_wrapper)
	mcount = month_map[ref_wrapper.recurring_type]

	from_date = get_next_date(ref_wrapper.from_date, mcount)

	# get last day of the month to maintain period if the from date is first day of its own month
	# and to date is the last day of its own month
	if (cstr(get_first_day(ref_wrapper.from_date)) == cstr(ref_wrapper.from_date)) and \
		(cstr(get_last_day(ref_wrapper.to_date)) == cstr(ref_wrapper.to_date)):
			to_date = get_last_day(get_next_date(ref_wrapper.to_date, mcount))
	else:
		to_date = get_next_date(ref_wrapper.to_date, mcount)
def make_new_document(reference_doc, date_field, posting_date):
	from erpnext.accounts.utils import get_fiscal_year
	new_document = frappe.copy_doc(reference_doc, ignore_no_copy=True)
	mcount = month_map[reference_doc.recurring_type]

	from_date = get_next_date(reference_doc.from_date, mcount)

	# get last day of the month to maintain period if the from date is first day of its own month
	# and to date is the last day of its own month
	if (cstr(get_first_day(reference_doc.from_date)) == cstr(reference_doc.from_date)) and \
		(cstr(get_last_day(reference_doc.to_date)) == cstr(reference_doc.to_date)):
			to_date = get_last_day(get_next_date(reference_doc.to_date, mcount))
	else:
		to_date = get_next_date(reference_doc.to_date, mcount)

	new_document.update({
		date_field: posting_date,
		"from_date": from_date,
		"to_date": to_date,
		"fiscal_year": get_fiscal_year(posting_date)[0],
        	"next_date": get_next_date(from_date, mcount,cint(reference_doc.repeat_on_day_of_month))
	})

	# copy document fields
	for fieldname in ("owner", "recurring_type", "repeat_on_day_of_month",
		"recurring_id", "notification_email_address", "is_recurring", "end_date",
		"title", "naming_series", "select_print_heading", "ignore_pricing_rule",
		"posting_time", "remarks", 'submit_on_creation'):
		if new_document.meta.get_field(fieldname):
			new_document.set(fieldname, reference_doc.get(fieldname))

	# copy item fields
	for i, item in enumerate(new_document.items):
		for fieldname in ("page_break",):
			item.set(fieldname, reference_doc.items[i].get(fieldname))

	new_document.run_method("on_recurring", reference_doc=reference_doc)

	if reference_doc.submit_on_creation:
		new_document.submit()
	else:
		new_document.docstatus=0
		new_document.insert()

	return new_document
示例#9
0
def create_salary_slips_for_payroll_period(employee, salary_structure, payroll_period, deduct_random=True):
	deducted_dates = []
	i = 0
	while i < 12:
		slip = frappe.get_doc({"doctype": "Salary Slip", "employee": employee,
				"salary_structure": salary_structure, "frequency": "Monthly"})
		if i == 0:
			posting_date = add_days(payroll_period.start_date, 25)
		else:
			posting_date = add_months(posting_date, 1)
		if i == 11:
			slip.deduct_tax_for_unsubmitted_tax_exemption_proof = 1
			slip.deduct_tax_for_unclaimed_employee_benefits = 1
		if deduct_random and not random.randint(0, 2):
			slip.deduct_tax_for_unsubmitted_tax_exemption_proof = 1
			deducted_dates.append(posting_date)
		slip.posting_date = posting_date
		slip.start_date = get_first_day(posting_date)
		slip.end_date = get_last_day(posting_date)
		doc = make_salary_slip(salary_structure, slip, employee)
		doc.submit()
		i += 1
	return deducted_dates
示例#10
0
def set_subscription_period(args, mcount, new_document):
	if mcount and new_document.meta.get_field('from_date') and new_document.meta.get_field('to_date'):
		last_ref_doc = frappe.db.sql("""
			select name, from_date, to_date
			from `tab{0}`
			where subscription=%s and docstatus < 2
			order by creation desc
			limit 1
		""".format(args.reference_doctype), args.name, as_dict=1)

		if not last_ref_doc:
			return

		from_date = get_next_date(last_ref_doc[0].from_date, mcount)

		if (cstr(get_first_day(last_ref_doc[0].from_date)) == cstr(last_ref_doc[0].from_date)) and \
			(cstr(get_last_day(last_ref_doc[0].to_date)) == cstr(last_ref_doc[0].to_date)):
				to_date = get_last_day(get_next_date(last_ref_doc[0].to_date, mcount))
		else:
			to_date = get_next_date(last_ref_doc[0].to_date, mcount)

		new_document.set('from_date', from_date)
		new_document.set('to_date', to_date)
示例#11
0
def get_total_pi(filters):

	filters = json.loads(filters)


	if(filters["period_type"]=="Month"):
		#convert from_date
		from_date = get_first_day(filters["period_num"] + '-' + filters["year"])
		filters["to_date"] =  get_last_day(filters["period_num"] + '-' + filters["year"])
		#frappe.msgprint(filters["from_date)
	
	if(filters["period_type"]=="Quarter"):
		#convert from_date
		period_num = "1"
		if(filters["period_num"]=="2"):
			period_num = "4"
		if(filters["period_num"]=="3"):
			period_num = "7"
		if(filters["period_num"]=="4"):
			period_num = "10"
			
		filters["from_date"] = get_first_day(period_num + '-' + filters["year"])
		filters["to_date"] = add_months(filters["from_date"], 3)
		filters["to_date"] = add_days(filters["to_date"], -1)
	
	#Purchase Invoice
	query = """ SELECT name, tax_rate FROM `tabAccount`
	WHERE `account_type`='Tax' 
	AND `freeze_account`='No' 
	AND `is_group` = 0 
	AND `name` LIKE '133%' 
	ORDER BY name """

	listAcount = frappe.db.sql(query, as_list=1)
	arrAcount = []
	arrTaxRate = []

	for i in range(0, len(listAcount)):
		arrAcount.append(listAcount[i][0])
		arrTaxRate.append(listAcount[i][1])
	
	conditions = get_conditions(filters)
	data = []
	total_pi = 0

	for i in range(0, len(arrAcount)):
		rate_name = arrAcount[i]
		tax_rate = arrTaxRate[i]

		query = """SELECT si_tax.account_head,
		sum(si.base_net_total), %d, sum(si_tax.base_tax_amount)
		FROM `tabPurchase Invoice` si, `tabPurchase Taxes and Charges` si_tax
		WHERE si.docstatus = 1 AND si_tax.parent = si.name AND si_tax.account_head = '%s'
		%s
		GROUP BY si_tax.account_head
		""" %(tax_rate, rate_name, conditions)

	
		row = frappe.db.sql(query, as_list=1)

		if (row):
			data.append(row[0])
			total_pi = total_pi + row[0][1]
		else:
			data.append([rate_name, 0, tax_rate, 0])
	
	#Sales Invoice
	query = """ SELECT name, tax_rate FROM `tabAccount`
	WHERE `account_type`='Tax' 
	AND `freeze_account`='No' 
	AND `is_group` = 0 
	AND `name` LIKE '3331%' 
	ORDER BY name """

	listAcount = frappe.db.sql(query, as_list=1)
	arrAcount = []
	arrTaxRate = []

	for i in range(0, len(listAcount)):
		arrAcount.append(listAcount[i][0])
		arrTaxRate.append(listAcount[i][1])

	for i in range(0, len(arrAcount)):
		rate_name = arrAcount[i]
		tax_rate = arrTaxRate[i]

		query = """SELECT si_tax.account_head,
		sum(si.base_net_total), %d, sum(si_tax.base_tax_amount)
		FROM `tabSales Invoice` si, `tabSales Taxes and Charges` si_tax
		WHERE si.docstatus = 1 AND si_tax.parent = si.name AND si_tax.account_head = '%s'
		%s
		GROUP BY si_tax.account_head
		""" %(tax_rate, rate_name, conditions)

	
		row = frappe.db.sql(query, as_list=1)

		if (row):
			data.append(row[0])
		else:
			data.append([rate_name, 0, tax_rate, 0])
	
	result = {
		'total_pi': total_pi,
		'total_tax_pi': data[2][3]+data[3][3],
		'data': data
	}
	return  result
示例#12
0
def get_period_list(from_fiscal_year, to_fiscal_year, periodicity):
    """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 xrange(months / months_to_add):
        period = frappe._dict({"from_date": start_date})

        to_date = add_months(start_date, months_to_add)
        start_date = to_date

        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 <= 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_date_fiscal_year(period.to_date)

        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":
            label = formatdate(opts["to_date"], "MMM YYYY")
        else:
            label = get_label(periodicity, opts["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_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
	def test_recurring_invoice(self):
		from frappe.utils import get_first_day, get_last_day, add_to_date, nowdate, getdate
		from erpnext.accounts.utils import get_fiscal_year
		today = nowdate()
		base_si = frappe.copy_doc(test_records[0])
		base_si.update({
			"convert_into_recurring_invoice": 1,
			"recurring_type": "Monthly",
			"notification_email_address": "[email protected], [email protected], [email protected]",
			"repeat_on_day_of_month": getdate(today).day,
			"posting_date": today,
			"fiscal_year": get_fiscal_year(today)[0],
			"invoice_period_from_date": get_first_day(today),
			"invoice_period_to_date": get_last_day(today)
		})

		# monthly
		si1 = frappe.copy_doc(base_si)
		si1.insert()
		si1.submit()
		self._test_recurring_invoice(si1, True)

		# monthly without a first and last day period
		si2 = frappe.copy_doc(base_si)
		si2.update({
			"invoice_period_from_date": today,
			"invoice_period_to_date": add_to_date(today, days=30)
		})
		si2.insert()
		si2.submit()
		self._test_recurring_invoice(si2, False)

		# quarterly
		si3 = frappe.copy_doc(base_si)
		si3.update({
			"recurring_type": "Quarterly",
			"invoice_period_from_date": get_first_day(today),
			"invoice_period_to_date": get_last_day(add_to_date(today, months=3))
		})
		si3.insert()
		si3.submit()
		self._test_recurring_invoice(si3, True)

		# quarterly without a first and last day period
		si4 = frappe.copy_doc(base_si)
		si4.update({
			"recurring_type": "Quarterly",
			"invoice_period_from_date": today,
			"invoice_period_to_date": add_to_date(today, months=3)
		})
		si4.insert()
		si4.submit()
		self._test_recurring_invoice(si4, False)

		# yearly
		si5 = frappe.copy_doc(base_si)
		si5.update({
			"recurring_type": "Yearly",
			"invoice_period_from_date": get_first_day(today),
			"invoice_period_to_date": get_last_day(add_to_date(today, years=1))
		})
		si5.insert()
		si5.submit()
		self._test_recurring_invoice(si5, True)

		# yearly without a first and last day period
		si6 = frappe.copy_doc(base_si)
		si6.update({
			"recurring_type": "Yearly",
			"invoice_period_from_date": today,
			"invoice_period_to_date": add_to_date(today, years=1)
		})
		si6.insert()
		si6.submit()
		self._test_recurring_invoice(si6, False)

		# change posting date but keep recuring day to be today
		si7 = frappe.copy_doc(base_si)
		si7.update({
			"posting_date": add_to_date(today, days=-1)
		})
		si7.insert()
		si7.submit()

		# setting so that _test function works
		si7.posting_date = today
		self._test_recurring_invoice(si7, True)
示例#15
0
def get_period_list(from_fiscal_year,
                    to_fiscal_year,
                    period_start_date,
                    period_end_date,
                    filter_based_on,
                    periodicity,
                    accumulated_values=False,
                    company=None,
                    reset_period_on_fy_change=True,
                    ignore_fiscal_year=False):
    """Get a list of dict {"from_date": from_date, "to_date": to_date, "key": key, "label": label}
		Periodicity can be (Yearly, Quarterly, Monthly)"""

    if filter_based_on == 'Fiscal Year':
        fiscal_year = get_fiscal_year_data(from_fiscal_year, to_fiscal_year)
        validate_fiscal_year(fiscal_year, from_fiscal_year, to_fiscal_year)
        year_start_date = getdate(fiscal_year.year_start_date)
        year_end_date = getdate(fiscal_year.year_end_date)
    else:
        validate_dates(period_start_date, period_end_date)
        year_start_date = getdate(period_start_date)
        year_end_date = getdate(period_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})

        if i == 0 and filter_based_on == 'Date Range':
            to_date = add_months(get_first_day(start_date), months_to_add)
        else:
            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

        if not ignore_fiscal_year:
            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_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
    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_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")
示例#19
0
    def test_recurring_invoice(self):
        from frappe.utils import get_first_day, get_last_day, add_to_date, nowdate, getdate
        from erpnext.accounts.utils import get_fiscal_year
        today = nowdate()
        base_si = frappe.bean(copy=test_records[0])
        base_si.doc.fields.update({
            "convert_into_recurring_invoice":
            1,
            "recurring_type":
            "Monthly",
            "notification_email_address":
            "[email protected], [email protected], [email protected]",
            "repeat_on_day_of_month":
            getdate(today).day,
            "posting_date":
            today,
            "fiscal_year":
            get_fiscal_year(today)[0],
            "invoice_period_from_date":
            get_first_day(today),
            "invoice_period_to_date":
            get_last_day(today)
        })

        # monthly
        si1 = frappe.bean(copy=base_si.doclist)
        si1.insert()
        si1.submit()
        self._test_recurring_invoice(si1, True)

        # monthly without a first and last day period
        si2 = frappe.bean(copy=base_si.doclist)
        si2.doc.fields.update({
            "invoice_period_from_date":
            today,
            "invoice_period_to_date":
            add_to_date(today, days=30)
        })
        si2.insert()
        si2.submit()
        self._test_recurring_invoice(si2, False)

        # quarterly
        si3 = frappe.bean(copy=base_si.doclist)
        si3.doc.fields.update({
            "recurring_type":
            "Quarterly",
            "invoice_period_from_date":
            get_first_day(today),
            "invoice_period_to_date":
            get_last_day(add_to_date(today, months=3))
        })
        si3.insert()
        si3.submit()
        self._test_recurring_invoice(si3, True)

        # quarterly without a first and last day period
        si4 = frappe.bean(copy=base_si.doclist)
        si4.doc.fields.update({
            "recurring_type":
            "Quarterly",
            "invoice_period_from_date":
            today,
            "invoice_period_to_date":
            add_to_date(today, months=3)
        })
        si4.insert()
        si4.submit()
        self._test_recurring_invoice(si4, False)

        # yearly
        si5 = frappe.bean(copy=base_si.doclist)
        si5.doc.fields.update({
            "recurring_type":
            "Yearly",
            "invoice_period_from_date":
            get_first_day(today),
            "invoice_period_to_date":
            get_last_day(add_to_date(today, years=1))
        })
        si5.insert()
        si5.submit()
        self._test_recurring_invoice(si5, True)

        # yearly without a first and last day period
        si6 = frappe.bean(copy=base_si.doclist)
        si6.doc.fields.update({
            "recurring_type":
            "Yearly",
            "invoice_period_from_date":
            today,
            "invoice_period_to_date":
            add_to_date(today, years=1)
        })
        si6.insert()
        si6.submit()
        self._test_recurring_invoice(si6, False)

        # change posting date but keep recuring day to be today
        si7 = frappe.bean(copy=base_si.doclist)
        si7.doc.fields.update({"posting_date": add_to_date(today, days=-1)})
        si7.insert()
        si7.submit()

        # setting so that _test function works
        si7.doc.posting_date = today
        self._test_recurring_invoice(si7, True)
def get_period_list(fiscal_year, periodicity):
	"""Get a list of dict {"from_date": from_date, "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 with first day, so as to avoid year to_dates like 2-April if ever they occur]
	year_start_date = get_first_day(getdate(fy_start_end_date[0]))
	year_end_date = getdate(fy_start_end_date[1])
	
	if periodicity == "Yearly":
		period_list = [frappe._dict({"from_date": year_start_date, "to_date": year_end_date, 
			"key": fiscal_year, "label": fiscal_year})]
	else:
		months_to_add = {
			"Half-Yearly": 6,
			"Quarterly": 3,
			"Monthly": 1
		}[periodicity]

		period_list = []

		start_date = year_start_date
		for i in xrange(12 / months_to_add):
			period = frappe._dict({
				"from_date": start_date
			})
			to_date = add_months(start_date, months_to_add)
			start_date = to_date
			
			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 <= 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_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":
			label = formatdate(opts["to_date"], "MMM YYYY")
		else:
			label = get_label(periodicity, opts["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_period_list(fiscal_year, periodicity):
	"""Get a list of dict {"from_date": from_date, "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 with first day, so as to avoid year to_dates like 2-April if ever they occur]
	year_start_date = get_first_day(getdate(fy_start_end_date[0]))
	year_end_date = getdate(fy_start_end_date[1])

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

		period_list = []

		start_date = year_start_date
		for i in xrange(12 / months_to_add):
			period = frappe._dict({
				"from_date": start_date
			})
			to_date = add_months(start_date, months_to_add)
			start_date = to_date

			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 <= 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_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":
			label = formatdate(opts["to_date"], "MMM YYYY")
		else:
			label = get_label(periodicity, opts["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
示例#22
0
def test_recurring_document(obj, test_records):
	from frappe.utils import get_first_day, get_last_day, add_to_date, nowdate, getdate, add_days
	from erpnext.accounts.utils import get_fiscal_year
	frappe.db.set_value("Print Settings", "Print Settings", "send_print_as_pdf", 1)
	today = nowdate()
	base_doc = frappe.copy_doc(test_records[0])

	base_doc.update({
		"is_recurring": 1,
		"recurring_type": "Monthly",
		"notification_email_address": "[email protected], [email protected], [email protected]",
		"repeat_on_day_of_month": getdate(today).day,
		"due_date": None,
		"fiscal_year": get_fiscal_year(today)[0],
		"from_date": get_first_day(today),
		"to_date": get_last_day(today)
	})

	if base_doc.doctype == "Sales Order":
		base_doc.update({
			"transaction_date": today,
			"delivery_date": add_days(today, 15)
		})
	elif base_doc.doctype == "Sales Invoice":
		base_doc.update({
			"posting_date": today
		})

	if base_doc.doctype == "Sales Order":
		date_field = "transaction_date"
	elif base_doc.doctype == "Sales Invoice":
		date_field = "posting_date"

	# monthly
	doc1 = frappe.copy_doc(base_doc)
	doc1.insert()
	doc1.submit()
	_test_recurring_document(obj, doc1, date_field, True)

	# monthly without a first and last day period
	doc2 = frappe.copy_doc(base_doc)
	doc2.update({
		"from_date": today,
		"to_date": add_to_date(today, days=30)
	})
	doc2.insert()
	doc2.submit()
	_test_recurring_document(obj, doc2, date_field, False)

	# quarterly
	doc3 = frappe.copy_doc(base_doc)
	doc3.update({
		"recurring_type": "Quarterly",
		"from_date": get_first_day(today),
		"to_date": get_last_day(add_to_date(today, months=3))
	})
	doc3.insert()
	doc3.submit()
	_test_recurring_document(obj, doc3, date_field, True)

	# quarterly without a first and last day period
	doc4 = frappe.copy_doc(base_doc)
	doc4.update({
		"recurring_type": "Quarterly",
		"from_date": today,
		"to_date": add_to_date(today, months=3)
	})
	doc4.insert()
	doc4.submit()
	_test_recurring_document(obj, doc4, date_field, False)

	# yearly
	doc5 = frappe.copy_doc(base_doc)
	doc5.update({
		"recurring_type": "Yearly",
		"from_date": get_first_day(today),
		"to_date": get_last_day(add_to_date(today, years=1))
	})
	doc5.insert()
	doc5.submit()
	_test_recurring_document(obj, doc5, date_field, True)

	# yearly without a first and last day period
	doc6 = frappe.copy_doc(base_doc)
	doc6.update({
		"recurring_type": "Yearly",
		"from_date": today,
		"to_date": add_to_date(today, years=1)
	})
	doc6.insert()
	doc6.submit()
	_test_recurring_document(obj, doc6, date_field, False)

	# change date field but keep recurring day to be today
	doc7 = frappe.copy_doc(base_doc)
	doc7.update({
		date_field: today,
	})
	doc7.insert()
	doc7.submit()

	# setting so that _test function works
	# doc7.set(date_field, today)
	_test_recurring_document(obj, doc7, date_field, True)
示例#23
0
def add_late_entry_deduction(debug=False):
    from hr_policies.custom_validate import preview_salary_slip_for_late_entry
    end_date = add_days(today(), -1)
    start_date = get_first_day(end_date)
    late_entry_doc = frappe.db.sql(
        """select employee,sum(hours) as 'hours' from
		`tabAttendance Extra Entry` where calculated = 0 and ignore_penalty = 0 and
		YEAR(date) = YEAR(CURRENT_DATE - INTERVAL 1 MONTH) AND MONTH(date) = MONTH(CURRENT_DATE - INTERVAL 1 MONTH)
		group by employee;""",
        as_dict=1)

    extra_entry = frappe.db.sql("""select name from
                `tabAttendance Extra Entry` where calculated = 0 and
                YEAR(date) = YEAR(CURRENT_DATE - INTERVAL 1 MONTH) AND MONTH(date) = MONTH(CURRENT_DATE - INTERVAL 1 MONTH);""",
                                as_dict=1)

    for row in late_entry_doc:
        if row.employee == emp:
            frappe.errprint("Iterating")
        try:
            hours = frappe.db.sql(
                """select office_hours from `tabAttendance` where docstatus = 1 and 
			employee = %s order by creation desc limit 1;""", (row.employee))
            salary_slip = preview_salary_slip_for_late_entry(row.employee)
            if row.employee == emp:
                frappe.errprint("Employee " + row.employee)
                frappe.errprint("Salary Slip Gropay")
                frappe.errprint(salary_slip.gross_pay)
            day_rate = salary_slip.gross_pay / 30  #salary_slip.total_working_days
            hourly_rate = 0
            if row.employee == emp:
                print(row.employee)
                print(salary_slip.gross_pay)
                print(salary_slip.total_working_days)
                print(abs(hours[0][0]))
            if not abs(hours[0][0]) == False and abs(hours[0][0]) > 0:
                hourly_rate = flt(day_rate) / flt(
                    abs(hours[0][0])
                )  # office hours 10, hourly rate should be 57.66, so day rate 576.6
                amount = hourly_rate * row.hours  # 865 row hours 15

                add_deduction_for_late_entry(row.employee, end_date, amount)
                if row.employee == emp:
                    frappe.errprint("Creating Late Entry")
                    frappe.errprint(row.employee)
                    frappe.errprint(end_date)
                    frappe.errprint(amount)
                    frappe.errprint(hourly_rate)
                    frappe.errprint(row.hours)
            else:
                frappe.throw(
                    _("Employee {0} Shift Not Define").format(row.employee))
        except Exception as e:
            frappe.errprint(str(e))
            frappe.log_error(frappe.get_traceback())
    frappe.errprint("Iteration Complete")
    frappe.db.commit()
    for id in extra_entry:
        if id.name:
            frappe.db.set_value("Attendance Extra Entry", id.name,
                                "calculated", True)
    frappe.db.commit()
示例#24
0
def calcute_latein_earlyout():
    cur_date = today()
    pre_mnth = add_months(cur_date, -1)
    first_day = get_first_day(pre_mnth)
    last_day = get_last_day(pre_mnth)
    employees = frappe.get_list("Employee", {'status': "Active"},
                                ['name', 'holiday_list'])
    for emp in employees:
        disciplinary_measure = ""
        late_in_count = 0
        early_out_count = 0
        monthly_occ_count = 0
        late_in_count_for_3month = 0
        early_out_count_for_3month = 0
        occ_count_for_3month = 0
        total_late_in_deduction_hours = 0
        total_early_out_deduction_hours = 0.0
        total_deduction_hours = 0.0
        total_deduction_amount = 0
        cum_late_in = "00:00:0"
        cum_late_in = cum_late_in.split(":")
        cum_late_in = timedelta(hours=cint(cum_late_in[0]),
                                minutes=cint(cum_late_in[1])).total_seconds()
        cum_early_out = "00:00:0"
        cum_early_out = cum_early_out.split(":")
        cum_early_out = timedelta(hours=cint(cum_early_out[0]),
                                  minutes=cint(
                                      cum_early_out[1])).total_seconds()
        late_in_list = frappe.db.sql(
            """select late_in,deduction_hours from `tabLate IN Register`
            where employee = %s and is_approved != 1 and attendance_date between %s and %s  """,
            (emp.name, first_day, last_day),
            as_dict=True)
        if late_in_list:
            for l in late_in_list:
                late_in = l.late_in
                late_in = late_in.split(":")
                late_in = timedelta(hours=cint(late_in[0]),
                                    minutes=cint(late_in[1])).total_seconds()
                cum_late_in += late_in
                late_in_count += 1
                # print l.deduction_hours
                total_late_in_deduction_hours += l.deduction_hours
        early_out_list = frappe.db.sql(
            """select early_out,deduction_hours from `tabEarly OUT Register`
            where employee = %s and is_approved != 1 and attendance_date between %s and %s  """,
            (emp.name, first_day, last_day),
            as_dict=True)
        if early_out_list:
            for e in early_out_list:
                early_out = e.early_out
                early_out = early_out.split(":")
                early_out = timedelta(hours=cint(early_out[0]),
                                      minutes=cint(
                                          early_out[1])).total_seconds()
                cum_early_out += early_out
                early_out_count += 1
                total_early_out_deduction_hours += e.deduction_hours
        monthly_occ_count = late_in_count + early_out_count
        bs = frappe.get_single("Biometry Settings")
        if monthly_occ_count >= int(bs.lateness_count_for_a_month):
            disciplinary_measure = "Probation for 60 Days"
        before_3month_first_day = add_days(first_day, -90)
        late_in_list_for_3month = frappe.db.sql(
            """select late_in from `tabLate IN Register`
            where employee = %s and attendance_date between %s and %s  """,
            (emp.name, before_3month_first_day, last_day),
            as_dict=True)
        if late_in_list_for_3month:
            for l in late_in_list_for_3month:
                late_in_count_for_3month += 1
        early_out_list_for_3month = frappe.db.sql(
            """select early_out from `tabEarly OUT Register`
            where employee = %s and attendance_date between %s and %s  """,
            (emp.name, before_3month_first_day, last_day),
            as_dict=True)
        if early_out_list_for_3month:
            for l in early_out_list_for_3month:
                early_out_count_for_3month += 1
        occ_count_for_3month = late_in_count_for_3month + early_out_count_for_3month
        if occ_count_for_3month >= int(bs.lateness_count_for_90_days):
            disciplinary_measure = "Termination"
        ssa = frappe.db.get_value("Salary Structure Assignment",
                                  {"employee": emp.name}, "salary_structure")
        if ssa:
            holiday_count = 0
            pay_per_hour = ""
            if emp.holiday_list:
                holiday_list = frappe.get_doc("Holiday List",
                                              {"name": emp.holiday_list})
                if holiday_list:
                    for h in holiday_list.holidays:
                        if h.holiday_date >= first_day and h.holiday_date <= last_day:
                            holiday_count += 1
            actual_days_count = date_diff(last_day, first_day) + 1
            pay_days = actual_days_count - holiday_count
            salary_structure = frappe.get_doc("Salary Structure", ssa)
            pay_per_hour = round(salary_structure.net_pay / pay_days / 9.5, 2)
        if cum_late_in or cum_early_out:
            total_deduction_hours = total_late_in_deduction_hours + total_early_out_deduction_hours
            total_deduction_amount = total_deduction_hours * pay_per_hour
        emp_details = frappe.get_doc("Employee", emp.name)
        emp_details.update({
            "current_month_late_in_count":
            late_in_count,
            "late_in_hours":
            round(cum_late_in / 3600, 1),
            "current_month_early_out_count":
            early_out_count,
            "early_out_hours":
            round(cum_early_out / 3600, 1),
            "disciplinary_measure":
            disciplinary_measure,
            "net_pay_per_hour":
            pay_per_hour,
            "total_deduction_amount":
            total_deduction_amount,
            "late_in_deduction_hours":
            total_late_in_deduction_hours,
            "early_out_deduction_hours":
            total_early_out_deduction_hours
        })
        emp_details.save(ignore_permissions=True)
        frappe.db.commit()
示例#25
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 = from_fiscal_year.date()
    fmt = "%Y-%m-%d"
    year_start_date = datetime.strptime(from_fiscal_year, fmt).date()
    year_end_date = datetime.strptime(to_fiscal_year, fmt).date()
    # year_end_date = to_fiscal_year.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(months // months_to_add):
        period = frappe._dict({"from_date": start_date})

        to_date = add_months(start_date, months_to_add)
        start_date = to_date

        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)

        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_report_content(company, customer_name, from_date=None, to_date=None):
    '''Returns html for the report in PDF format'''

    settings_doc = frappe.get_single('Customer Statements Sender')

    if not from_date:
        from_date = get_first_day(today()).strftime("%Y-%m-%d")
    if not to_date:
        to_date = today()

    # Get General Ledger report content
    report_gl = frappe.get_doc('Report', 'General Ledger')
    report_gl_filters = {
        'company': company,
        'party_type': 'Customer',
        'party': [customer_name],
        'from_date': from_date,
        'to_date': to_date,
        'group_by': 'Group by Voucher (Consolidated)'
    }

    columns_gl, data_gl = report_gl.get_data(limit=500,
                                             user="******",
                                             filters=report_gl_filters,
                                             as_dict=True)

    # Add serial numbers
    columns_gl.insert(0, frappe._dict(fieldname='idx', label='', width='30px'))
    for i in range(len(data_gl)):
        data_gl[i]['idx'] = i + 1

    # Get ageing summary report content
    data_ageing = []
    labels_ageing = []
    if settings_doc.no_ageing != 1:
        report_ageing = frappe.get_doc('Report', 'Accounts Receivable Summary')
        report_ageing_filters = {
            'company': company,
            'ageing_based_on': 'Posting Date',
            'report_date': datetime.datetime.today(),
            'range1': 30,
            'range2': 60,
            'range3': 90,
            'range4': 120,
            'customer': customer_name
        }
        columns_ageing, data_ageing = report_ageing.get_data(
            limit=50,
            user="******",
            filters=report_ageing_filters,
            as_dict=True)
        labels_ageing = {}
        for col in columns_ageing:
            if 'range' in col['fieldname']:
                labels_ageing[col['fieldname']] = col['label']

    # Get Letter Head
    no_letterhead = bool(
        frappe.db.get_single_value('Customer Statements Sender',
                                   'no_letter_head'))
    letter_head = frappe._dict(
        printview.get_letter_head(settings_doc, no_letterhead) or {})
    if letter_head.content:
        letter_head.content = frappe.utils.jinja.render_template(
            letter_head.content, {"doc": settings_doc.as_dict()})

    # Render Template
    date_time = global_date_format(now()) + ' ' + format_time(now())
    currency = frappe.db.get_value('Company', company, 'default_currency')
    report_html_data = frappe.render_template(
        'erpnext_customer_statements_sender/templates/report/customer_statement_jinja.html',
        {
            'title': 'Customer Statement for {0}'.format(customer_name),
            'description': 'Customer Statement for {0}'.format(customer_name),
            'date_time': date_time,
            'columns': columns_gl,
            'data': data_gl,
            'report_name': 'Customer Statement for {0}'.format(customer_name),
            'filters': report_gl_filters,
            'currency': currency,
            'letter_head': letter_head.content,
            'billing_address': get_billing_address(customer_name),
            'labels_ageing': labels_ageing,
            'data_ageing': data_ageing
        })

    return report_html_data
示例#27
0
	def validate_cross_sale_limit(self):
		indent_amount = {}
		errors = []

		default_aggr_dict = {'amt': 0, 'qty_in_kg': 0}

		for indent_item in self.indent:
			if indent_item.cross_sold:
				indent_amount.setdefault(indent_item.customer, default_aggr_dict.copy())
				indent_amount[indent_item.customer]['amt'] += indent_item.amount
				indent_amount[indent_item.customer]['qty_in_kg'] += float(indent_item.item.replace('FC', '').replace('L', '')) * indent_item.qty

		month_end = get_last_day(self.posting_date)
		month_start = get_first_day(self.posting_date)

		for customer in indent_amount.keys():
			invoice_sum_value = frappe.db.sql("""
			select ifnull(sum(inv.actual_amount), 0) + ifnull(sum(sal.grand_total_export), 0)
			from `tabIndent Invoice` inv
			LEFT JOIN `tabSales Invoice` sal
			on inv.transportation_invoice = sal.name
			where inv.customer = "{customer}"
			and inv.docstatus = 1
			and inv.cross_sold = 1
			and inv.transaction_date between "{month_start}" and "{month_end}"
			""".format(customer=customer, month_end=month_end, month_start=month_start))[0][0]

			indent_sum = frappe.db.sql("""
			select ifnull(sum(replace(replace(itm.item, 'FC' ,''), 'L', '')*itm.qty), 0) as qty,
			ifnull(sum(itm.amount), 0) as amount
			from `tabIndent Item` itm left join `tabIndent` ind
			on itm.parent = ind.name
			where itm.name not in (
				select ifnull(indent_item, '')
				from `tabIndent Invoice`
				where docstatus = 1
			)
			and itm.parent != "{self_indent}"
			and itm.docstatus != 2
			and itm.customer = "{customer}"
			and itm.cross_sold = 1
			and ind.posting_date  between "{month_start}" and "{month_end}"
			""".format(customer=customer, month_end=month_end, month_start=month_start, self_indent=self.name), as_dict=True)[0]

			sales_rate = frappe.db.sql(
				"""
				SELECT applicable_transport_rate
				FROM `tabCustomer Sale`
				WHERE customer="{customer}"
				AND with_effect_from <= "{invoice_date}"
				AND ifnull(valid_up_to, "{invoice_date}") <= "{invoice_date}"
				AND docstatus = 1
				ORDER BY with_effect_from DESC LIMIT 1
				""".format(invoice_date=today(), customer=customer)
			)

			sales_rate = sales_rate[0][0] if sales_rate else 0

			limit = frappe.db.get_value("Customer", {'name': customer}, 'cross_sale_limit')
			limit = limit if limit else 0

			available_limit = limit - invoice_sum_value - indent_sum.amount - (float(indent_sum.qty) * float(sales_rate))

			cur_dict = indent_amount.get(customer, default_aggr_dict)
			diff = round(available_limit - cur_dict['amt'] - cur_dict['qty_in_kg'] * sales_rate, 2)

			if diff < 0:
				errors.append(
					"Cross sold limit exceeded for customer `{}` by {}. Get it increased or place indent for other customer"
						.format(customer, abs(diff))
				)

		if errors:
			errors.insert(0, 'Did not save')
			frappe.throw('\n'.join(errors))
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 xrange(months / months_to_add):
		period = frappe._dict({
			"from_date": start_date
		})

		to_date = add_months(start_date, months_to_add)
		start_date = to_date

		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)

		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
示例#29
0
def test_recurring_document(obj, test_records):
    frappe.db.set_value("Print Settings", "Print Settings",
                        "send_print_as_pdf", 1)
    today = nowdate()
    base_doc = frappe.copy_doc(test_records[0])

    base_doc.update({
        "is_recurring": 1,
        "submit_on_create": 1,
        "recurring_type": "Monthly",
        "notification_email_address":
        "[email protected], [email protected], [email protected]",
        "repeat_on_day_of_month": getdate(today).day,
        "due_date": None,
        "from_date": get_first_day(today),
        "to_date": get_last_day(today)
    })

    date_field = date_field_map[base_doc.doctype]
    base_doc.set(date_field, today)

    if base_doc.doctype == "Sales Order":
        base_doc.set("delivery_date", add_days(today, 15))

    # monthly
    doc1 = frappe.copy_doc(base_doc)
    doc1.insert()
    doc1.submit()
    _test_recurring_document(obj, doc1, date_field, True)

    # monthly without a first and last day period
    if getdate(today).day != 1:
        doc2 = frappe.copy_doc(base_doc)
        doc2.update({
            "from_date": today,
            "to_date": add_to_date(today, days=30)
        })
        doc2.insert()
        doc2.submit()
        _test_recurring_document(obj, doc2, date_field, False)

    # quarterly
    doc3 = frappe.copy_doc(base_doc)
    doc3.update({
        "recurring_type": "Quarterly",
        "from_date": get_first_day(today),
        "to_date": get_last_day(add_to_date(today, months=3))
    })
    doc3.insert()
    doc3.submit()
    _test_recurring_document(obj, doc3, date_field, True)

    # quarterly without a first and last day period
    doc4 = frappe.copy_doc(base_doc)
    doc4.update({
        "recurring_type": "Quarterly",
        "from_date": today,
        "to_date": add_to_date(today, months=3)
    })
    doc4.insert()
    doc4.submit()
    _test_recurring_document(obj, doc4, date_field, False)

    # yearly
    doc5 = frappe.copy_doc(base_doc)
    doc5.update({
        "recurring_type": "Yearly",
        "from_date": get_first_day(today),
        "to_date": get_last_day(add_to_date(today, years=1))
    })
    doc5.insert()
    doc5.submit()
    _test_recurring_document(obj, doc5, date_field, True)

    # yearly without a first and last day period
    doc6 = frappe.copy_doc(base_doc)
    doc6.update({
        "recurring_type": "Yearly",
        "from_date": today,
        "to_date": add_to_date(today, years=1)
    })
    doc6.insert()
    doc6.submit()
    _test_recurring_document(obj, doc6, date_field, False)

    # change date field but keep recurring day to be today
    doc7 = frappe.copy_doc(base_doc)
    doc7.update({
        date_field: today,
    })
    doc7.insert()
    doc7.submit()

    # setting so that _test function works
    # doc7.set(date_field, today)
    _test_recurring_document(obj, doc7, date_field, True)