Merge branch 'develop' into improve_taxes_setup
This commit is contained in:
commit
344cb11a21
@ -13,6 +13,7 @@
|
||||
"stop_birthday_reminders",
|
||||
"expense_approver_mandatory_in_expense_claim",
|
||||
"leave_settings",
|
||||
"send_leave_notification",
|
||||
"leave_approval_notification_template",
|
||||
"leave_status_notification_template",
|
||||
"role_allowed_to_create_backdated_leave_application",
|
||||
@ -69,15 +70,19 @@
|
||||
"label": "Leave Settings"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.send_leave_notification == 1",
|
||||
"fieldname": "leave_approval_notification_template",
|
||||
"fieldtype": "Link",
|
||||
"label": "Leave Approval Notification Template",
|
||||
"mandatory_depends_on": "eval: doc.send_leave_notification == 1",
|
||||
"options": "Email Template"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.send_leave_notification == 1",
|
||||
"fieldname": "leave_status_notification_template",
|
||||
"fieldtype": "Link",
|
||||
"label": "Leave Status Notification Template",
|
||||
"mandatory_depends_on": "eval: doc.send_leave_notification == 1",
|
||||
"options": "Email Template"
|
||||
},
|
||||
{
|
||||
@ -132,13 +137,19 @@
|
||||
"fieldname": "automatically_allocate_leaves_based_on_leave_policy",
|
||||
"fieldtype": "Check",
|
||||
"label": "Automatically Allocate Leaves Based On Leave Policy"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"fieldname": "send_leave_notification",
|
||||
"fieldtype": "Check",
|
||||
"label": "Send Leave Notification"
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-cog",
|
||||
"idx": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2021-02-25 12:31:14.947865",
|
||||
"modified": "2021-03-14 02:04:22.907159",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "HR Settings",
|
||||
|
@ -40,7 +40,8 @@ class LeaveApplication(Document):
|
||||
def on_update(self):
|
||||
if self.status == "Open" and self.docstatus < 1:
|
||||
# notify leave approver about creation
|
||||
self.notify_leave_approver()
|
||||
if frappe.db.get_single_value("HR Settings", "send_leave_notification"):
|
||||
self.notify_leave_approver()
|
||||
|
||||
def on_submit(self):
|
||||
if self.status == "Open":
|
||||
@ -50,7 +51,8 @@ class LeaveApplication(Document):
|
||||
self.update_attendance()
|
||||
|
||||
# notify leave applier about approval
|
||||
self.notify_employee()
|
||||
if frappe.db.get_single_value("HR Settings", "send_leave_notification"):
|
||||
self.notify_employee()
|
||||
self.create_leave_ledger_entry()
|
||||
self.reload()
|
||||
|
||||
@ -60,7 +62,8 @@ class LeaveApplication(Document):
|
||||
def on_cancel(self):
|
||||
self.create_leave_ledger_entry(submit=False)
|
||||
# notify leave applier about cancellation
|
||||
self.notify_employee()
|
||||
if frappe.db.get_single_value("HR Settings", "send_leave_notification"):
|
||||
self.notify_employee()
|
||||
self.cancel_attendance()
|
||||
|
||||
def validate_applicable_after(self):
|
||||
|
@ -91,6 +91,10 @@ def capture_razorpay_donations(*args, **kwargs):
|
||||
if not data.event == 'payment.captured':
|
||||
return
|
||||
|
||||
# to avoid capturing subscription payments as donations
|
||||
if payment.description and 'subscription' in str(payment.description).lower():
|
||||
return
|
||||
|
||||
donor = get_donor(payment.email)
|
||||
if not donor:
|
||||
donor = create_donor(payment)
|
||||
@ -119,7 +123,7 @@ def create_donation(donor, payment):
|
||||
'donor_name': donor.donor_name,
|
||||
'email': donor.email,
|
||||
'date': getdate(),
|
||||
'amount': flt(payment.amount),
|
||||
'amount': flt(payment.amount) / 100, # Convert to rupees from paise
|
||||
'mode_of_payment': payment.method,
|
||||
'razorpay_payment_id': payment.id
|
||||
}).insert(ignore_mandatory=True)
|
||||
|
@ -48,7 +48,7 @@ class Membership(Document):
|
||||
last_membership = erpnext.get_last_membership(self.member)
|
||||
|
||||
# if person applied for offline membership
|
||||
if last_membership and not frappe.session.user == "Administrator":
|
||||
if last_membership and last_membership != self.name and not frappe.session.user == "Administrator":
|
||||
# if last membership does not expire in 30 days, then do not allow to renew
|
||||
if getdate(add_days(last_membership.to_date, -30)) > getdate(nowdate()) :
|
||||
frappe.throw(_("You can only renew if your membership expires within 30 days"))
|
||||
@ -287,7 +287,7 @@ def trigger_razorpay_subscription(*args, **kwargs):
|
||||
membership.generate_invoice(with_payment_entry=settings.automate_membership_payment_entries, save=True)
|
||||
|
||||
except Exception as e:
|
||||
message = "{0}\n\n{1}\n\n{2}: {3}".format(e, frappe.get_traceback(), __("Payment ID"), payment.id)
|
||||
message = "{0}\n\n{1}\n\n{2}: {3}".format(e, frappe.get_traceback(), _("Payment ID"), payment.id)
|
||||
log = frappe.log_error(message, _("Error creating membership entry for {0}").format(member.name))
|
||||
notify_failure(log)
|
||||
return { "status": "Failed", "reason": e}
|
||||
|
@ -759,3 +759,4 @@ erpnext.patches.v13_0.update_vehicle_no_reqd_condition
|
||||
erpnext.patches.v13_0.setup_fields_for_80g_certificate_and_donation
|
||||
erpnext.patches.v13_0.rename_membership_settings_to_non_profit_settings
|
||||
erpnext.patches.v13_0.setup_gratuity_rule_for_india_and_uae
|
||||
execute:frappe.db.set_value('System Settings', None, 'app_name', 'ERPNext')
|
||||
|
@ -11,6 +11,7 @@ def execute():
|
||||
|
||||
# Update options in gst_state custom fields
|
||||
for field in custom_fields:
|
||||
gst_state_field = frappe.get_doc('Custom Field', field)
|
||||
gst_state_field.options = '\n'.join(states)
|
||||
gst_state_field.save()
|
||||
if frappe.db.exists('Custom Field', field):
|
||||
gst_state_field = frappe.get_doc('Custom Field', field)
|
||||
gst_state_field.options = '\n'.join(states)
|
||||
gst_state_field.save()
|
||||
|
@ -2,15 +2,12 @@ import frappe
|
||||
from erpnext.regional.india.setup import make_custom_fields
|
||||
|
||||
def execute():
|
||||
company = frappe.get_all('Company', filters = {'country': 'India'})
|
||||
if not company:
|
||||
return
|
||||
if frappe.get_all('Company', filters = {'country': 'India'}):
|
||||
make_custom_fields()
|
||||
|
||||
make_custom_fields()
|
||||
|
||||
if not frappe.db.exists('Party Type', 'Donor'):
|
||||
frappe.get_doc({
|
||||
'doctype': 'Party Type',
|
||||
'party_type': 'Donor',
|
||||
'account_type': 'Receivable'
|
||||
}).insert(ignore_permissions=True)
|
||||
if not frappe.db.exists('Party Type', 'Donor'):
|
||||
frappe.get_doc({
|
||||
'doctype': 'Party Type',
|
||||
'party_type': 'Donor',
|
||||
'account_type': 'Receivable'
|
||||
}).insert(ignore_permissions=True)
|
||||
|
@ -89,10 +89,11 @@ class AdditionalSalary(Document):
|
||||
no_of_days = date_diff(getdate(end_date), getdate(start_date)) + 1
|
||||
return amount_per_day * no_of_days
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_additional_salary_component(employee, start_date, end_date, component_type):
|
||||
additional_salaries = frappe.db.sql("""
|
||||
select name, salary_component, type, amount, overwrite_salary_structure_amount, deduct_full_tax_on_selected_payroll_date
|
||||
def get_additional_salaries(employee, start_date, end_date, component_type):
|
||||
additional_salary_list = frappe.db.sql("""
|
||||
select name, salary_component as component, type, amount,
|
||||
overwrite_salary_structure_amount as overwrite,
|
||||
deduct_full_tax_on_selected_payroll_date
|
||||
from `tabAdditional Salary`
|
||||
where employee=%(employee)s
|
||||
and docstatus = 1
|
||||
@ -102,7 +103,7 @@ def get_additional_salary_component(employee, start_date, end_date, component_ty
|
||||
from_date <= %(to_date)s and to_date >= %(to_date)s
|
||||
)
|
||||
and type = %(component_type)s
|
||||
order by salary_component, overwrite_salary_structure_amount DESC
|
||||
order by salary_component, overwrite ASC
|
||||
""", {
|
||||
'employee': employee,
|
||||
'from_date': start_date,
|
||||
@ -110,38 +111,18 @@ def get_additional_salary_component(employee, start_date, end_date, component_ty
|
||||
'component_type': "Earning" if component_type == "earnings" else "Deduction"
|
||||
}, as_dict=1)
|
||||
|
||||
existing_salary_components= []
|
||||
salary_components_details = {}
|
||||
additional_salary_details = []
|
||||
additional_salaries = []
|
||||
components_to_overwrite = []
|
||||
|
||||
overwrites_components = [ele.salary_component for ele in additional_salaries if ele.overwrite_salary_structure_amount == 1]
|
||||
for d in additional_salary_list:
|
||||
if d.overwrite:
|
||||
if d.component in components_to_overwrite:
|
||||
frappe.throw(_("Multiple Additional Salaries with overwrite "
|
||||
"property exist for Salary Component {0} between {1} and {2}.").format(
|
||||
frappe.bold(d.component), start_date, end_date), title=_("Error"))
|
||||
|
||||
component_fields = ["depends_on_payment_days", "salary_component_abbr", "is_tax_applicable", "variable_based_on_taxable_salary", 'type']
|
||||
for d in additional_salaries:
|
||||
components_to_overwrite.append(d.component)
|
||||
|
||||
if d.salary_component not in existing_salary_components:
|
||||
component = frappe.get_all("Salary Component", filters={'name': d.salary_component}, fields=component_fields)
|
||||
struct_row = frappe._dict({'salary_component': d.salary_component})
|
||||
if component:
|
||||
struct_row.update(component[0])
|
||||
additional_salaries.append(d)
|
||||
|
||||
struct_row['deduct_full_tax_on_selected_payroll_date'] = d.deduct_full_tax_on_selected_payroll_date
|
||||
struct_row['is_additional_component'] = 1
|
||||
|
||||
salary_components_details[d.salary_component] = struct_row
|
||||
|
||||
|
||||
if overwrites_components.count(d.salary_component) > 1:
|
||||
frappe.throw(_("Multiple Additional Salaries with overwrite property exist for Salary Component: {0} between {1} and {2}.".format(d.salary_component, start_date, end_date)), title=_("Error"))
|
||||
else:
|
||||
additional_salary_details.append({
|
||||
'name': d.name,
|
||||
'component': d.salary_component,
|
||||
'amount': d.amount,
|
||||
'type': d.type,
|
||||
'overwrite': d.overwrite_salary_structure_amount,
|
||||
})
|
||||
|
||||
existing_salary_components.append(d.salary_component)
|
||||
|
||||
return salary_components_details, additional_salary_details
|
||||
return additional_salaries
|
||||
|
@ -13,7 +13,7 @@ from erpnext.payroll.doctype.payroll_entry.payroll_entry import get_start_end_da
|
||||
from erpnext.hr.doctype.employee.employee import get_holiday_list_for_employee
|
||||
from erpnext.utilities.transaction_base import TransactionBase
|
||||
from frappe.utils.background_jobs import enqueue
|
||||
from erpnext.payroll.doctype.additional_salary.additional_salary import get_additional_salary_component
|
||||
from erpnext.payroll.doctype.additional_salary.additional_salary import get_additional_salaries
|
||||
from erpnext.payroll.doctype.payroll_period.payroll_period import get_period_factor, get_payroll_period
|
||||
from erpnext.payroll.doctype.employee_benefit_application.employee_benefit_application import get_benefit_component_amount
|
||||
from erpnext.payroll.doctype.employee_benefit_claim.employee_benefit_claim import get_benefit_claim_amount, get_last_payroll_period_benefits
|
||||
@ -524,7 +524,7 @@ class SalarySlip(TransactionBase):
|
||||
|
||||
except NameError as err:
|
||||
frappe.throw(_("{0} <br> This error can be due to missing or deleted field.").format(err),
|
||||
title=_("Name error"))
|
||||
title=_("Name error"))
|
||||
except SyntaxError as err:
|
||||
frappe.throw(_("Syntax error in formula or condition: {0}").format(err))
|
||||
except Exception as e:
|
||||
@ -558,15 +558,16 @@ class SalarySlip(TransactionBase):
|
||||
self.update_component_row(frappe._dict(last_benefit.struct_row), amount, "earnings")
|
||||
|
||||
def add_additional_salary_components(self, component_type):
|
||||
salary_components_details, additional_salary_details = get_additional_salary_component(self.employee,
|
||||
additional_salaries = get_additional_salaries(self.employee,
|
||||
self.start_date, self.end_date, component_type)
|
||||
if salary_components_details and additional_salary_details:
|
||||
for additional_salary in additional_salary_details:
|
||||
additional_salary =frappe._dict(additional_salary)
|
||||
amount = additional_salary.amount
|
||||
overwrite = additional_salary.overwrite
|
||||
self.update_component_row(frappe._dict(salary_components_details[additional_salary.component]), amount,
|
||||
component_type, overwrite=overwrite, additional_salary=additional_salary.name)
|
||||
|
||||
for additional_salary in additional_salaries:
|
||||
self.update_component_row(
|
||||
get_salary_component_data(additional_salary.component),
|
||||
additional_salary.amount,
|
||||
component_type,
|
||||
additional_salary
|
||||
)
|
||||
|
||||
def add_tax_components(self, payroll_period):
|
||||
# Calculate variable_based_on_taxable_salary after all components updated in salary slip
|
||||
@ -583,47 +584,59 @@ class SalarySlip(TransactionBase):
|
||||
|
||||
for d in tax_components:
|
||||
tax_amount = self.calculate_variable_based_on_taxable_salary(d, payroll_period)
|
||||
tax_row = self.get_salary_slip_row(d)
|
||||
tax_row = get_salary_component_data(d)
|
||||
self.update_component_row(tax_row, tax_amount, "deductions")
|
||||
|
||||
def update_component_row(self, struct_row, amount, key, overwrite=1, additional_salary = ''):
|
||||
def update_component_row(self, component_data, amount, component_type, additional_salary=None):
|
||||
component_row = None
|
||||
for d in self.get(key):
|
||||
if d.salary_component == struct_row.salary_component:
|
||||
for d in self.get(component_type):
|
||||
if d.salary_component != component_data.salary_component:
|
||||
continue
|
||||
|
||||
if (
|
||||
not d.additional_salary
|
||||
and (not additional_salary or additional_salary.overwrite)
|
||||
or additional_salary
|
||||
and additional_salary.name == d.additional_salary
|
||||
):
|
||||
component_row = d
|
||||
break
|
||||
|
||||
if not component_row or (struct_row.get("is_additional_component") and not overwrite):
|
||||
if amount:
|
||||
self.append(key, {
|
||||
'amount': amount,
|
||||
'default_amount': amount if not struct_row.get("is_additional_component") else 0,
|
||||
'depends_on_payment_days' : struct_row.depends_on_payment_days,
|
||||
'salary_component' : struct_row.salary_component,
|
||||
'abbr' : struct_row.abbr or struct_row.get("salary_component_abbr"),
|
||||
'additional_salary': additional_salary,
|
||||
'do_not_include_in_total' : struct_row.do_not_include_in_total,
|
||||
'is_tax_applicable': struct_row.is_tax_applicable,
|
||||
'is_flexible_benefit': struct_row.is_flexible_benefit,
|
||||
'variable_based_on_taxable_salary': struct_row.variable_based_on_taxable_salary,
|
||||
'deduct_full_tax_on_selected_payroll_date': struct_row.deduct_full_tax_on_selected_payroll_date,
|
||||
'additional_amount': amount if struct_row.get("is_additional_component") else 0,
|
||||
'exempted_from_income_tax': struct_row.exempted_from_income_tax
|
||||
})
|
||||
if additional_salary and additional_salary.overwrite:
|
||||
# Additional Salary with overwrite checked, remove default rows of same component
|
||||
self.set(component_type, [
|
||||
d for d in self.get(component_type)
|
||||
if d.salary_component != component_data.salary_component
|
||||
or d.additional_salary and additional_salary.name != d.additional_salary
|
||||
or d == component_row
|
||||
])
|
||||
|
||||
if not component_row:
|
||||
if not amount:
|
||||
return
|
||||
|
||||
component_row = self.append(component_type)
|
||||
for attr in (
|
||||
'depends_on_payment_days', 'salary_component', 'abbr'
|
||||
'do_not_include_in_total', 'is_tax_applicable',
|
||||
'is_flexible_benefit', 'variable_based_on_taxable_salary',
|
||||
'exempted_from_income_tax'
|
||||
):
|
||||
component_row.set(attr, component_data.get(attr))
|
||||
|
||||
if additional_salary:
|
||||
component_row.default_amount = 0
|
||||
component_row.additional_amount = amount
|
||||
component_row.additional_salary = additional_salary.name
|
||||
component_row.deduct_full_tax_on_selected_payroll_date = \
|
||||
additional_salary.deduct_full_tax_on_selected_payroll_date
|
||||
else:
|
||||
if struct_row.get("is_additional_component"):
|
||||
if overwrite:
|
||||
component_row.additional_amount = amount - component_row.get("default_amount", 0)
|
||||
component_row.additional_salary = additional_salary
|
||||
else:
|
||||
component_row.additional_amount = amount
|
||||
component_row.default_amount = amount
|
||||
component_row.additional_amount = 0
|
||||
component_row.deduct_full_tax_on_selected_payroll_date = \
|
||||
component_data.deduct_full_tax_on_selected_payroll_date
|
||||
|
||||
if not overwrite and component_row.default_amount:
|
||||
amount += component_row.default_amount
|
||||
else:
|
||||
component_row.default_amount = amount
|
||||
|
||||
component_row.amount = amount
|
||||
component_row.deduct_full_tax_on_selected_payroll_date = struct_row.deduct_full_tax_on_selected_payroll_date
|
||||
component_row.amount = amount
|
||||
|
||||
def calculate_variable_based_on_taxable_salary(self, tax_component, payroll_period):
|
||||
if not payroll_period:
|
||||
@ -950,26 +963,13 @@ class SalarySlip(TransactionBase):
|
||||
return frappe.safe_eval(condition, self.whitelisted_globals, data)
|
||||
except NameError as err:
|
||||
frappe.throw(_("{0} <br> This error can be due to missing or deleted field.").format(err),
|
||||
title=_("Name error"))
|
||||
title=_("Name error"))
|
||||
except SyntaxError as err:
|
||||
frappe.throw(_("Syntax error in condition: {0}").format(err))
|
||||
except Exception as e:
|
||||
frappe.throw(_("Error in formula or condition: {0}").format(e))
|
||||
raise
|
||||
|
||||
def get_salary_slip_row(self, salary_component):
|
||||
component = frappe.get_doc("Salary Component", salary_component)
|
||||
# Data for update_component_row
|
||||
struct_row = frappe._dict()
|
||||
struct_row['depends_on_payment_days'] = component.depends_on_payment_days
|
||||
struct_row['salary_component'] = component.name
|
||||
struct_row['abbr'] = component.salary_component_abbr
|
||||
struct_row['do_not_include_in_total'] = component.do_not_include_in_total
|
||||
struct_row['is_tax_applicable'] = component.is_tax_applicable
|
||||
struct_row['is_flexible_benefit'] = component.is_flexible_benefit
|
||||
struct_row['variable_based_on_taxable_salary'] = component.variable_based_on_taxable_salary
|
||||
return struct_row
|
||||
|
||||
def get_component_totals(self, component_type, depends_on_payment_days=0):
|
||||
joining_date, relieving_date = frappe.get_cached_value("Employee", self.employee,
|
||||
["date_of_joining", "relieving_date"])
|
||||
@ -1032,7 +1032,6 @@ class SalarySlip(TransactionBase):
|
||||
self.total_loan_repayment += payment.total_payment
|
||||
|
||||
def get_loan_details(self):
|
||||
|
||||
return frappe.get_all("Loan",
|
||||
fields=["name", "interest_income_account", "loan_account", "loan_type"],
|
||||
filters = {
|
||||
@ -1263,3 +1262,19 @@ def unlink_ref_doc_from_salary_slip(ref_no):
|
||||
def generate_password_for_pdf(policy_template, employee):
|
||||
employee = frappe.get_doc("Employee", employee)
|
||||
return policy_template.format(**employee.as_dict())
|
||||
|
||||
def get_salary_component_data(component):
|
||||
return frappe.get_value(
|
||||
"Salary Component",
|
||||
component,
|
||||
[
|
||||
"name as salary_component",
|
||||
"depends_on_payment_days",
|
||||
"salary_component_abbr as abbr",
|
||||
"do_not_include_in_total",
|
||||
"is_tax_applicable",
|
||||
"is_flexible_benefit",
|
||||
"variable_based_on_taxable_salary",
|
||||
],
|
||||
as_dict=1,
|
||||
)
|
||||
|
@ -29,7 +29,10 @@ class TaxExemption80GCertificate(Document):
|
||||
|
||||
def validate_duplicates(self):
|
||||
if self.recipient == 'Donor':
|
||||
certificate = frappe.db.exists(self.doctype, {'donation': self.donation})
|
||||
certificate = frappe.db.exists(self.doctype, {
|
||||
'donation': self.donation,
|
||||
'name': ('!=', self.name)
|
||||
})
|
||||
if certificate:
|
||||
frappe.throw(_('An 80G Certificate {0} already exists for the donation {1}').format(
|
||||
get_link_to_form(self.doctype, certificate), frappe.bold(self.donation)
|
||||
|
@ -719,25 +719,12 @@ def update_grand_total_for_rcm(doc, method):
|
||||
if country != 'India':
|
||||
return
|
||||
|
||||
if not doc.total_taxes_and_charges:
|
||||
gst_tax, base_gst_tax = get_gst_tax_amount(doc)
|
||||
|
||||
if not base_gst_tax:
|
||||
return
|
||||
|
||||
if doc.reverse_charge == 'Y':
|
||||
gst_accounts = get_gst_accounts(doc.company)
|
||||
gst_account_list = gst_accounts.get('cgst_account') + gst_accounts.get('sgst_account') \
|
||||
+ gst_accounts.get('igst_account')
|
||||
|
||||
base_gst_tax = 0
|
||||
gst_tax = 0
|
||||
|
||||
for tax in doc.get('taxes'):
|
||||
if tax.category not in ("Total", "Valuation and Total"):
|
||||
continue
|
||||
|
||||
if flt(tax.base_tax_amount_after_discount_amount) and tax.account_head in gst_account_list:
|
||||
base_gst_tax += tax.base_tax_amount_after_discount_amount
|
||||
gst_tax += tax.tax_amount_after_discount_amount
|
||||
|
||||
doc.taxes_and_charges_added -= gst_tax
|
||||
doc.total_taxes_and_charges -= gst_tax
|
||||
doc.base_taxes_and_charges_added -= base_gst_tax
|
||||
@ -771,6 +758,11 @@ def make_regional_gl_entries(gl_entries, doc):
|
||||
if country != 'India':
|
||||
return gl_entries
|
||||
|
||||
gst_tax, base_gst_tax = get_gst_tax_amount(doc)
|
||||
|
||||
if not base_gst_tax:
|
||||
return gl_entries
|
||||
|
||||
if doc.reverse_charge == 'Y':
|
||||
gst_accounts = get_gst_accounts(doc.company)
|
||||
gst_account_list = gst_accounts.get('cgst_account') + gst_accounts.get('sgst_account') \
|
||||
@ -799,6 +791,24 @@ def make_regional_gl_entries(gl_entries, doc):
|
||||
|
||||
return gl_entries
|
||||
|
||||
def get_gst_tax_amount(doc):
|
||||
gst_accounts = get_gst_accounts(doc.company)
|
||||
gst_account_list = gst_accounts.get('cgst_account', []) + gst_accounts.get('sgst_account', []) \
|
||||
+ gst_accounts.get('igst_account', [])
|
||||
|
||||
base_gst_tax = 0
|
||||
gst_tax = 0
|
||||
|
||||
for tax in doc.get('taxes'):
|
||||
if tax.category not in ("Total", "Valuation and Total"):
|
||||
continue
|
||||
|
||||
if flt(tax.base_tax_amount_after_discount_amount) and tax.account_head in gst_account_list:
|
||||
base_gst_tax += tax.base_tax_amount_after_discount_amount
|
||||
gst_tax += tax.tax_amount_after_discount_amount
|
||||
|
||||
return gst_tax, base_gst_tax
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_regional_round_off_accounts(company, account_list):
|
||||
country = frappe.get_cached_value('Company', company, 'country')
|
||||
|
@ -161,5 +161,4 @@ def add_standard_navbar_items():
|
||||
navbar_settings.save()
|
||||
|
||||
def add_app_name():
|
||||
settings = frappe.get_doc("System Settings")
|
||||
settings.app_name = _("ERPNext")
|
||||
frappe.db.set_value('System Settings', None, 'app_name', 'ERPNext')
|
||||
|
@ -717,6 +717,18 @@ $.extend(erpnext.item, {
|
||||
.on('focus', function(e) {
|
||||
$(e.target).val('').trigger('input');
|
||||
})
|
||||
.on("awesomplete-open", () => {
|
||||
let modal = field.$input.parents('.modal-dialog')[0];
|
||||
if (modal) {
|
||||
$(modal).removeClass("modal-dialog-scrollable");
|
||||
}
|
||||
})
|
||||
.on("awesomplete-close", () => {
|
||||
let modal = field.$input.parents('.modal-dialog')[0];
|
||||
if (modal) {
|
||||
$(modal).addClass("modal-dialog-scrollable");
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<div class="web-list-item transaction-list-item">
|
||||
<a href="/issues?name={{ doc.name }}" class="no-underline">
|
||||
<div class="row py-4 border-bottom">
|
||||
<div class="row py-4">
|
||||
<div class="col-3 d-flex align-items-center">
|
||||
{% set indicator = 'red' if doc.status == 'Open' else 'gray' %}
|
||||
{% set indicator = 'green' if doc.status == 'Closed' else indicator %}
|
||||
|
Loading…
Reference in New Issue
Block a user