def calculate_next_due_date(periodicity, start_date=None, end_date=None, last_completion_date=None, next_due_date=None): if not start_date and not last_completion_date: start_date = dataent.utils.now() if last_completion_date and (last_completion_date > start_date or not start_date): start_date = last_completion_date if periodicity == 'Daily': next_due_date = add_days(start_date, 1) if periodicity == 'Weekly': next_due_date = add_days(start_date, 7) if periodicity == 'Monthly': next_due_date = add_months(start_date, 1) if periodicity == 'Yearly': next_due_date = add_years(start_date, 1) if periodicity == '2 Yearly': next_due_date = add_years(start_date, 2) if periodicity == 'Quarterly': next_due_date = add_months(start_date, 3) if end_date and (start_date >= end_date or last_completion_date >= end_date or next_due_date): next_due_date = "" return next_due_date
def test_leave_grant(self): leave_type = "_Test Leave Type" # create the leave policy leave_policy = dataent.get_doc({ "doctype": "Leave Policy", "leave_policy_details": [{ "leave_type": leave_type, "annual_allocation": 20 }] }).insert() leave_policy.submit() # create employee and assign the leave period employee = "*****@*****.**" employee_doc_name = make_employee(employee) dataent.db.set_value("Employee", employee_doc_name, "leave_policy", leave_policy.name) # clear the already allocated leave dataent.db.sql( '''delete from `tabLeave Allocation` where employee=%s''', "*****@*****.**") # create the leave period leave_period = create_leave_period(add_months(today(), -3), add_months(today(), 3)) # test leave_allocation leave_period.grant_leave_allocation(employee=employee_doc_name) self.assertEqual( get_leave_balance_on(employee_doc_name, leave_type, today()), 20)
def create_salary_slips_for_payroll_period(employee, salary_structure, payroll_period, deduct_random=True): deducted_dates = [] i = 0 while i < 12: slip = dataent.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
def calculate_service_end_date(args, item=None): args = process_args(args) if not item: item = dataent.get_cached_doc("Item", args.item_code) doctype = args.get("parenttype") or args.get("doctype") if doctype == "Sales Invoice": enable_deferred = "enable_deferred_revenue" no_of_months = "no_of_months" account = "deferred_revenue_account" else: enable_deferred = "enable_deferred_expense" no_of_months = "no_of_months_exp" account = "deferred_expense_account" service_start_date = args.service_start_date if args.service_start_date else args.transaction_date service_end_date = add_months(service_start_date, item.get(no_of_months)) deferred_detail = { "service_start_date": service_start_date, "service_end_date": service_end_date } deferred_detail[enable_deferred] = item.get(enable_deferred) deferred_detail[account] = get_default_deferred_account(args, item, fieldname=account) return deferred_detail
def make_repayment_schedule(self): self.repayment_schedule = [] payment_date = self.repayment_start_date balance_amount = self.loan_amount while (balance_amount > 0): interest_amount = rounded(balance_amount * flt(self.rate_of_interest) / (12 * 100)) principal_amount = self.monthly_repayment_amount - interest_amount balance_amount = rounded(balance_amount + interest_amount - self.monthly_repayment_amount) if balance_amount < 0: principal_amount += balance_amount balance_amount = 0.0 total_payment = principal_amount + interest_amount self.append( "repayment_schedule", { "payment_date": payment_date, "principal_amount": principal_amount, "interest_amount": interest_amount, "total_payment": total_payment, "balance_loan_amount": balance_amount }) next_payment_date = add_months(payment_date, 1) payment_date = next_payment_date
def test_make_sales_order(self): from epaas.selling.doctype.quotation.quotation import make_sales_order quotation = dataent.copy_doc(test_records[0]) quotation.transaction_date = nowdate() quotation.valid_till = add_months(quotation.transaction_date, 1) quotation.insert() self.assertRaises(dataent.ValidationError, make_sales_order, quotation.name) quotation.submit() sales_order = make_sales_order(quotation.name) self.assertEqual(sales_order.doctype, "Sales Order") self.assertEqual(len(sales_order.get("items")), 1) self.assertEqual( sales_order.get("items")[0].doctype, "Sales Order Item") self.assertEqual( sales_order.get("items")[0].prevdoc_docname, quotation.name) self.assertEqual(sales_order.customer, "_Test Customer") sales_order.delivery_date = "2014-01-01" sales_order.naming_series = "_T-Quotation-" sales_order.transaction_date = nowdate() sales_order.insert()
def create_quotation(self): quotation = dataent.new_doc("Quotation") values = { "doctype": "Quotation", "quotation_to": "Customer", "order_type": "Shopping Cart", "party_name": get_party(dataent.session.user).name, "docstatus": 0, "contact_email": dataent.session.user, "selling_price_list": "_Test Price List Rest of the World", "currency": "USD", "taxes_and_charges" : "_Test Tax 1 - _TC", "conversion_rate":1, "transaction_date" : nowdate(), "valid_till" : add_months(nowdate(), 1), "items": [{ "item_code": "_Test Item", "qty": 1 }], "taxes": dataent.get_doc("Sales Taxes and Charges Template", "_Test Tax 1 - _TC").taxes, "company": "_Test Company" } quotation.update(values) quotation.insert(ignore_permissions=True) return quotation
def sync_transactions(bank, bank_account): last_sync_date = dataent.db.get_value("Bank Account", bank_account, "last_integration_date") if last_sync_date: start_date = formatdate(last_sync_date, "YYYY-MM-dd") else: start_date = formatdate(add_months(today(), -12), "YYYY-MM-dd") end_date = formatdate(today(), "YYYY-MM-dd") try: transactions = get_transactions(bank=bank, bank_account=bank_account, start_date=start_date, end_date=end_date) result = [] if transactions: for transaction in transactions: result.append(new_bank_transaction(transaction)) dataent.db.set_value("Bank Account", bank_account, "last_integration_date", getdate(end_date)) return result except Exception: dataent.log_error(dataent.get_traceback(), _("Plaid transactions sync error"))
def test_result_for_partial_material_request(self): so = make_sales_order() mr=make_material_request(so.name) mr.items[0].qty = 4 mr.schedule_date = add_months(nowdate(),1) mr.submit() report = execute() l = len(report[1]) self.assertEqual((so.items[0].qty - mr.items[0].qty), report[1][l-1]['pending_qty'])
def create_benefit_claim(employee, payroll_period, amount, component): claim_date = add_months(payroll_period.start_date, random.randint(0, 11)) dataent.get_doc({ "doctype": "Employee Benefit Claim", "employee": employee, "claimed_amount": amount, "claim_date": claim_date, "earning_component": component }).submit() return claim_date
def test_monthly_auto_repeat(self): start_date = today() end_date = add_months(start_date, 12) todo = dataent.get_doc( dict(doctype='ToDo', description='test recurring todo', assigned_by='Administrator')).insert() self.monthly_auto_repeat('ToDo', todo.name, start_date, end_date)
def create_additional_salary(employee, payroll_period, amount): salary_date = add_months(payroll_period.start_date, random.randint(0, 11)) dataent.get_doc({ "doctype": "Additional Salary", "employee": employee, "company": epaas.get_default_company(), "salary_component": "Performance Bonus", "payroll_date": salary_date, "amount": amount, "type": "Earning" }).submit() return salary_date
def test_make_sales_order_terms_copied(self): from epaas.selling.doctype.quotation.quotation import make_sales_order quotation = dataent.copy_doc(test_records[0]) quotation.transaction_date = nowdate() quotation.valid_till = add_months(quotation.transaction_date, 1) quotation.insert() quotation.submit() sales_order = make_sales_order(quotation.name) self.assertTrue(sales_order.get('payment_schedule'))
def create_salary_structure_assignment(employee, salary_structure, from_date=None): if dataent.db.exists("Salary Structure Assignment", {"employee": employee}): dataent.db.sql("""delete from `tabSalary Structure Assignment` where employee=%s""",(employee)) salary_structure_assignment = dataent.new_doc("Salary Structure Assignment") salary_structure_assignment.employee = employee salary_structure_assignment.base = 50000 salary_structure_assignment.variable = 5000 salary_structure_assignment.from_date = from_date or add_months(nowdate(), -1) salary_structure_assignment.salary_structure = salary_structure salary_structure_assignment.company = epaas.get_default_company() salary_structure_assignment.save(ignore_permissions=True) salary_structure_assignment.submit() return salary_structure_assignment
def test_leave_balance_value_and_amount(self): employee = "*****@*****.**" leave_type = "_Test Leave Type Encashment" # create the leave policy leave_policy = dataent.get_doc({ "doctype": "Leave Policy", "leave_policy_details": [{ "leave_type": leave_type, "annual_allocation": 10 }] }).insert() leave_policy.submit() # create employee, salary structure and assignment employee = make_employee(employee) dataent.db.set_value("Employee", employee, "leave_policy", leave_policy.name) salary_structure = make_salary_structure("Salary Structure for Encashment", "Monthly", employee, other_details={"leave_encashment_amount_per_day": 50}) # create the leave period and assign the leaves leave_period = create_leave_period(add_months(today(), -3), add_months(today(), 3)) leave_period.grant_leave_allocation(employee=employee) leave_encashment = dataent.get_doc(dict( doctype = 'Leave Encashment', employee = employee, leave_type = leave_type, leave_period = leave_period.name, payroll_date = today() )).insert() self.assertEqual(leave_encashment.leave_balance, 10) self.assertEqual(leave_encashment.encashable_days, 5) self.assertEqual(leave_encashment.encashment_amount, 250) leave_encashment.submit() self.assertTrue(dataent.db.get_value("Leave Encashment", leave_encashment.name, "additional_salary"))
def convert_deferred_revenue_to_income(start_date=None, end_date=None): # book the expense/income on the last day, but it will be trigger on the 1st of month at 12:00 AM if not start_date: start_date = add_months(today(), -1) if not end_date: end_date = add_days(today(), -1) # check for the sales invoice for which GL entries has to be done invoices = dataent.db.sql_list(''' select distinct parent from `tabSales Invoice Item` where service_start_date<=%s and service_end_date>=%s and enable_deferred_revenue = 1 and docstatus = 1 and ifnull(amount, 0) > 0 ''', (end_date, start_date)) for invoice in invoices: doc = dataent.get_doc("Sales Invoice", invoice) book_deferred_income_or_expense(doc, end_date)
def test_make_sales_order_with_terms(self): from epaas.selling.doctype.quotation.quotation import make_sales_order quotation = dataent.copy_doc(test_records[0]) quotation.transaction_date = nowdate() quotation.valid_till = add_months(quotation.transaction_date, 1) quotation.update( {"payment_terms_template": "_Test Payment Term Template"}) quotation.insert() self.assertRaises(dataent.ValidationError, make_sales_order, quotation.name) quotation.save() quotation.submit() self.assertEqual(quotation.payment_schedule[0].payment_amount, 8906.00) self.assertEqual(quotation.payment_schedule[0].due_date, quotation.transaction_date) self.assertEqual(quotation.payment_schedule[1].payment_amount, 8906.00) self.assertEqual(quotation.payment_schedule[1].due_date, add_days(quotation.transaction_date, 30)) sales_order = make_sales_order(quotation.name) self.assertEqual(sales_order.doctype, "Sales Order") self.assertEqual(len(sales_order.get("items")), 1) self.assertEqual( sales_order.get("items")[0].doctype, "Sales Order Item") self.assertEqual( sales_order.get("items")[0].prevdoc_docname, quotation.name) self.assertEqual(sales_order.customer, "_Test Customer") sales_order.delivery_date = "2014-01-01" sales_order.naming_series = "_T-Quotation-" sales_order.transaction_date = nowdate() sales_order.insert() self.assertEqual(sales_order.payment_schedule[0].payment_amount, 8906.00) self.assertEqual(sales_order.payment_schedule[0].due_date, getdate(quotation.transaction_date)) self.assertEqual(sales_order.payment_schedule[1].payment_amount, 8906.00) self.assertEqual(sales_order.payment_schedule[1].due_date, getdate(add_days(quotation.transaction_date, 30)))
def create_proof_submission(employee, payroll_period, amount): submission_date = add_months(payroll_period.start_date, random.randint(0, 11)) proof_submission = dataent.get_doc({ "doctype": "Employee Tax Exemption Proof Submission", "employee": employee, "payroll_period": payroll_period.name, "submission_date": submission_date }) proof_submission.append( "tax_exemption_proofs", { "exemption_sub_category": "_Test Sub Category", "exemption_category": "_Test Category", "type_of_proof": "Test", "amount": amount }) proof_submission.submit() return submission_date
def test_make_sales_order_with_different_currency(self): from epaas.selling.doctype.quotation.quotation import make_sales_order quotation = dataent.copy_doc(test_records[0]) quotation.transaction_date = nowdate() quotation.valid_till = add_months(quotation.transaction_date, 1) quotation.insert() quotation.submit() sales_order = make_sales_order(quotation.name) sales_order.currency = "USD" sales_order.conversion_rate = 20.0 sales_order.delivery_date = "2019-01-01" sales_order.naming_series = "_T-Quotation-" sales_order.transaction_date = nowdate() sales_order.insert() self.assertEquals(sales_order.currency, "USD") self.assertNotEqual(sales_order.currency, quotation.currency)
def make_salary_structure_for_timesheet(employee): salary_structure_name = "Timesheet Salary Structure Test" frequency = "Monthly" salary_structure = make_salary_structure(salary_structure_name, frequency, dont_submit=True) salary_structure.salary_component = "Timesheet Component" salary_structure.salary_slip_based_on_timesheet = 1 salary_structure.hour_rate = 50.0 salary_structure.save() salary_structure.submit() if not dataent.db.get_value("Salary Structure Assignment", { 'employee': employee, 'docstatus': 1 }): dataent.db.set_value('Employee', employee, 'date_of_joining', add_months(nowdate(), -5)) create_salary_structure_assignment(employee, salary_structure.name) return salary_structure
def get_due_date_from_template(template_name, posting_date, bill_date): """ Inspects all `Payment Term`s from the a `Payment Terms Template` and returns the due date after considering all the `Payment Term`s requirements. :param template_name: Name of the `Payment Terms Template` :return: String representing the calculated due date """ due_date = getdate(bill_date or posting_date) template = dataent.get_doc('Payment Terms Template', template_name) for term in template.terms: if term.due_date_based_on == 'Day(s) after invoice date': due_date = max(due_date, add_days(due_date, term.credit_days)) elif term.due_date_based_on == 'Day(s) after the end of the invoice month': due_date = max(due_date, add_days(get_last_day(due_date), term.credit_days)) else: due_date = max( due_date, add_months(get_last_day(due_date), term.credit_months)) return due_date
def test_create_quotation_with_margin(self): from epaas.selling.doctype.quotation.quotation import make_sales_order from epaas.selling.doctype.sales_order.sales_order \ import make_delivery_note, make_sales_invoice rate_with_margin = flt((1500 * 18.75) / 100 + 1500) test_records[0]['items'][0]['price_list_rate'] = 1500 test_records[0]['items'][0]['margin_type'] = 'Percentage' test_records[0]['items'][0]['margin_rate_or_amount'] = 18.75 quotation = dataent.copy_doc(test_records[0]) quotation.transaction_date = nowdate() quotation.valid_till = add_months(quotation.transaction_date, 1) quotation.insert() self.assertEqual(quotation.get("items")[0].rate, rate_with_margin) self.assertRaises(dataent.ValidationError, make_sales_order, quotation.name) quotation.submit() sales_order = make_sales_order(quotation.name) sales_order.naming_series = "_T-Quotation-" sales_order.transaction_date = "2016-01-01" sales_order.delivery_date = "2016-01-02" sales_order.insert() self.assertEqual(quotation.get("items")[0].rate, rate_with_margin) sales_order.submit() dn = make_delivery_note(sales_order.name) self.assertEqual(quotation.get("items")[0].rate, rate_with_margin) dn.save() si = make_sales_invoice(sales_order.name) self.assertEqual(quotation.get("items")[0].rate, rate_with_margin) si.save()
def get_accumulated_monthly_budget(monthly_distribution, posting_date, fiscal_year, annual_budget): distribution = {} if monthly_distribution: for d in dataent.db.sql("""select mdp.month, mdp.percentage_allocation from `tabMonthly Distribution Percentage` mdp, `tabMonthly Distribution` md where mdp.parent=md.name and md.fiscal_year=%s""", fiscal_year, as_dict=1): distribution.setdefault(d.month, d.percentage_allocation) dt = dataent.db.get_value("Fiscal Year", fiscal_year, "year_start_date") accumulated_percentage = 0.0 while (dt <= getdate(posting_date)): if monthly_distribution: accumulated_percentage += distribution.get( getdate(dt).strftime("%B"), 0) else: accumulated_percentage += 100.0 / 12 dt = add_months(dt, 1) return annual_budget * accumulated_percentage / 100
def make_blanket_order(**args): args = dataent._dict(args) bo = dataent.new_doc("Blanket Order") bo.blanket_order_type = args.blanket_order_type bo.company = args.company or "_Test Company" if args.blanket_order_type == "Selling": bo.customer = args.customer or "_Test Customer" else: bo.supplier = args.supplier or "_Test Supplier" bo.from_date = today() bo.to_date = add_months(bo.from_date, months=12) bo.append( "items", { "item_code": args.item_code or "_Test Item", "qty": args.quantity or 1000, "rate": args.rate or 100 }) bo.insert() bo.submit() return bo
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(months // months_to_add): period = dataent._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 make_depreciation_schedule(self): depreciation_method = [ d.depreciation_method for d in self.finance_books ] if 'Manual' not in depreciation_method: self.schedules = [] if not self.get("schedules") and self.available_for_use_date: total_depreciations = sum([ d.total_number_of_depreciations for d in self.get('finance_books') ]) for d in self.get('finance_books'): self.validate_asset_finance_books(d) value_after_depreciation = ( flt(self.gross_purchase_amount) - flt(self.opening_accumulated_depreciation)) d.value_after_depreciation = value_after_depreciation no_of_depreciations = cint( d.total_number_of_depreciations - 1) - cint( self.number_of_depreciations_booked) end_date = add_months( d.depreciation_start_date, no_of_depreciations * cint(d.frequency_of_depreciation)) total_days = date_diff(end_date, self.available_for_use_date) rate_per_day = ( value_after_depreciation - d.get("expected_value_after_useful_life")) / total_days number_of_pending_depreciations = cint(d.total_number_of_depreciations) - \ cint(self.number_of_depreciations_booked) from_date = self.available_for_use_date if number_of_pending_depreciations: next_depr_date = getdate( add_months(self.available_for_use_date, number_of_pending_depreciations * 12)) if (cint( dataent.db.get_value( "Asset Settings", None, "schedule_based_on_fiscal_year")) == 1 and getdate( d.depreciation_start_date) < next_depr_date): number_of_pending_depreciations += 1 for n in range(number_of_pending_depreciations): if n == list(range( number_of_pending_depreciations))[-1]: schedule_date = add_months( self.available_for_use_date, n * 12) previous_scheduled_date = add_months( d.depreciation_start_date, (n - 1) * 12) depreciation_amount = \ self.get_depreciation_amount_prorata_temporis(value_after_depreciation, d, previous_scheduled_date, schedule_date) elif n == list( range(number_of_pending_depreciations))[0]: schedule_date = d.depreciation_start_date depreciation_amount = \ self.get_depreciation_amount_prorata_temporis(value_after_depreciation, d, self.available_for_use_date, schedule_date) else: schedule_date = add_months( d.depreciation_start_date, n * 12) depreciation_amount = \ self.get_depreciation_amount_prorata_temporis(value_after_depreciation, d) if value_after_depreciation != 0: value_after_depreciation -= flt( depreciation_amount) self.append( "schedules", { "schedule_date": schedule_date, "depreciation_amount": depreciation_amount, "depreciation_method": d.depreciation_method, "finance_book": d.finance_book, "finance_book_id": d.idx }) else: for n in range(number_of_pending_depreciations): schedule_date = add_months( d.depreciation_start_date, n * cint(d.frequency_of_depreciation)) if d.depreciation_method in ("Straight Line", "Manual"): days = date_diff(schedule_date, from_date) if n == 0: days += 1 depreciation_amount = days * rate_per_day from_date = schedule_date else: depreciation_amount = self.get_depreciation_amount( value_after_depreciation, d.total_number_of_depreciations, d) if depreciation_amount: value_after_depreciation -= flt( depreciation_amount) self.append( "schedules", { "schedule_date": schedule_date, "depreciation_amount": depreciation_amount, "depreciation_method": d.depreciation_method, "finance_book": d.finance_book, "finance_book_id": d.idx })
def get_monthly_goal_graph_data(title, doctype, docname, goal_value_field, goal_total_field, goal_history_field, goal_doctype, goal_doctype_link, goal_field, date_field, filter_str, aggregation="sum"): ''' Get month-wise graph data for a doctype based on aggregation values of a field in the goal doctype :param title: Graph title :param doctype: doctype of graph doc :param docname: of the doc to set the graph in :param goal_value_field: goal field of doctype :param goal_total_field: current month value field of doctype :param goal_history_field: cached history field :param goal_doctype: doctype the goal is based on :param goal_doctype_link: doctype link field in goal_doctype :param goal_field: field from which the goal is calculated :param filter_str: where clause condition :param aggregation: a value like 'count', 'sum', 'avg' :return: dict of graph data ''' from dataent.utils.formatters import format_value import json meta = dataent.get_meta(doctype) doc = dataent.get_doc(doctype, docname) goal = doc.get(goal_value_field) formatted_goal = format_value(goal, meta.get_field(goal_value_field), doc) current_month_value = doc.get(goal_total_field) formatted_value = format_value(current_month_value, meta.get_field(goal_total_field), doc) from dataent.utils import today, getdate, formatdate, add_months current_month_year = formatdate(today(), "MM-yyyy") history = doc.get(goal_history_field) try: month_to_value_dict = json.loads(history) if history and '{' in history else None except ValueError: month_to_value_dict = None if month_to_value_dict is None: doc_filter = (goal_doctype_link + ' = "' + docname + '"') if doctype != goal_doctype else '' if filter_str: doc_filter += ' and ' + filter_str if doc_filter else filter_str month_to_value_dict = get_monthly_results(goal_doctype, goal_field, date_field, doc_filter, aggregation) dataent.db.set_value(doctype, docname, goal_history_field, json.dumps(month_to_value_dict)) month_to_value_dict[current_month_year] = current_month_value months = [] months_formatted = [] values = [] values_formatted = [] for i in range(0, 12): date_value = add_months(today(), -i) month_value = formatdate(date_value, "MM-yyyy") month_word = getdate(date_value).strftime('%b') month_year = getdate(date_value).strftime('%B') + ', ' + getdate(date_value).strftime('%Y') months.insert(0, month_word) months_formatted.insert(0, month_year) if month_value in month_to_value_dict: val = month_to_value_dict[month_value] else: val = 0 values.insert(0, val) values_formatted.insert(0, format_value(val, meta.get_field(goal_total_field), doc)) y_markers = [] summary_values = [ { 'title': _("This month"), 'color': '#ffa00a', 'value': formatted_value } ] if float(goal) > 0: y_markers = [ { 'label': _("Goal"), 'lineType': "dashed", 'value': goal }, ] summary_values += [ { 'title': _("Goal"), 'color': '#5e64ff', 'value': formatted_goal }, { 'title': _("Completed"), 'color': '#28a745', 'value': str(int(round(float(current_month_value)/float(goal)*100))) + "%" } ] data = { 'title': title, # 'subtitle': 'data': { 'datasets': [ { 'values': values, 'formatted': values_formatted } ], 'labels': months, }, 'summary': summary_values, } if y_markers: data["data"]["yMarkers"] = y_markers return data