Merge remote-tracking branch 'frappe/develop' into enlarge-item-image-website

This commit is contained in:
Scheercuzy 2017-01-03 16:03:43 +06:30
commit 7c161cfff2
15 changed files with 101 additions and 63 deletions

View File

@ -2,7 +2,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe import frappe
__version__ = '7.2.3' __version__ = '7.2.6'
def get_default_company(user=None): def get_default_company(user=None):
'''Get default company for user''' '''Get default company for user'''

View File

@ -9,11 +9,13 @@
"doctype": "DocType", "doctype": "DocType",
"document_type": "", "document_type": "",
"editable_grid": 1, "editable_grid": 1,
"engine": "InnoDB",
"fields": [ "fields": [
{ {
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0,
"fieldname": "account", "fieldname": "account",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0, "hidden": 0,
@ -30,6 +32,7 @@
"print_hide": 0, "print_hide": 0,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0, "report_hide": 0,
"reqd": 1, "reqd": 1,
"search_index": 0, "search_index": 0,
@ -40,6 +43,7 @@
"allow_on_submit": 0, "allow_on_submit": 0,
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0,
"fieldname": "budget_amount", "fieldname": "budget_amount",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0, "hidden": 0,
@ -50,11 +54,13 @@
"label": "Budget Amount", "label": "Budget Amount",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,
"options": "Company:company:default_currency",
"permlevel": 0, "permlevel": 0,
"precision": "", "precision": "",
"print_hide": 0, "print_hide": 0,
"print_hide_if_no_value": 0, "print_hide_if_no_value": 0,
"read_only": 0, "read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0, "report_hide": 0,
"reqd": 1, "reqd": 1,
"search_index": 0, "search_index": 0,
@ -72,7 +78,7 @@
"issingle": 0, "issingle": 0,
"istable": 1, "istable": 1,
"max_attachments": 0, "max_attachments": 0,
"modified": "2016-07-11 03:27:58.705376", "modified": "2017-01-02 17:02:53.339420",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Budget Account", "name": "Budget Account",

View File

@ -326,10 +326,12 @@ class JournalEntry(AccountsController):
if d.account_currency == self.company_currency: if d.account_currency == self.company_currency:
d.exchange_rate = 1 d.exchange_rate = 1
elif not d.exchange_rate or d.exchange_rate == 1 or \ elif not d.exchange_rate or d.exchange_rate == 1 or \
(d.reference_type in ("Sales Invoice", "Purchase Invoice") and d.reference_name and d.posting_date): (d.reference_type in ("Sales Invoice", "Purchase Invoice")
and d.reference_name and self.posting_date):
# Modified to include the posting date for which to retreive the exchange rate # Modified to include the posting date for which to retreive the exchange rate
d.exchange_rate = get_exchange_rate(self.posting_date, d.account, d.account_currency, self.company, d.exchange_rate = get_exchange_rate(self.posting_date, d.account, d.account_currency,
d.reference_type, d.reference_name, d.debit, d.credit, d.exchange_rate) self.company, d.reference_type, d.reference_name, d.debit, d.credit, d.exchange_rate)
if not d.exchange_rate: if not d.exchange_rate:
frappe.throw(_("Row {0}: Exchange Rate is mandatory").format(d.idx)) frappe.throw(_("Row {0}: Exchange Rate is mandatory").format(d.idx))
@ -651,7 +653,8 @@ def get_payment_entry(ref_doc, args):
if args.get("party_account"): if args.get("party_account"):
# Modified to include the posting date for which the exchange rate is required. # Modified to include the posting date for which the exchange rate is required.
# Assumed to be the posting date in the reference document # Assumed to be the posting date in the reference document
exchange_rate = get_exchange_rate(ref_doc.posting_date, args.get("party_account"), args.get("party_account_currency"), exchange_rate = get_exchange_rate(ref_doc.get("posting_date") or ref_doc.get("transaction_date"),
args.get("party_account"), args.get("party_account_currency"),
ref_doc.company, ref_doc.doctype, ref_doc.name) ref_doc.company, ref_doc.doctype, ref_doc.name)
je = frappe.new_doc("Journal Entry") je = frappe.new_doc("Journal Entry")
@ -686,7 +689,8 @@ def get_payment_entry(ref_doc, args):
bank_row.update(bank_account) bank_row.update(bank_account)
# Modified to include the posting date for which the exchange rate is required. # Modified to include the posting date for which the exchange rate is required.
# Assumed to be the posting date of the reference date # Assumed to be the posting date of the reference date
bank_row.exchange_rate = get_exchange_rate(ref_doc.posting_date, bank_account["account"], bank_row.exchange_rate = get_exchange_rate(ref_doc.get("posting_date")
or ref_doc.get("transaction_date"), bank_account["account"],
bank_account["account_currency"], ref_doc.company) bank_account["account_currency"], ref_doc.company)
bank_row.cost_center = cost_center bank_row.cost_center = cost_center

View File

@ -110,10 +110,14 @@ def apply_pricing_rule(args):
item_list = args.get("items") item_list = args.get("items")
args.pop("items") args.pop("items")
set_serial_nos_based_on_fifo = frappe.db.get_single_value("Stock Settings",
"automatically_set_serial_nos_based_on_fifo")
for item in item_list: for item in item_list:
args_copy = copy.deepcopy(args) args_copy = copy.deepcopy(args)
args_copy.update(item) args_copy.update(item)
out.append(get_pricing_rule_for_item(args_copy)) out.append(get_pricing_rule_for_item(args_copy))
if set_serial_nos_based_on_fifo:
out.append(get_serial_no_for_item(args_copy)) out.append(get_serial_no_for_item(args_copy))
return out return out

View File

@ -217,7 +217,7 @@ class LeaveApplication(Document):
def validate_attendance(self): def validate_attendance(self):
attendance = frappe.db.sql("""select name from `tabAttendance` where employee = %s and (att_date between %s and %s) attendance = frappe.db.sql("""select name from `tabAttendance` where employee = %s and (att_date between %s and %s)
and docstatus = 1""", and status = "Present" and docstatus = 1""",
(self.employee, self.from_date, self.to_date)) (self.employee, self.from_date, self.to_date))
if attendance: if attendance:
frappe.throw(_("Attendance for employee {0} is already marked for this day").format(self.employee), frappe.throw(_("Attendance for employee {0} is already marked for this day").format(self.employee),

View File

@ -3,7 +3,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe import frappe
from frappe.utils import cint, flt, nowdate, add_days, getdate from frappe.utils import cint, flt, nowdate, add_days, getdate, fmt_money
from frappe import _ from frappe import _
from erpnext.accounts.utils import get_fiscal_year from erpnext.accounts.utils import get_fiscal_year
@ -103,18 +103,24 @@ class ProcessPayroll(Document):
"posting_date": self.posting_date "posting_date": self.posting_date
}) })
ss.insert() ss.insert()
ss_list.append(ss.name) ss_dict = {}
ss_dict["Employee Name"] = ss.employee_name
ss_dict["Total Pay"] = fmt_money(ss.rounded_total,currency = frappe.defaults.get_global_default("currency"))
ss_dict["Salary Slip"] = self.format_as_links(ss.name)[0]
ss_list.append(ss_dict)
return self.create_log(ss_list) return self.create_log(ss_list)
def create_log(self, ss_list): def create_log(self, ss_list):
if not ss_list:
log = "<p>" + _("No employee for the above selected criteria OR salary slip already created") + "</p>" log = "<p>" + _("No employee for the above selected criteria OR salary slip already created") + "</p>"
if ss_list: else:
log = "<b>" + _("Salary Slip Created") + "</b>\ log = frappe.render_template("templates/includes/salary_slip_log.html",
<br><br>%s" % '<br>'.join(self.format_as_links(ss_list)) dict(ss_list=ss_list,
keys=sorted(ss_list[0].keys()),
title=_('Created Salary Slips')))
return log return log
def get_sal_slip_list(self, ss_status, as_dict=False): def get_sal_slip_list(self, ss_status, as_dict=False):
""" """
Returns list of salary slips based on selected criteria Returns list of salary slips based on selected criteria
@ -136,44 +142,50 @@ class ProcessPayroll(Document):
self.check_permission('write') self.check_permission('write')
ss_list = self.get_sal_slip_list(ss_status=0) ss_list = self.get_sal_slip_list(ss_status=0)
submitted_ss = []
not_submitted_ss = [] not_submitted_ss = []
for ss in ss_list: for ss in ss_list:
ss_obj = frappe.get_doc("Salary Slip",ss[0]) ss_obj = frappe.get_doc("Salary Slip",ss[0])
ss_dict = {}
ss_dict["Employee Name"] = ss_obj.employee_name
ss_dict["Total Pay"] = fmt_money(ss_obj.rounded_total,currency = frappe.defaults.get_global_default("currency"))
ss_dict["Salary Slip"] = self.format_as_links(ss_obj.name)[0]
if ss_obj.net_pay<0: if ss_obj.net_pay<0:
not_submitted_ss.append(ss[0]) not_submitted_ss.append(ss_dict)
else: else:
try: try:
ss_obj.submit() ss_obj.submit()
submitted_ss.append(ss_dict)
except frappe.ValidationError: except frappe.ValidationError:
not_submitted_ss.append(ss[0]) not_submitted_ss.append(ss_dict)
return self.create_submit_log(ss_list, not_submitted_ss) return self.create_submit_log(submitted_ss, not_submitted_ss)
def create_submit_log(self, all_ss, not_submitted_ss): def create_submit_log(self, submitted_ss, not_submitted_ss):
log = '' log = ''
if not all_ss: if not submitted_ss and not not_submitted_ss:
log = "No salary slip found to submit for the above selected criteria" log = "No salary slip found to submit for the above selected criteria"
else:
all_ss = [d[0] for d in all_ss]
submitted_ss = self.format_as_links(list(set(all_ss) - set(not_submitted_ss)))
if submitted_ss: if submitted_ss:
log = """ log = frappe.render_template("templates/includes/salary_slip_log.html",
<b>Salary Slips Submitted:</b> <br><br>%s dict(ss_list=submitted_ss,
""" % ('<br>'.join(submitted_ss)) keys=sorted(submitted_ss[0].keys()),
title=_('Submitted Salary Slips')))
if not_submitted_ss: if not_submitted_ss:
log += frappe.render_template(self.get_log_template(),
dict(ss_list=not_submitted_ss,
keys=sorted(not_submitted_ss[0].keys()),
title=_('Not Submitted Salary Slips')))
log += """ log += """
<b>Not Submitted Salary Slips: </b>\
<br><br> %s <br><br> \
Possible reasons: <br>\ Possible reasons: <br>\
1. Net pay is less than 0 <br> 1. Net pay is less than 0 <br>
2. Company email id specified in employee master is not valid. <br> \ 2. Company email id specified in employee master is not valid. <br>
"""% ('<br>'.join(not_submitted_ss)) """
return log return log
def format_as_links(self, ss_list): def format_as_links(self, salary_slip):
return ['<a href="#Form/Salary Slip/{0}">{0}</a>'.format(s) for s in ss_list] return ['<a href="#Form/Salary Slip/{0}">{0}</a>'.format(salary_slip)]
def get_total_salary(self): def get_total_salary(self):

