and tssa.employee = %s
and ifnull(tas.from_date,tas.payroll_date) <= %s"""
results = frappe.db.sql(salary, values=(self.employee,self.from_date))
if results and results[0]:
salary = results[0][0]
else:
salary = frappe.throw(_("No salary was found no deduction applied"))
It’s often easier not to use direct SQL, but instead to use frappe.get_all or similar.
Edit: just seen that this is what Brian Pond recommended, but I’ve already written it now and it might explain why you should do this rather than string interpolation.
It is also always a bad idea to use string interpolation in SQL for parameters. That’s how you get SQL injection attacks if you fail to sanitize your data…
For example, you have:
frappe.db.sql(
"""SELECT salary_rate FROM `tabEmployee Salary` WHERE user_id="{}";""".format(user_id)
)
All very well and good, but what happens if I put my name as my_name" OR 1 OR "?
Now you are making an SQL query:
frappe.db.sql(
"""SELECT salary_rate FROM `tabEmployee Salary` WHERE user_id="my_name" OR 1 OR "";
)
which will return everyone’s salary rate…
What you should do is used a parametrized query, namely:
user_id = 'my_name" OR 1 OR "'
frappe.db.sql(
"""SELECT salary_rate FROM `tabEmployee Salary` WHERE user_id=%(user_id)s;""",
{'user_id': user_id}
)
Here the parameters (defined in the SQL string as %(name)s and accessed from a dictionary) are inserted at query time, so are not vulnerable to SQL injection and don’t need to be escaped. You can also use %s and pass a tuple/list instead of a dictionary. You can only do this for the parameters, not the structure of the query, so you can’t use it for syntax (like ‘SELECT’, ‘OR’ etc.) or table/database names.
Not that I’ve used as_dict=True on the SQL, because then it returns what get_all returns (a list of frappe._dict objects).
Using the abstracted Frappe calls should be more robust as it is the published API, and doesn’t depend on underlying details of the DB implementation (e.g. MariaDB vs PostgreSQL).
Thank you for the work method that you provided to me, that I needed to get the total salary based on the date in the leave Application(from date, to date), I saw that it was called by complex SQL, so I will use what he gave me.