View File

@ -4,19 +4,18 @@
frappe.query_reports["Monthly Salary Register"] = { frappe.query_reports["Monthly Salary Register"] = {
"filters": [ "filters": [
{ {
"fieldname":"month", "fieldname":"from_date",
"label": __("Month"), "label": __("From"),
"fieldtype": "Select", "fieldtype": "Date",
"options": "\nJan\nFeb\nMar\nApr\nMay\nJun\nJul\nAug\nSep\nOct\nNov\nDec", "default": frappe.datetime.add_months(frappe.datetime.get_today(), -1),
"default": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "reqd": 1
"Dec"][frappe.datetime.str_to_obj(frappe.datetime.get_today()).getMonth()],
}, },
{ {
"fieldname":"fiscal_year", "fieldname":"to_date",
"label": __("Fiscal Year"), "label": __("To"),
"fieldtype": "Link", "fieldtype": "Date",
"options": "Fiscal Year", "default": frappe.datetime.get_today(),
"default": sys_defaults.fiscal_year, "reqd": 1
}, },
{ {
"fieldname":"employee", "fieldname":"employee",

View File

@ -18,7 +18,7 @@ def execute(filters=None):
data = [] data = []
for ss in salary_slips: for ss in salary_slips:
row = [ss.name, ss.employee, ss.employee_name, ss.branch, ss.department, ss.designation, row = [ss.name, ss.employee, ss.employee_name, ss.branch, ss.department, ss.designation,
ss.company, ss.month, ss.leave_withut_pay, ss.payment_days] ss.company, ss.start_date, ss.end_date, ss.leave_withut_pay, ss.payment_days]
for e in earning_types: for e in earning_types:
row.append(ss_earning_map.get(ss.name, {}).get(e)) row.append(ss_earning_map.get(ss.name, {}).get(e))
@ -38,7 +38,7 @@ def get_columns(salary_slips):
columns = [ columns = [
_("Salary Slip ID") + ":Link/Salary Slip:150",_("Employee") + ":Link/Employee:120", _("Employee Name") + "::140", _("Branch") + ":Link/Branch:120", _("Salary Slip ID") + ":Link/Salary Slip:150",_("Employee") + ":Link/Employee:120", _("Employee Name") + "::140", _("Branch") + ":Link/Branch:120",
_("Department") + ":Link/Department:120", _("Designation") + ":Link/Designation:120", _("Department") + ":Link/Department:120", _("Designation") + ":Link/Designation:120",
_("Company") + ":Link/Company:120", _("Month") + "::80", _("Leave Without Pay") + ":Float:130", _("Company") + ":Link/Company:120", _("Start Date") + "::80", _("End Date") + "::80", _("Leave Without Pay") + ":Float:130",
_("Payment Days") + ":Float:120" _("Payment Days") + ":Float:120"
] ]
@ -60,23 +60,18 @@ def get_columns(salary_slips):
def get_salary_slips(filters): def get_salary_slips(filters):
conditions, filters = get_conditions(filters) conditions, filters = get_conditions(filters)
salary_slips = frappe.db.sql("""select * from `tabSalary Slip` where docstatus = 1 %s salary_slips = frappe.db.sql("""select * from `tabSalary Slip` where docstatus = 1 %s
order by employee, month""" % conditions, filters, as_dict=1) order by employee""" % conditions, filters, as_dict=1)
if not salary_slips: if not salary_slips:
frappe.throw(_("No salary slip found for month {0} and year {1}").format( frappe.throw(_("No salary slip found between {0} and {1}").format(
filters.get("month"), filters.get("fiscal_year"))) filters.get("from_date"), filters.get("to_date")))
return salary_slips return salary_slips
def get_conditions(filters): def get_conditions(filters):
conditions = "" conditions = ""
if filters.get("month"): if filters.get("from_date"): conditions += " and start_date >= %(from_date)s"
month = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", if filters.get("to_date"): conditions += " and end_date <= %(to_date)s"
"Dec"].index(filters["month"]) + 1
filters["month"] = month
conditions += " and month = %(month)s"
if filters.get("fiscal_year"): conditions += " and fiscal_year = %(fiscal_year)s"
if filters.get("company"): conditions += " and company = %(company)s" if filters.get("company"): conditions += " and company = %(company)s"
if filters.get("employee"): conditions += " and employee = %(employee)s" if filters.get("employee"): conditions += " and employee = %(employee)s"

View File

@ -349,7 +349,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
me.frm.set_value("letter_head", company_doc.default_letter_head); me.frm.set_value("letter_head", company_doc.default_letter_head);
} }
} }
if (company_doc.default_terms && me.frm.doc.doctype != "Purchase Invoice") { if (company_doc.default_terms && me.frm.doc.doctype != "Purchase Invoice" && frappe.meta.has_field(me.frm.doc.doctype, "tc_name")) {
me.frm.set_value("tc_name", company_doc.default_terms); me.frm.set_value("tc_name", company_doc.default_terms);
} }

View File

@ -28,7 +28,6 @@ class ItemGroup(NestedSet, WebsiteGenerator):
def on_update(self): def on_update(self):
NestedSet.on_update(self) NestedSet.on_update(self)
WebsiteGenerator.on_update(self)
invalidate_cache_for(self) invalidate_cache_for(self)
self.validate_name_with_item() self.validate_name_with_item()
self.validate_one_root() self.validate_one_root()

View File

@ -77,7 +77,7 @@ def send_via_gateway(arg):
for d in arg.get('receiver_list'): for d in arg.get('receiver_list'):
args[ss.receiver_parameter] = d args[ss.receiver_parameter] = d
status = send_request(ss.sms_gateway_url, args) status = send_request(ss.sms_gateway_url, args)
if status > 200 and status < 300: if status >= 200 and status < 300:
success_list.append(d) success_list.append(d)
if len(success_list) > 0: if len(success_list) > 0:

View File

@ -9,6 +9,7 @@ from frappe.utils.jinja import validate_template
class TermsandConditions(Document): class TermsandConditions(Document):
def validate(self): def validate(self):
if self.terms:
validate_template(self.terms) validate_template(self.terms)
@frappe.whitelist() @frappe.whitelist()

View File

@ -93,7 +93,6 @@ class Item(WebsiteGenerator):
where parentfield='website_item_groups' and parenttype='Item' and parent=%s""", self.name) where parentfield='website_item_groups' and parenttype='Item' and parent=%s""", self.name)
def on_update(self): def on_update(self):
super(Item, self).on_update()
invalidate_cache_for_item(self) invalidate_cache_for_item(self)
self.validate_name_with_item_group() self.validate_name_with_item_group()
self.update_item_price() self.update_item_price()

View File

@ -9,7 +9,7 @@ cur_frm.fields_dict['item_code'].get_query = function(doc, cdt, cdn) {
return { return {
query: "erpnext.stock.doctype.quality_inspection.quality_inspection.item_query", query: "erpnext.stock.doctype.quality_inspection.quality_inspection.item_query",
filters: { filters: {
"from": doc.reference_type, "from": doc.reference_type + " Item",
"parent": doc.reference_name "parent": doc.reference_name
} }
} }

View File

@ -0,0 +1,19 @@
<table class='table table-bordered'>
<caption>{{title}}</caption>
<thead>
<tr>
{% for key in keys %}
<th {% if key == "Total Pay"%} style="text-align: right;" {% endif %}> {{ key }} </th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for ss_dict in ss_list %}
<tr>
{% for key, value in ss_dict.iteritems()|sort %}
<td {% if key == "Total Pay"%} align = "right" {% endif %}> {{value}} </td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>