From 9f0d6253003a06c6caba9fbdb9f05940156d4839 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Mon, 14 Apr 2014 19:20:45 +0530 Subject: [PATCH] update translation strings #1403 --- .../bank_reconciliation.py | 28 +-- .../doctype/cost_center/cost_center.py | 46 ++--- .../doctype/fiscal_year/fiscal_year.py | 15 +- .../journal_voucher/journal_voucher.py | 40 ++--- .../payment_to_invoice_matching_tool.py | 92 +++++----- .../doctype/pos_setting/pos_setting.py | 30 ++-- .../purchase_invoice/purchase_invoice.py | 40 ++--- .../doctype/sales_invoice/sales_invoice.py | 65 +++---- .../doctype/shipping_rule/shipping_rule.py | 36 ++-- erpnext/accounts/party.py | 2 +- erpnext/accounts/utils.py | 19 +- .../doctype/purchase_order/purchase_order.py | 12 +- erpnext/buying/doctype/supplier/supplier.py | 4 +- erpnext/controllers/accounts_controller.py | 3 +- erpnext/controllers/buying_controller.py | 130 +++++++------- erpnext/controllers/selling_controller.py | 14 +- erpnext/controllers/status_updater.py | 30 +--- erpnext/controllers/stock_controller.py | 8 +- erpnext/controllers/trends.py | 94 +++++----- erpnext/hr/doctype/appraisal/appraisal.py | 31 ++-- .../appraisal_template/appraisal_template.py | 6 +- erpnext/hr/doctype/attendance/attendance.py | 41 ++--- .../hr/doctype/expense_claim/expense_claim.py | 15 +- .../hr/doctype/holiday_list/holiday_list.py | 21 ++- .../leave_allocation/leave_allocation.py | 67 +++---- .../leave_application/leave_application.py | 169 +++++++++--------- .../leave_control_panel.py | 12 +- .../doctype/salary_manager/salary_manager.py | 107 ++++++----- erpnext/hr/doctype/salary_slip/salary_slip.py | 131 +++++++------- .../salary_structure/salary_structure.py | 37 ++-- .../upload_attendance/upload_attendance.py | 52 +++--- erpnext/hr/utils.py | 7 +- erpnext/manufacturing/doctype/bom/bom.py | 49 ++--- .../bom_replace_tool/bom_replace_tool.py | 22 +-- .../production_order/production_order.py | 72 ++++---- .../production_planning_tool.py | 131 +++++++------- erpnext/projects/doctype/project/project.py | 19 +- erpnext/projects/doctype/task/task.py | 32 ++-- erpnext/projects/doctype/time_log/time_log.py | 39 ++-- .../doctype/time_log_batch/time_log_batch.py | 3 +- .../installation_note/installation_note.py | 20 +-- erpnext/selling/doctype/lead/lead.py | 57 +++--- .../doctype/opportunity/opportunity.py | 65 ++++--- .../selling/doctype/quotation/quotation.py | 66 ++++--- .../selling/doctype/sales_bom/sales_bom.py | 21 +-- .../doctype/sales_order/sales_order.py | 68 ++++--- .../customers_not_buying_since_long_time.py | 47 ++--- ..._person_target_variance_item_group_wise.py | 42 +++-- .../authorization_control.py | 70 ++++---- .../authorization_rule/authorization_rule.py | 72 ++------ .../backup_manager/backup_googledrive.py | 31 ++-- erpnext/setup/doctype/company/company.py | 83 +++++---- .../currency_exchange/currency_exchange.py | 10 +- .../doctype/customer_group/customer_group.py | 35 +--- .../global_defaults/global_defaults.py | 18 +- .../setup/doctype/item_group/item_group.py | 3 +- .../jobs_email_settings.py | 7 +- .../notification_control.py | 5 +- erpnext/setup/doctype/territory/territory.py | 8 +- erpnext/setup/utils.py | 20 +-- .../doctype/delivery_note/delivery_note.py | 44 ++--- erpnext/stock/doctype/item/item.py | 49 ++--- .../landed_cost_wizard/landed_cost_wizard.py | 40 ++--- .../material_request/material_request.py | 2 +- .../doctype/packing_slip/packing_slip.py | 58 +++--- .../purchase_receipt/purchase_receipt.py | 20 +-- erpnext/stock/doctype/serial_no/serial_no.py | 124 ++++++------- .../stock/doctype/stock_entry/stock_entry.py | 77 +++----- erpnext/stock/stock_ledger.py | 16 +- erpnext/stock/utils.py | 15 +- 70 files changed, 1325 insertions(+), 1639 deletions(-) diff --git a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py index dc7d57becb..7d6ce34fb4 100644 --- a/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py +++ b/erpnext/accounts/doctype/bank_reconciliation/bank_reconciliation.py @@ -12,17 +12,17 @@ class BankReconciliation(Document): if not (self.bank_account and self.from_date and self.to_date): msgprint("Bank Account, From Date and To Date are Mandatory") return - - dl = frappe.db.sql("""select t1.name, t1.cheque_no, t1.cheque_date, t2.debit, - t2.credit, t1.posting_date, t2.against_account - from - `tabJournal Voucher` t1, `tabJournal Voucher Detail` t2 - where - t2.parent = t1.name and t2.account = %s - and (clearance_date is null or clearance_date = '0000-00-00' or clearance_date = '') - and t1.posting_date >= %s and t1.posting_date <= %s and t1.docstatus=1""", + + dl = frappe.db.sql("""select t1.name, t1.cheque_no, t1.cheque_date, t2.debit, + t2.credit, t1.posting_date, t2.against_account + from + `tabJournal Voucher` t1, `tabJournal Voucher Detail` t2 + where + t2.parent = t1.name and t2.account = %s + and (clearance_date is null or clearance_date = '0000-00-00' or clearance_date = '') + and t1.posting_date >= %s and t1.posting_date <= %s and t1.docstatus=1""", (self.bank_account, self.from_date, self.to_date)) - + self.set('entries', []) self.total_amount = 0.0 @@ -43,13 +43,13 @@ class BankReconciliation(Document): if d.clearance_date: if d.cheque_date and getdate(d.clearance_date) < getdate(d.cheque_date): frappe.throw("Clearance Date can not be before Cheque Date (Row #%s)" % d.idx) - + frappe.db.set_value("Journal Voucher", d.voucher_id, "clearance_date", d.clearance_date) - frappe.db.sql("""update `tabJournal Voucher` set clearance_date = %s, modified = %s + frappe.db.sql("""update `tabJournal Voucher` set clearance_date = %s, modified = %s where name=%s""", (d.clearance_date, nowdate(), d.voucher_id)) vouchers.append(d.voucher_id) if vouchers: - msgprint("Clearance Date updated in %s" % ", ".join(vouchers)) + msgprint("Clearance Date updated in: {0}".format(", ".join(vouchers))) else: - msgprint(_("Clearance Date not mentioned")) \ No newline at end of file + msgprint(_("Clearance Date not mentioned")) diff --git a/erpnext/accounts/doctype/cost_center/cost_center.py b/erpnext/accounts/doctype/cost_center/cost_center.py index d79bbcc5cd..71ebe6c745 100644 --- a/erpnext/accounts/doctype/cost_center/cost_center.py +++ b/erpnext/accounts/doctype/cost_center/cost_center.py @@ -10,33 +10,33 @@ from frappe.utils.nestedset import NestedSet class CostCenter(NestedSet): nsm_parent_field = 'parent_cost_center' - + def autoname(self): self.name = self.cost_center_name.strip() + ' - ' + \ frappe.db.get_value("Company", self.company, "abbr") - + def validate_mandatory(self): if not self.group_or_ledger: - msgprint("Please select Group or Ledger value", raise_exception=1) - + msgprint(_("Please select Group or Ledger value"), raise_exception=1) + if self.cost_center_name != self.company and not self.parent_cost_center: - msgprint("Please enter parent cost center", raise_exception=1) + msgprint(_("Please enter parent cost center"), raise_exception=1) elif self.cost_center_name == self.company and self.parent_cost_center: msgprint(_("Root cannot have a parent cost center"), raise_exception=1) - + def convert_group_to_ledger(self): if self.check_if_child_exists(): - msgprint("Cost Center: %s has existing child. You can not convert this cost center to ledger" % (self.name), raise_exception=1) + msgprint(_("Cannot convert Cost Center to ledger as it has child nodes"), raise_exception=1) elif self.check_gle_exists(): - msgprint("Cost Center with existing transaction can not be converted to ledger.", raise_exception=1) + msgprint(_("Cost Center with existing transactions can not be converted to ledger"), raise_exception=1) else: self.group_or_ledger = 'Ledger' self.save() return 1 - + def convert_ledger_to_group(self): if self.check_gle_exists(): - msgprint("Cost Center with existing transaction can not be converted to group.", raise_exception=1) + msgprint(_("Cost Center with existing transactions can not be converted to group"), raise_exception=1) else: self.group_or_ledger = 'Group' self.save() @@ -44,7 +44,7 @@ class CostCenter(NestedSet): def check_gle_exists(self): return frappe.db.get_value("GL Entry", {"cost_center": self.name}) - + def check_if_child_exists(self): return frappe.db.sql("select name from `tabCost Center` where \ parent_cost_center = %s and docstatus != 2", self.name) @@ -53,11 +53,11 @@ class CostCenter(NestedSet): check_acc_list = [] for d in self.get('budget_details'): if self.group_or_ledger=="Group": - msgprint("Budget cannot be set for Group Cost Centers", raise_exception=1) - + msgprint(_("Budget cannot be set for Group Cost Centers"), raise_exception=1) + if [d.account, d.fiscal_year] in check_acc_list: - msgprint("Account " + d.account + "has been entered more than once for fiscal year " + d.fiscal_year, raise_exception=1) - else: + msgprint(_("Account {0} has been entered more than once for fiscal year {1}").format(d.account, d.fiscal_year), raise_exception=1) + else: check_acc_list.append([d.account, d.fiscal_year]) def validate(self): @@ -65,25 +65,25 @@ class CostCenter(NestedSet): Cost Center name must be unique """ if (self.get("__islocal") or not self.name) and frappe.db.sql("select name from `tabCost Center` where cost_center_name = %s and company=%s", (self.cost_center_name, self.company)): - msgprint("Cost Center Name already exists, please rename", raise_exception=1) - + msgprint(_("Cost Center Name already exists"), raise_exception=1) + self.validate_mandatory() self.validate_budget_details() - + def before_rename(self, olddn, newdn, merge=False): # Add company abbr if not provided from erpnext.setup.doctype.company.company import get_name_with_abbr new_cost_center = get_name_with_abbr(newdn, self.company) - + # Validate properties before merging super(CostCenter, self).before_rename(olddn, new_cost_center, merge, "group_or_ledger") - + return new_cost_center - + def after_rename(self, olddn, newdn, merge=False): if not merge: - frappe.db.set_value("Cost Center", newdn, "cost_center_name", + frappe.db.set_value("Cost Center", newdn, "cost_center_name", " - ".join(newdn.split(" - ")[:-1])) else: super(CostCenter, self).after_rename(olddn, newdn, merge) - + diff --git a/erpnext/accounts/doctype/fiscal_year/fiscal_year.py b/erpnext/accounts/doctype/fiscal_year/fiscal_year.py index 6e72c9ad79..14461ff633 100644 --- a/erpnext/accounts/doctype/fiscal_year/fiscal_year.py +++ b/erpnext/accounts/doctype/fiscal_year/fiscal_year.py @@ -9,19 +9,18 @@ from frappe.utils import getdate from frappe.model.document import Document class FiscalYear(Document): - + def set_as_default(self): frappe.db.set_value("Global Defaults", None, "current_fiscal_year", self.name) frappe.get_doc("Global Defaults").on_update() - + # clear cache frappe.clear_cache() - - msgprint(self.name + _(""" is now the default Fiscal Year. \ - Please refresh your browser for the change to take effect.""")) + + msgprint(_("{0} is now the default Fiscal Year. Please refresh your browser for the change to take effect.").format(self.name)) def validate(self): - year_start_end_dates = frappe.db.sql("""select year_start_date, year_end_date + year_start_end_dates = frappe.db.sql("""select year_start_date, year_end_date from `tabFiscal Year` where name=%s""", (self.name)) if year_start_end_dates: @@ -36,10 +35,10 @@ class FiscalYear(Document): if (getdate(self.year_end_date) - getdate(self.year_start_date)).days > 366: frappe.throw(_("Year Start Date and Year End Date are not within Fiscal Year.")) - year_start_end_dates = frappe.db.sql("""select name, year_start_date, year_end_date + year_start_end_dates = frappe.db.sql("""select name, year_start_date, year_end_date from `tabFiscal Year` where name!=%s""", (self.name)) for fiscal_year, ysd, yed in year_start_end_dates: if (getdate(self.year_start_date) == ysd and getdate(self.year_end_date) == yed) \ and (not frappe.flags.in_test): - frappe.throw(_("Year Start Date and Year End Date are already set in Fiscal Year: ") + fiscal_year) \ No newline at end of file + frappe.throw(_("Year Start Date and Year End Date are already set in Fiscal Year: ") + fiscal_year) diff --git a/erpnext/accounts/doctype/journal_voucher/journal_voucher.py b/erpnext/accounts/doctype/journal_voucher/journal_voucher.py index f11589bdf1..b586a2c57e 100644 --- a/erpnext/accounts/doctype/journal_voucher/journal_voucher.py +++ b/erpnext/accounts/doctype/journal_voucher/journal_voucher.py @@ -57,17 +57,16 @@ class JournalVoucher(AccountsController): def validate_debit_credit(self): for d in self.get('entries'): if d.debit and d.credit: - msgprint("You cannot credit and debit same account at the same time.", - raise_exception=1) + msgprint(_("You cannot credit and debit same account at the same time."), raise_exception=1) def validate_cheque_info(self): if self.voucher_type in ['Bank Voucher']: if not self.cheque_no or not self.cheque_date: - msgprint("Reference No & Reference Date is required for %s" % - self.voucher_type, raise_exception=1) + msgprint(_("Reference No & Reference Date is required for {0}").format(self.voucher_type), + raise_exception=1) if self.cheque_date and not self.cheque_no: - msgprint("Reference No is mandatory if you entered Reference Date", raise_exception=1) + msgprint(_("Reference No is mandatory if you entered Reference Date"), raise_exception=1) def validate_entries_for_advance(self): for d in self.get('entries'): @@ -76,19 +75,17 @@ class JournalVoucher(AccountsController): master_type = frappe.db.get_value("Account", d.account, "master_type") if (master_type == 'Customer' and flt(d.credit) > 0) or \ (master_type == 'Supplier' and flt(d.debit) > 0): - msgprint("Message: Please check Is Advance as 'Yes' against \ - Account %s if this is an advance entry." % d.account) + msgprint(_("Please check 'Is Advance' against Account {0} if this is an advance entry.").format(d.account)) def validate_against_jv(self): for d in self.get('entries'): if d.against_jv: if d.against_jv == self.name: - msgprint("You can not enter current voucher in 'Against JV' column", - raise_exception=1) + msgprint(_("You can not enter current voucher in 'Against Journal Voucher' column"), raise_exception=1) elif not frappe.db.sql("""select name from `tabJournal Voucher Detail` where account = %s and docstatus = 1 and parent = %s""", (d.account, d.against_jv)): - msgprint("Against JV: %s is not valid." % d.against_jv, raise_exception=1) + msgprint(_("Journal Voucher {0} does not have account {1}.").format(d.against_jv, d.account), raise_exception=1) def set_against_account(self): # Debit = Credit @@ -104,8 +101,8 @@ class JournalVoucher(AccountsController): self.total_credit = credit if abs(self.total_debit-self.total_credit) > 0.001: - msgprint("Debit must be equal to Credit. The difference is %s" % - (self.total_debit-self.total_credit), raise_exception=1) + msgprint(_("Debit must equal Credit. The difference is {0}").format(self.total_debit-self.total_credit), + raise_exception=1) # update against account for d in self.get('entries'): @@ -116,10 +113,9 @@ class JournalVoucher(AccountsController): r = [] if self.cheque_no: if self.cheque_date: - r.append('Via Reference #%s dated %s' % - (self.cheque_no, formatdate(self.cheque_date))) + r.append(_('Reference #{0} dated {1}').fomrat(self.cheque_no, formatdate(self.cheque_date))) else : - msgprint("Please enter Reference date", raise_exception=1) + msgprint(_("Please enter Reference date"), raise_exception=1) for d in self.get('entries'): if d.against_invoice and d.credit: @@ -137,12 +133,12 @@ class JournalVoucher(AccountsController): bill_no[0][1] and formatdate(bill_no[0][1].strftime('%Y-%m-%d')) or '')) if self.user_remark: - r.append("User Remark : %s"%self.user_remark) + r.append(_("Note: {0}").format(self.user_remark)) if r: self.remark = ("\n").join(r) else: - frappe.msgprint("User Remarks is mandatory", raise_exception=1) + frappe.msgprint(_("User Remarks is mandatory"), raise_exception=1) def set_aging_date(self): if self.is_opening != 'Yes': @@ -158,7 +154,7 @@ class JournalVoucher(AccountsController): # If customer/supplier account, aging date is mandatory if exists and not self.aging_date: - msgprint("Aging Date is mandatory for opening entry", raise_exception=1) + msgprint(_("Aging Date is mandatory for opening entry"), raise_exception=1) else: self.aging_date = self.posting_date @@ -195,8 +191,8 @@ class JournalVoucher(AccountsController): credit_days = self.get_credit_days_for(d.account) # Check credit days if credit_days > 0 and not self.get_authorized_user() and cint(date_diff) > credit_days: - msgprint("Credit Not Allowed: Cannot allow a check that is dated \ - more than %s days after the posting date" % credit_days, raise_exception=1) + msgprint(_("Maximum allowed credit is {0} days after posting date").format(credit_days), + raise_exception=1) def get_credit_days_for(self, ac): if not self.credit_days_for.has_key(ac): @@ -272,7 +268,7 @@ class JournalVoucher(AccountsController): def get_balance(self): if not self.get('entries'): - msgprint("Please enter atleast 1 entry in 'GL Entries' table") + msgprint(_("'Entries' cannot be empty"), raise_exception=True) else: flag, self.total_debit, self.total_credit = 0, 0, 0 diff = flt(self.difference, 2) @@ -390,7 +386,7 @@ def get_payment_entry(doc): jv.company = doc.company jv.fiscal_year = doc.fiscal_year - d1 = jv.append("entries") + jv.append("entries") d2 = jv.append("entries") if bank_account: diff --git a/erpnext/accounts/doctype/payment_to_invoice_matching_tool/payment_to_invoice_matching_tool.py b/erpnext/accounts/doctype/payment_to_invoice_matching_tool/payment_to_invoice_matching_tool.py index cff24e14e8..f845138d32 100644 --- a/erpnext/accounts/doctype/payment_to_invoice_matching_tool/payment_to_invoice_matching_tool.py +++ b/erpnext/accounts/doctype/payment_to_invoice_matching_tool/payment_to_invoice_matching_tool.py @@ -12,23 +12,23 @@ from frappe.model.document import Document class PaymenttoInvoiceMatchingTool(Document): def get_voucher_details(self): - total_amount = frappe.db.sql("""select sum(ifnull(debit, 0)) - sum(ifnull(credit, 0)) - from `tabGL Entry` - where voucher_type = %s and voucher_no = %s + total_amount = frappe.db.sql("""select sum(ifnull(debit, 0)) - sum(ifnull(credit, 0)) + from `tabGL Entry` + where voucher_type = %s and voucher_no = %s and account = %s""", (self.voucher_type, self.voucher_no, self.account)) - + total_amount = total_amount and flt(total_amount[0][0]) or 0 reconciled_payment = frappe.db.sql(""" - select abs(sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))) from `tabGL Entry` where + select abs(sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))) from `tabGL Entry` where against_voucher = %s and voucher_no != %s and account = %s""", (self.voucher_no, self.voucher_no, self.account)) - + reconciled_payment = reconciled_payment and flt(reconciled_payment[0][0]) or 0 ret = { - 'total_amount': total_amount, + 'total_amount': total_amount, 'pending_amt_to_reconcile': total_amount - reconciled_payment } - + return ret def get_payment_entries(self): @@ -37,16 +37,16 @@ class PaymenttoInvoiceMatchingTool(Document): Payment entry will be decided based on account type (Dr/Cr) """ - self.set('ir_payment_details', []) + self.set('ir_payment_details', []) gle = self.get_gl_entries() self.create_payment_table(gle) def get_gl_entries(self): self.validate_mandatory() - + cond = self.from_date and " and t1.posting_date >= '" + self.from_date + "'" or "" cond += self.to_date and " and t1.posting_date <= '" + self.to_date + "'"or "" - + if self.amt_greater_than: cond += ' and abs(ifnull(t2.debit, 0) - ifnull(t2.credit, 0)) >= ' + \ self.amt_greater_than @@ -55,13 +55,13 @@ class PaymenttoInvoiceMatchingTool(Document): self.amt_less_than gle = frappe.db.sql(""" - select t1.name as voucher_no, t1.posting_date, t1.total_debit as total_amt, + select t1.name as voucher_no, t1.posting_date, t1.total_debit as total_amt, abs(sum(ifnull(t2.credit, 0)) - sum(ifnull(t2.debit, 0))) as amt_due, t1.remark, t2.against_account, t2.name as voucher_detail_no from `tabJournal Voucher` t1, `tabJournal Voucher Detail` t2 where t1.name = t2.parent and t1.docstatus = 1 and t2.account = %s - and ifnull(t2.against_voucher, '')='' and ifnull(t2.against_invoice, '')='' - and ifnull(t2.against_jv, '')='' and t1.name != %s %s group by t1.name, t2.name """ % + and ifnull(t2.against_voucher, '')='' and ifnull(t2.against_invoice, '')='' + and ifnull(t2.against_jv, '')='' and t1.name != %s %s group by t1.name, t2.name """ % ('%s', '%s', cond), (self.account, self.voucher_no), as_dict=1) return gle @@ -76,11 +76,11 @@ class PaymenttoInvoiceMatchingTool(Document): ch.against_account = d.get('against_account') ch.remarks = d.get('remark') ch.voucher_detail_no = d.get('voucher_detail_no') - + def validate_mandatory(self): if not self.account: - msgprint("Please select Account first", raise_exception=1) - + msgprint(_("Please select Account first"), raise_exception=1) + def reconcile(self): """ Links booking and payment voucher @@ -88,59 +88,59 @@ class PaymenttoInvoiceMatchingTool(Document): 2. split into multiple rows if partially adjusted, assign against voucher 3. submit payment voucher """ - if not self.voucher_no or not frappe.db.sql("""select name from `tab%s` + if not self.voucher_no or not frappe.db.sql("""select name from `tab%s` where name = %s""" % (self.voucher_type, '%s'), self.voucher_no): frappe.throw(_("Please select valid Voucher No to proceed")) - + lst = [] for d in self.get('ir_payment_details'): if flt(d.amt_to_be_reconciled) > 0: args = { 'voucher_no' : d.voucher_no, - 'voucher_detail_no' : d.voucher_detail_no, - 'against_voucher_type' : self.voucher_type, + 'voucher_detail_no' : d.voucher_detail_no, + 'against_voucher_type' : self.voucher_type, 'against_voucher' : self.voucher_no, - 'account' : self.account, - 'is_advance' : 'No', - # 'dr_or_cr' : self.account_type=='debit' and 'credit' or 'debit', + 'account' : self.account, + 'is_advance' : 'No', + # 'dr_or_cr' : self.account_type=='debit' and 'credit' or 'debit', 'unadjusted_amt' : flt(d.amt_due), 'allocated_amt' : flt(d.amt_to_be_reconciled) } - + lst.append(args) - + if lst: from erpnext.accounts.utils import reconcile_against_document reconcile_against_document(lst) - msgprint("Successfully allocated.") + msgprint(_("Successfully allocated")) else: - msgprint("No amount allocated.", raise_exception=1) + msgprint(_("No amount allocated"), raise_exception=1) def gl_entry_details(doctype, txt, searchfield, start, page_len, filters): from erpnext.controllers.queries import get_match_cond - return frappe.db.sql("""select gle.voucher_no, gle.posting_date, + return frappe.db.sql("""select gle.voucher_no, gle.posting_date, gle.debit, gle.credit from `tabGL Entry` gle - where gle.account = '%(acc)s' + where gle.account = '%(acc)s' and gle.voucher_type = '%(dt)s' - and gle.voucher_no like '%(txt)s' - and (ifnull(gle.against_voucher, '') = '' - or ifnull(gle.against_voucher, '') = gle.voucher_no ) - and (select ifnull(abs(sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))), 0) - from `tabGL Entry` + and gle.voucher_no like '%(txt)s' + and (ifnull(gle.against_voucher, '') = '' + or ifnull(gle.against_voucher, '') = gle.voucher_no ) + and (select ifnull(abs(sum(ifnull(debit, 0)) - sum(ifnull(credit, 0))), 0) + from `tabGL Entry` where account = '%(acc)s' - and against_voucher_type = '%(dt)s' - and against_voucher = gle.voucher_no - and voucher_no != gle.voucher_no) - != abs(ifnull(gle.debit, 0) - ifnull(gle.credit, 0)) - and if(gle.voucher_type='Sales Invoice', ifnull((select is_pos from `tabSales Invoice` + and against_voucher_type = '%(dt)s' + and against_voucher = gle.voucher_no + and voucher_no != gle.voucher_no) + != abs(ifnull(gle.debit, 0) - ifnull(gle.credit, 0)) + and if(gle.voucher_type='Sales Invoice', ifnull((select is_pos from `tabSales Invoice` where name=gle.voucher_no), 0), 0)=0 %(mcond)s - ORDER BY gle.posting_date desc, gle.voucher_no desc + ORDER BY gle.posting_date desc, gle.voucher_no desc limit %(start)s, %(page_len)s""" % { - "dt":filters["dt"], - "acc":filters["acc"], - 'mcond':get_match_cond(doctype), - 'txt': "%%%s%%" % txt, - "start": start, + "dt":filters["dt"], + "acc":filters["acc"], + 'mcond':get_match_cond(doctype), + 'txt': "%%%s%%" % txt, + "start": start, "page_len": page_len }) diff --git a/erpnext/accounts/doctype/pos_setting/pos_setting.py b/erpnext/accounts/doctype/pos_setting/pos_setting.py index f7fdd319fe..383400f99e 100755 --- a/erpnext/accounts/doctype/pos_setting/pos_setting.py +++ b/erpnext/accounts/doctype/pos_setting/pos_setting.py @@ -16,18 +16,18 @@ class POSSetting(Document): self.check_for_duplicate() self.validate_expense_account() self.validate_all_link_fields() - + def check_for_duplicate(self): - res = frappe.db.sql("""select name, user from `tabPOS Setting` - where ifnull(user, '') = %s and name != %s and company = %s""", + res = frappe.db.sql("""select name, user from `tabPOS Setting` + where ifnull(user, '') = %s and name != %s and company = %s""", (self.user, self.name, self.company)) if res: if res[0][1]: - msgprint("POS Setting '%s' already created for user: '%s' and company: '%s'" % - (res[0][0], res[0][1], self.company), raise_exception=1) + msgprint(_("POS Setting {0} already created for user: {1} and company {2}").format(res[0][0], + res[0][1], self.company), raise_exception=1) else: - msgprint("Global POS Setting already created - %s for this company: '%s'" % - (res[0][0], self.company), raise_exception=1) + msgprint(_("Global POS Setting {0} already created for company {1}").format(res[0][0], + self.company), raise_exception=1) def validate_expense_account(self): if cint(frappe.defaults.get_global_default("auto_accounting_for_stock")) \ @@ -35,13 +35,13 @@ class POSSetting(Document): msgprint(_("Expense Account is mandatory"), raise_exception=1) def validate_all_link_fields(self): - accounts = {"Account": [self.cash_bank_account, self.income_account, - self.expense_account], "Cost Center": [self.cost_center], + accounts = {"Account": [self.cash_bank_account, self.income_account, + self.expense_account], "Cost Center": [self.cost_center], "Warehouse": [self.warehouse]} - + for link_dt, dn_list in accounts.items(): for link_dn in dn_list: - if link_dn and not frappe.db.exists({"doctype": link_dt, + if link_dn and not frappe.db.exists({"doctype": link_dt, "company": self.company, "name": link_dn}): frappe.throw(link_dn +_(" does not belong to ") + self.company) @@ -53,17 +53,17 @@ class POSSetting(Document): def set_defaults(self, include_current_pos=True): frappe.defaults.clear_default("is_pos") - + if not include_current_pos: condition = " where name != '%s'" % self.name.replace("'", "\'") else: condition = "" - pos_view_users = frappe.db.sql_list("""select user + pos_view_users = frappe.db.sql_list("""select user from `tabPOS Setting` {0}""".format(condition)) - + for user in pos_view_users: if user: frappe.defaults.set_user_default("is_pos", 1, user) else: - frappe.defaults.set_global_default("is_pos", 1) \ No newline at end of file + frappe.defaults.set_global_default("is_pos", 1) diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 8860a78e27..ea74fd61d4 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -6,7 +6,7 @@ import frappe from frappe.utils import cint, cstr, flt, formatdate -from frappe import msgprint, _ +from frappe import msgprint, _, throw from erpnext.setup.utils import get_company_currency import frappe.defaults @@ -73,22 +73,15 @@ class PurchaseInvoice(BuyingController): def check_active_purchase_items(self): for d in self.get('entries'): if d.item_code: # extra condn coz item_code is not mandatory in PV - valid_item = frappe.db.sql("select docstatus,is_purchase_item from tabItem where name = %s",d.item_code) - if valid_item[0][0] == 2: - msgprint("Item : '%s' is Inactive, you can restore it from Trash" %(d.item_code)) - raise Exception - if not valid_item[0][1] == 'Yes': - msgprint("Item : '%s' is not Purchase Item"%(d.item_code)) - raise Exception + if frappe.db.get_value("Item", d.item_code, "is_purchase_item") != 'Yes': + msgprint(_("Item {0} is not Purchase Item").format(d.item_code), raise_exception=True) def check_conversion_rate(self): default_currency = get_company_currency(self.company) if not default_currency: - msgprint('Message: Please enter default currency in Company Master') - raise Exception + throw(_('Please enter default currency in Company Master')) if (self.currency == default_currency and flt(self.conversion_rate) != 1.00) or not self.conversion_rate or (self.currency != default_currency and flt(self.conversion_rate) == 1.00): - msgprint("Message: Please Enter Appropriate Conversion Rate.") - raise Exception + throw(_("Conversion rate cannot be 0 or 1")) def validate_bill_no(self): if self.bill_no and self.bill_no.lower().strip() \ @@ -97,13 +90,12 @@ class PurchaseInvoice(BuyingController): where bill_no = %s and credit_to = %s and docstatus = 1 and name != %s""", (self.bill_no, self.credit_to, self.name)) if b_no and cstr(b_no[0][2]) == cstr(self.is_opening): - msgprint("Please check you have already booked expense against Bill No. %s \ - in Purchase Invoice %s" % (cstr(b_no[0][0]), cstr(b_no[0][1])), - raise_exception=1) + throw(_("Bill No {0} already booked in Purchase Invoice {1}").format(cstr(b_no[0][0]), + cstr(b_no[0][1]))) if not self.remarks and self.bill_date: - self.remarks = (self.remarks or '') + "\n" + ("Against Bill %s dated %s" - % (self.bill_no, formatdate(self.bill_date))) + self.remarks = (self.remarks or '') + "\n" \ + + _("Against Bill %s dated %s").format(self.bill_no, formatdate(self.bill_date)) if not self.remarks: self.remarks = "No Remarks" @@ -130,7 +122,7 @@ class PurchaseInvoice(BuyingController): check_list.append(d.purchase_order) stopped = frappe.db.sql("select name from `tabPurchase Order` where status = 'Stopped' and name = %s", d.purchase_order) if stopped: - msgprint("One cannot do any transaction against 'Purchase Order' : %s, it's status is 'Stopped'" % (d.purhcase_order)) + throw(_("Purchase Order {0} is 'Stopped'").format(d.purchase_order)) raise Exception def validate_with_previous_doc(self): @@ -176,7 +168,7 @@ class PurchaseInvoice(BuyingController): if self.is_opening != 'Yes': self.aging_date = self.posting_date elif not self.aging_date: - msgprint("Aging Date is mandatory for opening entry") + msgprint(_("Ageing date is mandatory for opening entry")) raise Exception def set_against_expense_account(self): @@ -199,8 +191,7 @@ class PurchaseInvoice(BuyingController): against_accounts.append(stock_not_billed_account) elif not item.expense_account: - msgprint(_("Expense account is mandatory for item") + ": " + - (item.item_code or item.item_name), raise_exception=1) + throw(_("Expense account is mandatory for item {0}").format(item.item_code or item.item_name)) elif item.expense_account not in against_accounts: # if no auto_accounting_for_stock or not a stock item @@ -212,19 +203,18 @@ class PurchaseInvoice(BuyingController): if frappe.db.get_value("Buying Settings", None, "po_required") == 'Yes': for d in self.get('entries'): if not d.purchase_order: - msgprint("Purchse Order No. required against item %s"%d.item_code) - raise Exception + throw(_("Purchse Order number required for Item {0}").format(d.item_code)) def pr_required(self): if frappe.db.get_value("Buying Settings", None, "pr_required") == 'Yes': for d in self.get('entries'): if not d.purchase_receipt: - msgprint("Purchase Receipt No. required against item %s"%d.item_code) + throw(_("Purchase Receipt number required for Item {0}").format(d.item_code)) raise Exception def validate_write_off_account(self): if self.write_off_amount and not self.write_off_account: - msgprint("Please enter Write Off Account", raise_exception=1) + throw(_("Please enter Write Off Account")) def check_prev_docstatus(self): for d in self.get('entries'): diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 3b09090bbe..5d42459343 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -6,9 +6,9 @@ import frappe import frappe.defaults from frappe.utils import add_days, cint, cstr, date_diff, flt, getdate, nowdate, \ - get_first_day, get_last_day, comma_and + get_first_day, get_last_day from frappe.model.naming import make_autoname -from frappe import _, msgprint +from frappe import _, msgprint, throw from erpnext.accounts.party import get_party_account, get_due_date from erpnext.controllers.stock_controller import update_gl_entries_after @@ -165,8 +165,7 @@ class SalesInvoice(SellingController): if d.time_log_batch: status = frappe.db.get_value("Time Log Batch", d.time_log_batch, "status") if status!="Submitted": - frappe.msgprint(_("Time Log Batch status must be 'Submitted'") + ":" + d.time_log_batch, - raise_exception=True) + frappe.throw(_("Time Log Batch {0} must be 'Submitted'").format(d.time_log_batch)) def set_pos_fields(self, for_validate=False): """Set retail related fields from pos settings""" @@ -263,10 +262,8 @@ class SalesInvoice(SellingController): where name = %s and (ifnull(end_of_life,'')='' or end_of_life > now())""", d.item_code) acc = frappe.db.sql("""select account_type from `tabAccount` where name = %s and docstatus != 2""", d.income_account) - if not acc: - msgprint("Account: "+d.income_account+" does not exist in the system", raise_exception=True) - elif item and item[0][1] == 'Yes' and not acc[0][0] == 'Fixed Asset': - msgprint("Please select income head with account type 'Fixed Asset' as Item %s is an asset item" % d.item_code, raise_exception=True) + if item and item[0][1] == 'Yes' and not acc[0][0] == 'Fixed Asset': + msgprint(_("Account {0} must be of type 'Fixed Asset' as Item {1} is an Asset Item").format(d.item_code), raise_exception=True) def validate_with_previous_doc(self): super(SalesInvoice, self).validate_with_previous_doc(self.tname, { @@ -302,7 +299,7 @@ class SalesInvoice(SellingController): if self.is_opening != 'Yes': self.aging_date = self.posting_date elif not self.aging_date: - msgprint("Aging Date is mandatory for opening entry") + msgprint(_("Ageing Date is mandatory for opening entry")) raise Exception @@ -327,7 +324,7 @@ class SalesInvoice(SellingController): for d in self.get('entries'): if frappe.db.get_value('Item', d.item_code, 'is_stock_item') == 'Yes' \ and not d.get(i.lower().replace(' ','_')): - msgprint("%s is mandatory for stock item which is not mentioed against item: %s"%(i,d.item_code), raise_exception=1) + msgprint(_("{0} is mandatory for Item {1}").format(i,d.item_code), raise_exception=1) def validate_proj_cust(self): @@ -337,34 +334,32 @@ class SalesInvoice(SellingController): where name = %s and (customer = %s or ifnull(customer,'')='')""", (self.project_name, self.customer)) if not res: - msgprint("Customer - %s does not belong to project - %s. \n\nIf you want to use project for multiple customers then please make customer details blank in that project."%(self.customer,self.project_name)) + msgprint(_("Customer {0} does not belong to project {1}").format(self.customer,self.project_name)) raise Exception def validate_pos(self): if not self.cash_bank_account and flt(self.paid_amount): - msgprint("Cash/Bank Account is mandatory for POS, for making payment entry") + msgprint(_("Cash or Bank Account is mandatory for making payment entry")) raise Exception if flt(self.paid_amount) + flt(self.write_off_amount) \ - flt(self.grand_total) > 1/(10**(self.precision("grand_total") + 1)): - frappe.throw(_("""(Paid amount + Write Off Amount) can not be \ - greater than Grand Total""")) + frappe.throw(_("""Paid amount + Write Off Amount can not be greater than Grand Total""")) def validate_item_code(self): for d in self.get('entries'): if not d.item_code: - msgprint("Please enter Item Code at line no : %s to update stock or remove check from Update Stock in Basic Info Tab." % (d.idx), - raise_exception=True) + msgprint(_("Item Code required at Row No {0}").format(d.idx), raise_exception=True) def validate_delivery_note(self): for d in self.get("entries"): if d.delivery_note: - msgprint("""Stock update can not be made against Delivery Note""", raise_exception=1) + msgprint(_("Stock cannot be updated against Delivery Note {0}").format(d.delivery_note), raise_exception=1) def validate_write_off_account(self): if flt(self.write_off_amount) and not self.write_off_account: - msgprint("Please enter Write Off Account", raise_exception=1) + msgprint(_("Please enter Write Off Account"), raise_exception=1) def validate_c_form(self): @@ -396,9 +391,9 @@ class SalesInvoice(SellingController): ps = frappe.db.sql("""select name, warehouse from `tabPOS Setting` where ifnull(user,'') = '' and company = %s""", self.company) if not ps: - msgprint("To make POS entry, please create POS Setting from Accounts --> POS Setting page and refresh the system.", raise_exception=True) + msgprint(_("POS Setting required to make POS Entry"), raise_exception=True) elif not ps[0][1]: - msgprint("Please enter warehouse in POS Setting") + msgprint(_("Warehouse required in POS Setting")) else: w = ps[0][1] return w @@ -426,7 +421,7 @@ class SalesInvoice(SellingController): else: # show message that the amount is not paid frappe.db.set(self,'paid_amount',0) - frappe.msgprint("Note: Payment Entry will not be created since 'Cash/Bank Account' was not specified.") + frappe.msgprint(_("Note: Payment Entry will not be created since 'Cash or Bank Account' was not specified")) else: frappe.db.set(self,'paid_amount',0) @@ -436,15 +431,15 @@ class SalesInvoice(SellingController): submitted = frappe.db.sql("""select name from `tabSales Order` where docstatus = 1 and name = %s""", d.sales_order) if not submitted: - msgprint("Sales Order : "+ cstr(d.sales_order) +" is not submitted") - raise Exception , "Validation Error." + msgprint(_("Sales Order {0} is not submitted").format(d.sales_order)) + raise Exception if d.delivery_note: submitted = frappe.db.sql("""select name from `tabDelivery Note` where docstatus = 1 and name = %s""", d.delivery_note) if not submitted: - msgprint("Delivery Note : "+ cstr(d.delivery_note) +" is not submitted") - raise Exception , "Validation Error." + msgprint(_("Delivery Note {0} is not submitted").format(d.delivery_note)) + raise Exception def update_stock_ledger(self): sl_entries = [] @@ -594,15 +589,12 @@ class SalesInvoice(SellingController): self.validate_notification_email_id() if not self.recurring_type: - msgprint(_("Please select: ") + self.meta.get_label("recurring_type"), + msgprint(_("Please select {0}").format(self.meta.get_label("recurring_type")), raise_exception=1) elif not (self.invoice_period_from_date and \ self.invoice_period_to_date): - msgprint(comma_and([self.meta.get_label("invoice_period_from_date"), - self.meta.get_label("invoice_period_to_date")]) - + _(": Mandatory for a Recurring Invoice."), - raise_exception=True) + throw(_("Invoice Period From and Invoice Period To dates mandatory for recurring invoice")) def convert_to_recurring(self): if self.convert_into_recurring_invoice: @@ -625,20 +617,15 @@ class SalesInvoice(SellingController): from frappe.utils import validate_email_add for email in email_list: if not validate_email_add(email): - msgprint(self.meta.get_label("notification_email_address") \ - + " - " + _("Invalid Email Address") + ": \"%s\"" % email, - raise_exception=1) + throw(_("{0} is an invalid email address in 'Notification Email Address'").format(email)) else: - msgprint("Notification Email Addresses not specified for recurring invoice", - raise_exception=1) + throw(_("'Notification Email Addresses' not specified for recurring invoice")) def set_next_date(self): """ Set next date on which auto invoice will be created""" if not self.repeat_on_day_of_month: - msgprint("""Please enter 'Repeat on Day of Month' field value. - The day of the month on which auto invoice - will be generated e.g. 05, 28 etc.""", raise_exception=1) + msgprint(_("Please enter 'Repeat on Day of Month' field value"), raise_exception=1) next_date = get_next_date(self.posting_date, month_map[self.recurring_type], cint(self.repeat_on_day_of_month)) @@ -765,7 +752,7 @@ def assign_task_to_owner(inv, msg, users): def get_bank_cash_account(mode_of_payment): val = frappe.db.get_value("Mode of Payment", mode_of_payment, "default_account") if not val: - frappe.msgprint("Default Bank / Cash Account not set in Mode of Payment: %s. Please add a Default Account in Mode of Payment master." % mode_of_payment) + frappe.msgprint(_("Please set default Cash or Bank account in Mode of Payment {0}").format(mode_of_payment)) return { "cash_bank_account": val } diff --git a/erpnext/accounts/doctype/shipping_rule/shipping_rule.py b/erpnext/accounts/doctype/shipping_rule/shipping_rule.py index 3cef9920b1..55b7ed639d 100644 --- a/erpnext/accounts/doctype/shipping_rule/shipping_rule.py +++ b/erpnext/accounts/doctype/shipping_rule/shipping_rule.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe -from frappe import _, msgprint +from frappe import _, msgprint, throw from frappe.utils import flt, fmt_money from frappe.model.controller import DocListController from erpnext.setup.utils import get_company_currency @@ -15,36 +15,34 @@ class FromGreaterThanToError(frappe.ValidationError): pass class ManyBlankToValuesError(frappe.ValidationError): pass class ShippingRule(DocListController): - + def validate(self): self.validate_value("calculate_based_on", "in", ["Net Total", "Net Weight"]) self.shipping_rule_conditions = self.get("shipping_rule_conditions") self.validate_from_to_values() self.sort_shipping_rule_conditions() self.validate_overlapping_shipping_rule_conditions() - + def validate_from_to_values(self): zero_to_values = [] - + for d in self.get("shipping_rule_conditions"): self.round_floats_in(d) - + # values cannot be negative self.validate_value("from_value", ">=", 0.0, d) self.validate_value("to_value", ">=", 0.0, d) - + if not d.to_value: zero_to_values.append(d) elif d.from_value >= d.to_value: - msgprint(_("Error") + ": " + _("Row") + " # %d: " % d.idx + - _("From Value should be less than To Value"), - raise_exception=FromGreaterThanToError) - + throw(_("From value must be less than to value in row {0}").format(d.idx), FromGreaterThanToError) + # check if more than two or more rows has To Value = 0 if len(zero_to_values) >= 2: - msgprint(_('''There can only be one Shipping Rule Condition with 0 or blank value for "To Value"'''), - raise_exception=ManyBlankToValuesError) - + throw(_('There can only be one Shipping Rule Condition with 0 or blank value for "To Value"'), + ManyBlankToValuesError) + def sort_shipping_rule_conditions(self): """Sort Shipping Rule Conditions based on increasing From Value""" self.shipping_rules_conditions = sorted(self.shipping_rule_conditions, key=lambda d: flt(d.from_value)) @@ -61,7 +59,7 @@ class ShippingRule(DocListController): """ separate = (x1 <= x2 <= y1 <= y2) or (y1 <= y2 <= x1 <= x2) return (not separate) - + overlaps = [] for i in xrange(0, len(self.shipping_rule_conditions)): for j in xrange(i+1, len(self.shipping_rule_conditions)): @@ -72,13 +70,13 @@ class ShippingRule(DocListController): range_b = (d2.from_value, d2.to_value or d2.from_value) if overlap_exists_between(range_a, range_b): overlaps.append([d1, d2]) - + if overlaps: company_currency = get_company_currency(self.company) - msgprint(_("Error") + ": " + _("Overlapping Conditions found between") + ":") + msgprint(_("Overlapping conditions found between:")) messages = [] for d1, d2 in overlaps: - messages.append("%s-%s = %s " % (d1.from_value, d1.to_value, fmt_money(d1.shipping_amount, currency=company_currency)) + + messages.append("%s-%s = %s " % (d1.from_value, d1.to_value, fmt_money(d1.shipping_amount, currency=company_currency)) + _("and") + " %s-%s = %s" % (d2.from_value, d2.to_value, fmt_money(d2.shipping_amount, currency=company_currency))) - - msgprint("\n".join(messages), raise_exception=OverlappingConditionError) \ No newline at end of file + + msgprint("\n".join(messages), raise_exception=OverlappingConditionError) diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index 6cabf1d68c..ae21099f15 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -180,4 +180,4 @@ def create_party_account(party, party_type, company): "report_type": "Balance Sheet" }).insert(ignore_permissions=True) - frappe.msgprint(_("Account Created") + ": " + account.name) + frappe.msgprint(_("Account Created: {0}").format(account.name)) diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index e317e1141b..a2224d86c2 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe from frappe.utils import nowdate, cstr, flt, now, getdate, add_months -from frappe import msgprint, throw, _ +from frappe import throw, _ from frappe.utils import formatdate from erpnext.utilities import build_filter_conditions @@ -29,9 +29,7 @@ def get_fiscal_years(date=None, fiscal_year=None, label="Date", verbose=1): from `tabFiscal Year` where %s order by year_start_date desc""" % cond) if not fy: - error_msg = """%s %s not in any Fiscal Year""" % (label, formatdate(date)) - error_msg = """{msg}: {date}""".format(msg=_("Fiscal Year does not exist for date"), - date=formatdate(date)) + error_msg = _("""{0} {1} not in any Fiscal Year""").format(label, formatdate(date)) if verbose: frappe.msgprint(error_msg) raise FiscalYearError, error_msg @@ -40,12 +38,7 @@ def get_fiscal_years(date=None, fiscal_year=None, label="Date", verbose=1): def validate_fiscal_year(date, fiscal_year, label="Date"): years = [f[0] for f in get_fiscal_years(date, label=label)] if fiscal_year not in years: - throw(("%(label)s '%(posting_date)s': " + _("not within Fiscal Year") + \ - ": '%(fiscal_year)s'") % { - "label": label, - "posting_date": formatdate(date), - "fiscal_year": fiscal_year - }) + throw(_("{0} '{1}' not in Fiscal Year {2}").format(label, formatdate(date), fiscal_year)) @frappe.whitelist() def get_balance_on(account=None, date=None): @@ -62,7 +55,7 @@ def get_balance_on(account=None, date=None): try: year_start_date = get_fiscal_year(date, verbose=0)[1] - except FiscalYearError, e: + except FiscalYearError: if getdate(date) > getdate(nowdate()): # if fiscal year not found and the date is greater than today # get fiscal year for today's date and its corresponding year start date @@ -232,9 +225,7 @@ def remove_against_link_from_jv(ref_type, ref_no, against_field): and voucher_no != ifnull(against_voucher, '')""", (now(), frappe.session.user, ref_type, ref_no)) - frappe.msgprint("{msg} {linked_jv}".format(msg = _("""Following linked Journal Vouchers \ - made against this transaction has been unlinked. You can link them again with other \ - transactions via Payment Reconciliation Tool."""), linked_jv="\n".join(linked_jv))) + frappe.msgprint(_("Following Journal Vouchers Unlinked: {0}".format("\n".join(linked_jv)))) @frappe.whitelist() diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index d39f6b6725..02170ff464 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import frappe from frappe.utils import cstr, flt -from frappe import msgprint +from frappe import msgprint, _ from erpnext.controllers.buying_controller import BuyingController class PurchaseOrder(BuyingController): @@ -128,8 +128,8 @@ class PurchaseOrder(BuyingController): date_diff = frappe.db.sql("select TIMEDIFF('%s', '%s')" % ( mod_db[0][0],cstr(self.modified))) if date_diff and date_diff[0][0]: - msgprint(cstr(self.doctype) +" => "+ cstr(self.name) +" has been modified. Please Refresh. ") - raise Exception + msgprint(_("{0} {1} has been modified. Please refresh").format(self.doctype, self.name), + raise_exception=True) def update_status(self, status): self.check_modified_date() @@ -140,7 +140,7 @@ class PurchaseOrder(BuyingController): self.update_bin(is_submit = (status == 'Submitted') and 1 or 0, is_stopped = 1) # step 3:=> Acknowledge user - msgprint(self.doctype + ": " + self.name + " has been %s." % ((status == 'Submitted') and 'Unstopped' or cstr(status))) + msgprint(_("Status of {0} {1} is now {2}").format(self.doctype, self.name, status)) def on_submit(self): purchase_controller = frappe.get_doc("Purchase Common") @@ -163,12 +163,12 @@ class PurchaseOrder(BuyingController): pc_obj.check_docstatus(check = 'Next', doctype = 'Purchase Receipt', docname = self.name, detail_doctype = 'Purchase Receipt Item') # Check if Purchase Invoice has been submitted against current Purchase Order - submitted = frappe.db.sql("""select t1.name + submitted = frappe.db.sql_list("""select t1.name from `tabPurchase Invoice` t1,`tabPurchase Invoice Item` t2 where t1.name = t2.parent and t2.purchase_order = %s and t1.docstatus = 1""", self.name) if submitted: - msgprint("Purchase Invoice : " + cstr(submitted[0][0]) + " has already been submitted !") + msgprint(_("Purchase Invoice {0} is already submitted").format(", ".join(submitted))) raise Exception frappe.db.set(self,'status','Cancelled') diff --git a/erpnext/buying/doctype/supplier/supplier.py b/erpnext/buying/doctype/supplier/supplier.py index 7c9236f586..6828845690 100644 --- a/erpnext/buying/doctype/supplier/supplier.py +++ b/erpnext/buying/doctype/supplier/supplier.py @@ -55,7 +55,7 @@ class Supplier(TransactionBase): #validation for Naming Series mandatory field... if frappe.defaults.get_global_default('supp_master_name') == 'Naming Series': if not self.naming_series: - msgprint("Series is Mandatory.", raise_exception=1) + msgprint(_("Series is mandatory"), raise_exception=1) def get_contacts(self,nm): if nm: @@ -106,7 +106,7 @@ class Supplier(TransactionBase): @frappe.whitelist() def get_dashboard_info(supplier): if not frappe.has_permission("Supplier", "read", supplier): - frappe.msgprint("No Permission", raise_exception=True) + frappe.throw(_("No permission")) out = {} for doctype in ["Supplier Quotation", "Purchase Order", "Purchase Receipt", "Purchase Invoice"]: diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 3caed03f35..137bf50b8b 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -417,8 +417,7 @@ class AccountsController(TransactionBase): ref_amt = flt(frappe.db.get_value(ref_dt + " Item", item.get(item_ref_dn), based_on), self.precision(based_on, item)) if not ref_amt: - frappe.msgprint(_("As amount for item") + ": " + item.item_code + _(" in ") + - ref_dt + _(" is zero, system will not check for over-billed")) + frappe.msgprint(_("Warning: System will not check overbilling since amount for Item {0} in {1} is zero").format(item.item_code, ref_dt)) else: already_billed = frappe.db.sql("""select sum(%s) from `tab%s` where %s=%s and docstatus=1 and parent != %s""" % diff --git a/erpnext/controllers/buying_controller.py b/erpnext/controllers/buying_controller.py index 3bde28b379..6a6da74ff3 100644 --- a/erpnext/controllers/buying_controller.py +++ b/erpnext/controllers/buying_controller.py @@ -14,22 +14,22 @@ class BuyingController(StockController): def onload_post_render(self): # contact, address, item details self.set_missing_values() - + def validate(self): super(BuyingController, self).validate() if getattr(self, "supplier", None) and not self.supplier_name: - self.supplier_name = frappe.db.get_value("Supplier", + self.supplier_name = frappe.db.get_value("Supplier", self.supplier, "supplier_name") self.is_item_table_empty() self.validate_stock_or_nonstock_items() self.validate_warehouse() - + def set_missing_values(self, for_validate=False): super(BuyingController, self).set_missing_values(for_validate) self.set_supplier_from_item_default() self.set_price_list_currency("Buying") - + # set contact and address details for supplier, if they are not mentioned if getattr(self, "supplier", None): self.update_if_missing(get_party_details(self.supplier, party_type="Supplier")) @@ -45,24 +45,24 @@ class BuyingController(StockController): if supplier: self.supplier = supplier break - + def validate_warehouse(self): from erpnext.stock.utils import validate_warehouse_company - - warehouses = list(set([d.warehouse for d in + + warehouses = list(set([d.warehouse for d in self.get(self.fname) if getattr(d, "warehouse", None)])) - + for w in warehouses: validate_warehouse_company(w, self.company) def validate_stock_or_nonstock_items(self): if not self.get_stock_items(): - tax_for_valuation = [d.account_head for d in - self.get("other_charges") + tax_for_valuation = [d.account_head for d in + self.get("other_charges") if d.category in ["Valuation", "Valuation and Total"]] if tax_for_valuation: - frappe.msgprint(_("""Tax Category can not be 'Valuation' or 'Valuation and Total' as all items are non-stock items"""), raise_exception=1) - + frappe.throw(_("Tax Category can not be 'Valuation' or 'Valuation and Total' as all items are non-stock items")) + def set_total_in_words(self): from frappe.utils import money_in_words company_currency = get_company_currency(self.company) @@ -71,12 +71,12 @@ class BuyingController(StockController): if self.meta.get_field("in_words_import"): self.in_words_import = money_in_words(self.grand_total_import, self.currency) - + def calculate_taxes_and_totals(self): self.other_fname = "other_charges" super(BuyingController, self).calculate_taxes_and_totals() self.calculate_total_advance("Purchase Invoice", "advance_allocation_details") - + def calculate_item_values(self): for item in self.item_doclist: self.round_floats_in(item) @@ -86,7 +86,7 @@ class BuyingController(StockController): elif not item.rate: item.rate = flt(item.price_list_rate * (1.0 - (item.discount_percentage / 100.0)), self.precision("rate", item)) - + item.amount = flt(item.rate * item.qty, self.precision("amount", item)) item.item_tax_amount = 0.0; @@ -94,19 +94,19 @@ class BuyingController(StockController): self._set_in_company_currency(item, "amount", "base_amount") self._set_in_company_currency(item, "price_list_rate", "base_price_list_rate") self._set_in_company_currency(item, "rate", "base_rate") - - + + def calculate_net_total(self): self.net_total = self.net_total_import = 0.0 for item in self.item_doclist: self.net_total += item.base_amount self.net_total_import += item.amount - + self.round_floats_in(self, ["net_total", "net_total_import"]) - + def calculate_totals(self): - self.grand_total = flt(self.tax_doclist[-1].total if self.tax_doclist + self.grand_total = flt(self.tax_doclist[-1].total if self.tax_doclist else self.net_total, self.precision("grand_total")) self.grand_total_import = flt(self.grand_total / self.conversion_rate, self.precision("grand_total_import")) @@ -116,28 +116,28 @@ class BuyingController(StockController): if self.meta.get_field("rounded_total"): self.rounded_total = _round(self.grand_total) - + if self.meta.get_field("rounded_total_import"): self.rounded_total_import = _round(self.grand_total_import) - + if self.meta.get_field("other_charges_added"): - self.other_charges_added = flt(sum([flt(d.tax_amount) for d in self.tax_doclist - if d.add_deduct_tax=="Add" and d.category in ["Valuation and Total", "Total"]]), + self.other_charges_added = flt(sum([flt(d.tax_amount) for d in self.tax_doclist + if d.add_deduct_tax=="Add" and d.category in ["Valuation and Total", "Total"]]), self.precision("other_charges_added")) - + if self.meta.get_field("other_charges_deducted"): - self.other_charges_deducted = flt(sum([flt(d.tax_amount) for d in self.tax_doclist - if d.add_deduct_tax=="Deduct" and d.category in ["Valuation and Total", "Total"]]), + self.other_charges_deducted = flt(sum([flt(d.tax_amount) for d in self.tax_doclist + if d.add_deduct_tax=="Deduct" and d.category in ["Valuation and Total", "Total"]]), self.precision("other_charges_deducted")) - + if self.meta.get_field("other_charges_added_import"): - self.other_charges_added_import = flt(self.other_charges_added / + self.other_charges_added_import = flt(self.other_charges_added / self.conversion_rate, self.precision("other_charges_added_import")) - + if self.meta.get_field("other_charges_deducted_import"): - self.other_charges_deducted_import = flt(self.other_charges_deducted / + self.other_charges_deducted_import = flt(self.other_charges_deducted / self.conversion_rate, self.precision("other_charges_deducted_import")) - + def calculate_outstanding_amount(self): if self.doctype == "Purchase Invoice" and self.docstatus == 0: self.total_advance = flt(self.total_advance, @@ -146,17 +146,17 @@ class BuyingController(StockController): self.precision("write_off_amount")), self.precision("total_amount_to_pay")) self.outstanding_amount = flt(self.total_amount_to_pay - self.total_advance, self.precision("outstanding_amount")) - + # update valuation rate def update_valuation_rate(self, parentfield): """ item_tax_amount is the total tax amount applied on that item - stored for valuation - + stored for valuation + TODO: rename item_tax_amount to valuation_tax_amount """ stock_items = self.get_stock_items() - + stock_items_qty, stock_items_amount = 0, 0 last_stock_item_idx = 1 for d in self.get(parentfield): @@ -164,47 +164,45 @@ class BuyingController(StockController): stock_items_qty += flt(d.qty) stock_items_amount += flt(d.base_amount) last_stock_item_idx = d.idx - - total_valuation_amount = sum([flt(d.tax_amount) for d in - self.get("other_charges") + + total_valuation_amount = sum([flt(d.tax_amount) for d in + self.get("other_charges") if d.category in ["Valuation", "Valuation and Total"]]) - - + + valuation_amount_adjustment = total_valuation_amount for i, item in enumerate(self.get(parentfield)): if item.item_code and item.qty and item.item_code in stock_items: item_proportion = flt(item.base_amount) / stock_items_amount if stock_items_amount \ else flt(item.qty) / stock_items_qty - + if i == (last_stock_item_idx - 1): - item.item_tax_amount = flt(valuation_amount_adjustment, + item.item_tax_amount = flt(valuation_amount_adjustment, self.precision("item_tax_amount", item)) else: - item.item_tax_amount = flt(item_proportion * total_valuation_amount, + item.item_tax_amount = flt(item_proportion * total_valuation_amount, self.precision("item_tax_amount", item)) valuation_amount_adjustment -= item.item_tax_amount self.round_floats_in(item) - + item.conversion_factor = item.conversion_factor or flt(frappe.db.get_value( - "UOM Conversion Detail", {"parent": item.item_code, "uom": item.uom}, + "UOM Conversion Detail", {"parent": item.item_code, "uom": item.uom}, "conversion_factor")) or 1 qty_in_stock_uom = flt(item.qty * item.conversion_factor) item.valuation_rate = ((item.base_amount + item.item_tax_amount + item.rm_supp_cost) / qty_in_stock_uom) else: item.valuation_rate = 0.0 - + def validate_for_subcontracting(self): if not self.is_subcontracted and self.sub_contracted_items: - frappe.msgprint(_("""Please enter whether %s is made for subcontracting or purchasing, - in 'Is Subcontracted' field""" % self.doctype), raise_exception=1) - + frappe.throw(_("Please enter 'Is Subcontracted' as Yes or No")) + if self.doctype == "Purchase Receipt" and self.is_subcontracted=="Yes" \ and not self.supplier_warehouse: - frappe.msgprint(_("Supplier Warehouse mandatory subcontracted purchase receipt"), - raise_exception=1) - + frappe.throw(_("Supplier Warehouse mandatory for sub-contracted Purchase Receipt")) + def update_raw_materials_supplied(self, raw_material_table): self.set(raw_material_table, []) if self.is_subcontracted=="Yes": @@ -234,30 +232,30 @@ class BuyingController(StockController): "consumed_qty": required_qty, "description": item.description, }) - + self.append(raw_material_table, rm_doclist) - + raw_materials_cost += required_qty * flt(item.rate) - + if self.doctype == "Purchase Receipt": d.rm_supp_cost = raw_materials_cost def get_items_from_default_bom(self, item_code): - bom_items = frappe.db.sql("""select t2.item_code, t2.qty_consumed_per_unit, - t2.rate, t2.stock_uom, t2.name, t2.description - from `tabBOM` t1, `tabBOM Item` t2 - where t2.parent = t1.name and t1.item = %s and t1.is_default = 1 + bom_items = frappe.db.sql("""select t2.item_code, t2.qty_consumed_per_unit, + t2.rate, t2.stock_uom, t2.name, t2.description + from `tabBOM` t1, `tabBOM Item` t2 + where t2.parent = t1.name and t1.item = %s and t1.is_default = 1 and t1.docstatus = 1 and t1.is_active = 1""", item_code, as_dict=1) if not bom_items: - msgprint(_("No default BOM exists for item: ") + item_code, raise_exception=1) - + msgprint(_("No default BOM exists for Item {0}").format(item_code), raise_exception=1) + return bom_items @property def sub_contracted_items(self): if not hasattr(self, "_sub_contracted_items"): self._sub_contracted_items = [] - item_codes = list(set(item.item_code for item in + item_codes = list(set(item.item_code for item in self.get(self.fname))) if item_codes: self._sub_contracted_items = [r[0] for r in frappe.db.sql("""select name @@ -265,12 +263,12 @@ class BuyingController(StockController): (", ".join((["%s"]*len(item_codes))),), item_codes)] return self._sub_contracted_items - + @property def purchase_items(self): if not hasattr(self, "_purchase_items"): self._purchase_items = [] - item_codes = list(set(item.item_code for item in + item_codes = list(set(item.item_code for item in self.get(self.fname))) if item_codes: self._purchase_items = [r[0] for r in frappe.db.sql("""select name @@ -282,4 +280,4 @@ class BuyingController(StockController): def is_item_table_empty(self): if not len(self.get(self.fname)): - frappe.throw(_("Item table can not be blank")) \ No newline at end of file + frappe.throw(_("Item table can not be blank")) diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index 3f78fe69cb..b13fea2fca 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -3,9 +3,9 @@ from __future__ import unicode_literals import frappe -from frappe.utils import cint, flt, comma_or, _round, cstr +from frappe.utils import cint, flt, _round, cstr from erpnext.setup.utils import get_company_currency -from frappe import msgprint, _ +from frappe import _, throw from erpnext.controllers.stock_controller import StockController @@ -233,8 +233,7 @@ class SellingController(StockController): if self.meta.get_field("commission_rate"): self.round_floats_in(self, ["net_total", "commission_rate"]) if self.commission_rate > 100.0: - msgprint(_(self.meta.get_label("commission_rate")) + " " + - _("cannot be greater than 100"), raise_exception=True) + throw(_("Commission rate cannot be greater than 100")) self.total_commission = flt(self.net_total * self.commission_rate / 100.0, self.precision("total_commission")) @@ -252,17 +251,14 @@ class SellingController(StockController): total += sales_person.allocated_percentage if sales_team and total != 100.0: - msgprint(_("Total") + " " + - _(self.meta.get_label("allocated_percentage", parentfield="sales_team")) + - " " + _("should be 100%"), raise_exception=True) + throw(_("Total allocated percentage for sales team should be 100")) def validate_order_type(self): valid_types = ["Sales", "Maintenance", "Shopping Cart"] if not self.order_type: self.order_type = "Sales" elif self.order_type not in valid_types: - msgprint(_(self.meta.get_label("order_type")) + " " + - _("must be one of") + ": " + comma_or(valid_types), raise_exception=True) + throw(_("Order Type must be one of {1}").comma_or(valid_types)) def check_credit(self, grand_total): customer_account = frappe.db.get_value("Account", {"company": self.company, diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py index 0fceebf84b..4ccdbda359 100644 --- a/erpnext/controllers/status_updater.py +++ b/erpnext/controllers/status_updater.py @@ -3,8 +3,8 @@ from __future__ import unicode_literals import frappe -from frappe.utils import flt, cstr -from frappe import msgprint +from frappe.utils import flt +from frappe import msgprint, _, throw from frappe.model.controller import DocListController @@ -129,19 +129,13 @@ class StatusUpdater(DocListController): item['target_ref_field'] = args['target_ref_field'].replace('_', ' ') if not item[args['target_ref_field']]: - msgprint("""As %(target_ref_field)s for item: %(item_code)s in \ - %(parenttype)s: %(parent)s is zero, system will not check \ - over-delivery or over-billed""" % item) + msgprint(_("Note: System will not check over-delivery and over-booking for Item {0} as quantity or amount is 0").format(item.item_code)) elif args.get('no_tolerance'): item['reduce_by'] = item[args['target_field']] - \ item[args['target_ref_field']] if item['reduce_by'] > .01: - msgprint(""" - Row #%(idx)s: Max %(target_ref_field)s allowed for Item \ - %(item_code)s against %(parenttype)s %(parent)s \ - is """ % item + cstr(item[args['target_ref_field']]) + - """.
You must reduce the %(target_ref_field)s by \ - %(reduce_by)s""" % item, raise_exception=1) + msgprint(_("Allowance for over-delivery / over-billing crossed for Item {0}").format(item.item_code)) + throw(_("{0} must be less than or equal to {1}").format(_(item.target_ref_field), item[args["target_ref_field"]])) else: self.check_overflow_with_tolerance(item, args) @@ -161,18 +155,8 @@ class StatusUpdater(DocListController): item['max_allowed'] = flt(item[args['target_ref_field']] * (100+tolerance)/100) item['reduce_by'] = item[args['target_field']] - item['max_allowed'] - msgprint(""" - Row #%(idx)s: Max %(target_ref_field)s allowed for Item %(item_code)s \ - against %(parenttype)s %(parent)s is %(max_allowed)s. - - If you want to increase your overflow tolerance, please increase tolerance %% in \ - Global Defaults or Item master. - - Or, you must reduce the %(target_ref_field)s by %(reduce_by)s - - Also, please check if the order item has already been billed in the Sales Order""" % - item, raise_exception=1) - + msgprint(_("Allowance for over-delivery / over-billing crossed for Item {0}").format(item["item_code"])) + throw(_("{0} must be less than or equal to {1}").format(_(item["target_ref_field"]), item[args["max_allowed"]])) def update_qty(self, change_modified=True): """ diff --git a/erpnext/controllers/stock_controller.py b/erpnext/controllers/stock_controller.py index 6aeb9402f6..b78392441d 100644 --- a/erpnext/controllers/stock_controller.py +++ b/erpnext/controllers/stock_controller.py @@ -65,7 +65,7 @@ class StockController(AccountsController): warehouse_with_no_account.append(sle.warehouse) if warehouse_with_no_account: - msgprint(_("No accounting entries for following warehouses") + ": \n" + + msgprint(_("No accounting entries for the following warehouses") + ": \n" + "\n".join(warehouse_with_no_account)) return process_gl_map(gl_list) @@ -231,12 +231,10 @@ class StockController(AccountsController): def check_expense_account(self, item): if item.meta.get_field("expense_account") and not item.expense_account: - msgprint(_("""Expense/Difference account is mandatory for item: """) + item.item_code, - raise_exception=1) + frappe.throw(_("Expense or Difference account is mandatory for Item {0}").format(item.item_code)) if item.meta.get_field("expense_account") and not item.cost_center: - msgprint(_("""Cost Center is mandatory for item: """) + item.item_code, - raise_exception=1) + frappe.throw(_("""Cost Center is mandatory for item {0}""").format(item.item_code)) def get_sl_entries(self, d, args): sl_dict = { diff --git a/erpnext/controllers/trends.py b/erpnext/controllers/trends.py index fa2e2aee82..2c3483c311 100644 --- a/erpnext/controllers/trends.py +++ b/erpnext/controllers/trends.py @@ -3,12 +3,12 @@ from __future__ import unicode_literals import frappe -from frappe.utils import add_days, add_months, cstr, getdate +from frappe.utils import getdate from frappe import _ def get_columns(filters, trans): validate_filters(filters) - + # get conditions for based_on filter cond based_on_details = based_wise_colums_query(filters.get("based_on"), trans) # get conditions for periodic filter cond @@ -17,11 +17,11 @@ def get_columns(filters, trans): group_by_cols = group_wise_column(filters.get("group_by")) columns = based_on_details["based_on_cols"] + period_cols + ["Total(Qty):Float:120", "Total(Amt):Currency:120"] - if group_by_cols: + if group_by_cols: columns = based_on_details["based_on_cols"] + group_by_cols + period_cols + \ - ["Total(Qty):Float:120", "Total(Amt):Currency:120"] + ["Total(Qty):Float:120", "Total(Amt):Currency:120"] - conditions = {"based_on_select": based_on_details["based_on_select"], "period_wise_select": period_select, + conditions = {"based_on_select": based_on_details["based_on_select"], "period_wise_select": period_select, "columns": columns, "group_by": based_on_details["based_on_group_by"], "grbc": group_by_cols, "trans": trans, "addl_tables": based_on_details["addl_tables"]} @@ -30,16 +30,16 @@ def get_columns(filters, trans): def validate_filters(filters): for f in ["Fiscal Year", "Based On", "Period", "Company"]: if not filters.get(f.lower().replace(" ", "_")): - frappe.msgprint(f + _(" is mandatory"), raise_exception=1) - + frappe.throw(_("{0} is mandatory").format(f)) + if filters.get("based_on") == filters.get("group_by"): - frappe.msgprint("'Based On' and 'Group By' can not be same", raise_exception=1) + frappe.throw(_("'Based On' and 'Group By' can not be same")) def get_data(filters, conditions): data = [] inc, cond= '','' query_details = conditions["based_on_select"] + conditions["period_wise_select"] - + if conditions["based_on_select"] in ["t1.project_name,", "t2.project_name,"]: cond = 'and '+ conditions["based_on_select"][:-1] +' IS Not NULL' @@ -59,55 +59,55 @@ def get_data(filters, conditions): else : inc = 1 data1 = frappe.db.sql(""" select %s from `tab%s` t1, `tab%s Item` t2 %s - where t2.parent = t1.name and t1.company = %s and t1.fiscal_year = %s and - t1.docstatus = 1 %s - group by %s - """ % (query_details, conditions["trans"], conditions["trans"], conditions["addl_tables"], "%s", - "%s", cond, conditions["group_by"]), (filters.get("company"), + where t2.parent = t1.name and t1.company = %s and t1.fiscal_year = %s and + t1.docstatus = 1 %s + group by %s + """ % (query_details, conditions["trans"], conditions["trans"], conditions["addl_tables"], "%s", + "%s", cond, conditions["group_by"]), (filters.get("company"), filters["fiscal_year"]),as_list=1) for d in range(len(data1)): #to add blanck column dt = data1[d] - dt.insert(ind,'') + dt.insert(ind,'') data.append(dt) #to get distinct value of col specified by group_by in filter row = frappe.db.sql("""select DISTINCT(%s) from `tab%s` t1, `tab%s Item` t2 %s - where t2.parent = t1.name and t1.company = %s and t1.fiscal_year = %s - and t1.docstatus = 1 and %s = %s - """ % - (sel_col, conditions["trans"], conditions["trans"], conditions["addl_tables"], + where t2.parent = t1.name and t1.company = %s and t1.fiscal_year = %s + and t1.docstatus = 1 and %s = %s + """ % + (sel_col, conditions["trans"], conditions["trans"], conditions["addl_tables"], "%s", "%s", conditions["group_by"], "%s"), (filters.get("company"), filters.get("fiscal_year"), data1[d][0]), as_list=1) for i in range(len(row)): des = ['' for q in range(len(conditions["columns"]))] - - #get data for group_by filter + + #get data for group_by filter row1 = frappe.db.sql(""" select %s , %s from `tab%s` t1, `tab%s Item` t2 %s - where t2.parent = t1.name and t1.company = %s and t1.fiscal_year = %s - and t1.docstatus = 1 and %s = %s and %s = %s - """ % - (sel_col, conditions["period_wise_select"], conditions["trans"], - conditions["trans"], conditions["addl_tables"], "%s", "%s", sel_col, - "%s", conditions["group_by"], "%s"), - (filters.get("company"), filters.get("fiscal_year"), row[i][0], + where t2.parent = t1.name and t1.company = %s and t1.fiscal_year = %s + and t1.docstatus = 1 and %s = %s and %s = %s + """ % + (sel_col, conditions["period_wise_select"], conditions["trans"], + conditions["trans"], conditions["addl_tables"], "%s", "%s", sel_col, + "%s", conditions["group_by"], "%s"), + (filters.get("company"), filters.get("fiscal_year"), row[i][0], data1[d][0]), as_list=1) des[ind] = row[i] - for j in range(1,len(conditions["columns"])-inc): + for j in range(1,len(conditions["columns"])-inc): des[j+inc] = row1[0][j] - + data.append(des) else: data = frappe.db.sql(""" select %s from `tab%s` t1, `tab%s Item` t2 %s - where t2.parent = t1.name and t1.company = %s and t1.fiscal_year = %s and - t1.docstatus = 1 %s - group by %s - """ % - (query_details, conditions["trans"], conditions["trans"], conditions["addl_tables"], - "%s", "%s", cond,conditions["group_by"]), + where t2.parent = t1.name and t1.company = %s and t1.fiscal_year = %s and + t1.docstatus = 1 %s + group by %s + """ % + (query_details, conditions["trans"], conditions["trans"], conditions["addl_tables"], + "%s", "%s", cond,conditions["group_by"]), (filters.get("company"), filters.get("fiscal_year")), as_list=1) return data @@ -124,13 +124,13 @@ def period_wise_colums_query(filters, trans): trans_date = 'posting_date' else: trans_date = 'transaction_date' - + if filters.get("period") != 'Yearly': for dt in bet_dates: get_period_wise_columns(dt, filters.get("period"), pwc) query_details = get_period_wise_query(dt, trans_date, query_details) else: - pwc = [filters.get("fiscal_year") + " (Qty):Float:120", + pwc = [filters.get("fiscal_year") + " (Qty):Float:120", filters.get("fiscal_year") + " (Amt):Currency:120"] query_details = " SUM(t2.qty), SUM(t1.grand_total)," @@ -139,14 +139,14 @@ def period_wise_colums_query(filters, trans): def get_period_wise_columns(bet_dates, period, pwc): if period == 'Monthly': - pwc += [get_mon(bet_dates[0]) + " (Qty):Float:120", + pwc += [get_mon(bet_dates[0]) + " (Qty):Float:120", get_mon(bet_dates[0]) + " (Amt):Currency:120"] else: - pwc += [get_mon(bet_dates[0]) + "-" + get_mon(bet_dates[1]) + " (Qty):Float:120", + pwc += [get_mon(bet_dates[0]) + "-" + get_mon(bet_dates[1]) + " (Qty):Float:120", get_mon(bet_dates[0]) + "-" + get_mon(bet_dates[1]) + " (Amt):Currency:120"] def get_period_wise_query(bet_dates, trans_date, query_details): - query_details += """SUM(IF(t1.%(trans_date)s BETWEEN '%(sd)s' AND '%(ed)s', t2.qty, NULL)), + query_details += """SUM(IF(t1.%(trans_date)s BETWEEN '%(sd)s' AND '%(ed)s', t2.qty, NULL)), SUM(IF(t1.%(trans_date)s BETWEEN '%(sd)s' AND '%(ed)s', t1.grand_total, NULL)), """ % {"trans_date": trans_date, "sd": bet_dates[0],"ed": bet_dates[1]} return query_details @@ -156,7 +156,7 @@ def get_period_date_ranges(period, fiscal_year=None, year_start_date=None): from dateutil.relativedelta import relativedelta if not year_start_date: - year_start_date, year_end_date = frappe.db.get_value("Fiscal Year", + year_start_date, year_end_date = frappe.db.get_value("Fiscal Year", fiscal_year, ["year_start_date", "year_end_date"]) increment = { @@ -197,13 +197,13 @@ def based_wise_colums_query(based_on, trans): # based_on_cols, based_on_select, based_on_group_by, addl_tables if based_on == "Item": based_on_details["based_on_cols"] = ["Item:Link/Item:120", "Item Name:Data:120"] - based_on_details["based_on_select"] = "t2.item_code, t2.item_name," + based_on_details["based_on_select"] = "t2.item_code, t2.item_name," based_on_details["based_on_group_by"] = 't2.item_code' based_on_details["addl_tables"] = '' elif based_on == "Item Group": based_on_details["based_on_cols"] = ["Item Group:Link/Item Group:120"] - based_on_details["based_on_select"] = "t2.item_group," + based_on_details["based_on_select"] = "t2.item_group," based_on_details["based_on_group_by"] = 't2.item_group' based_on_details["addl_tables"] = '' @@ -224,7 +224,7 @@ def based_wise_colums_query(based_on, trans): based_on_details["based_on_select"] = "t1.supplier, t3.supplier_type," based_on_details["based_on_group_by"] = 't1.supplier' based_on_details["addl_tables"] = ',`tabSupplier` t3' - + elif based_on == 'Supplier Type': based_on_details["based_on_cols"] = ["Supplier Type:Link/Supplier Type:140"] based_on_details["based_on_select"] = "t3.supplier_type," @@ -249,7 +249,7 @@ def based_wise_colums_query(based_on, trans): based_on_details["based_on_group_by"] = 't2.project_name' based_on_details["addl_tables"] = '' else: - frappe.msgprint("Project-wise data is not available for Quotation", raise_exception=1) + frappe.throw(_("Project-wise data is not available for Quotation")) return based_on_details @@ -257,4 +257,4 @@ def group_wise_column(group_by): if group_by: return [group_by+":Link/"+group_by+":120"] else: - return [] \ No newline at end of file + return [] diff --git a/erpnext/hr/doctype/appraisal/appraisal.py b/erpnext/hr/doctype/appraisal/appraisal.py index 1f7f255c8b..090ba20de7 100644 --- a/erpnext/hr/doctype/appraisal/appraisal.py +++ b/erpnext/hr/doctype/appraisal/appraisal.py @@ -22,22 +22,22 @@ class Appraisal(Document): def get_employee_name(self): self.employee_name = frappe.db.get_value("Employee", self.employee, "employee_name") return self.employee_name - + def validate_dates(self): if getdate(self.start_date) > getdate(self.end_date): frappe.throw(_("End Date can not be less than Start Date")) - + def validate_existing_appraisal(self): - chk = frappe.db.sql("""select name from `tabAppraisal` where employee=%s - and (status='Submitted' or status='Completed') - and ((start_date>=%s and start_date<=%s) + chk = frappe.db.sql("""select name from `tabAppraisal` where employee=%s + and (status='Submitted' or status='Completed') + and ((start_date>=%s and start_date<=%s) or (end_date>=%s and end_date<=%s))""", (self.employee,self.start_date,self.end_date,self.start_date,self.end_date)) if chk: frappe.throw("You have already created Appraisal "\ +cstr(chk[0][0])+" in the current date range for employee "\ +cstr(self.employee_name)) - + def calculate_total(self): total, total_w = 0, 0 for d in self.get('appraisal_details'): @@ -47,30 +47,29 @@ class Appraisal(Document): total_w += flt(d.per_weightage) if int(total_w) != 100: - msgprint("Total weightage assigned should be 100%. It is :" + str(total_w) + "%", - raise_exception=1) + frappe.throw(_("Total weightage assigned should be 100%. It is {0}").format(str(total_w) + "%")) if frappe.db.get_value("Employee", self.employee, "user_id") != \ frappe.session.user and total == 0: - msgprint("Total can't be zero. You must atleast give some points!", raise_exception=1) + frappe.throw(_("Total cannot be zero")) self.total_score = total - + def on_submit(self): frappe.db.set(self, 'status', 'Submitted') - - def on_cancel(self): + + def on_cancel(self): frappe.db.set(self, 'status', 'Cancelled') @frappe.whitelist() def fetch_appraisal_template(source_name, target_doc=None): target_doc = get_mapped_doc("Appraisal Template", source_name, { "Appraisal Template": { - "doctype": "Appraisal", - }, + "doctype": "Appraisal", + }, "Appraisal Template Goal": { - "doctype": "Appraisal Goal", + "doctype": "Appraisal Goal", } }, target_doc) - return target_doc \ No newline at end of file + return target_doc diff --git a/erpnext/hr/doctype/appraisal_template/appraisal_template.py b/erpnext/hr/doctype/appraisal_template/appraisal_template.py index 930d509a7a..1f753d051b 100644 --- a/erpnext/hr/doctype/appraisal_template/appraisal_template.py +++ b/erpnext/hr/doctype/appraisal_template/appraisal_template.py @@ -12,8 +12,6 @@ class AppraisalTemplate(Document): self.total_points = 0 for d in self.get("kra_sheet"): self.total_points += int(d.per_weightage or 0) - + if int(self.total_points) != 100: - frappe.msgprint(_("Total (sum of) points distribution for all goals should be 100.") \ - + " " + _("Not") + " " + str(self.total_points), - raise_exception=True) \ No newline at end of file + frappe.throw(_("Total points for all goals should be 100. It is {0}").format(self.total_points)) diff --git a/erpnext/hr/doctype/attendance/attendance.py b/erpnext/hr/doctype/attendance/attendance.py index 8c1c3f0a4e..ea9f27131f 100644 --- a/erpnext/hr/doctype/attendance/attendance.py +++ b/erpnext/hr/doctype/attendance/attendance.py @@ -5,44 +5,41 @@ from __future__ import unicode_literals import frappe from frappe.utils import getdate, nowdate -from frappe import msgprint, _ +from frappe import _ from frappe.model.document import Document class Attendance(Document): - def validate_duplicate_record(self): - res = frappe.db.sql("""select name from `tabAttendance` where employee = %s and att_date = %s - and name != %s and docstatus = 1""", + def validate_duplicate_record(self): + res = frappe.db.sql("""select name from `tabAttendance` where employee = %s and att_date = %s + and name != %s and docstatus = 1""", (self.employee, self.att_date, self.name)) if res: - msgprint(_("Attendance for the employee: ") + self.employee + - _(" already marked"), raise_exception=1) - + frappe.throw(_("Attendance for employee {0} is already marked").format(self.employee)) + def check_leave_record(self): if self.status == 'Present': - leave = frappe.db.sql("""select name from `tabLeave Application` - where employee = %s and %s between from_date and to_date and status = 'Approved' + leave = frappe.db.sql("""select name from `tabLeave Application` + where employee = %s and %s between from_date and to_date and status = 'Approved' and docstatus = 1""", (self.employee, self.att_date)) - + if leave: - frappe.msgprint(_("Employee: ") + self.employee + _(" was on leave on ") - + self.att_date + _(". You can not mark his attendance as 'Present'"), - raise_exception=1) - + frappe.throw(_("Employee {0} was on leave on {1}. Cannot mark attendance.").format(self.employee, + self.att_date)) + def validate_fiscal_year(self): from erpnext.accounts.utils import validate_fiscal_year validate_fiscal_year(self.att_date, self.fiscal_year) - + def validate_att_date(self): if getdate(self.att_date) > getdate(nowdate()): - msgprint(_("Attendance can not be marked for future dates"), raise_exception=1) + frappe.throw(_("Attendance can not be marked for future dates")) def validate_employee(self): emp = frappe.db.sql("select name from `tabEmployee` where name = %s and status = 'Active'", self.employee) if not emp: - msgprint(_("Employee: ") + self.employee + - _(" not active or does not exists in the system"), raise_exception=1) - + frappe.throw(_("Employee {0} is not active or does not exist").format(self.employee)) + def validate(self): from erpnext.utilities import validate_status validate_status(self.status, ["Present", "Absent", "Half Day"]) @@ -50,9 +47,9 @@ class Attendance(Document): self.validate_att_date() self.validate_duplicate_record() self.check_leave_record() - + def on_update(self): - # this is done because sometimes user entered wrong employee name + # this is done because sometimes user entered wrong employee name # while uploading employee attendance employee_name = frappe.db.get_value("Employee", self.employee, "employee_name") - frappe.db.set(self, 'employee_name', employee_name) \ No newline at end of file + frappe.db.set(self, 'employee_name', employee_name) diff --git a/erpnext/hr/doctype/expense_claim/expense_claim.py b/erpnext/hr/doctype/expense_claim/expense_claim.py index d95be6bf3a..8250e51ede 100644 --- a/erpnext/hr/doctype/expense_claim/expense_claim.py +++ b/erpnext/hr/doctype/expense_claim/expense_claim.py @@ -3,25 +3,22 @@ from __future__ import unicode_literals import frappe -from frappe import msgprint +from frappe import _ from frappe.model.document import Document class ExpenseClaim(Document): - def validate(self): self.validate_fiscal_year() self.validate_exp_details() - + def on_submit(self): if self.approval_status=="Draft": - frappe.msgprint("""Please set Approval Status to 'Approved' or \ - 'Rejected' before submitting""", raise_exception=1) - + frappe.throw(_("""Approval Status must be 'Approved' or 'Rejected'""")) + def validate_fiscal_year(self): from erpnext.accounts.utils import validate_fiscal_year validate_fiscal_year(self.posting_date, self.fiscal_year, "Posting Date") - + def validate_exp_details(self): if not self.get('expense_voucher_details'): - msgprint("Please add expense voucher details") - raise Exception + frappe.throw(_("Please add expense voucher details")) diff --git a/erpnext/hr/doctype/holiday_list/holiday_list.py b/erpnext/hr/doctype/holiday_list/holiday_list.py index ec15604a30..496c930714 100644 --- a/erpnext/hr/doctype/holiday_list/holiday_list.py +++ b/erpnext/hr/doctype/holiday_list/holiday_list.py @@ -4,20 +4,19 @@ from __future__ import unicode_literals import frappe -from frappe.utils import add_days, add_years, cint, getdate +from frappe.utils import cint from frappe.model.naming import make_autoname -from frappe import msgprint, throw, _ -import datetime +from frappe import throw, _ from frappe.model.document import Document class HolidayList(Document): def autoname(self): self.name = make_autoname(self.fiscal_year + "/" + self.holiday_list_name + "/.###") - + def validate(self): self.update_default_holiday_list() - + def get_weekly_off_dates(self): self.validate_values() yr_start_date, yr_end_date = self.get_fy_start_end_dates() @@ -42,24 +41,24 @@ class HolidayList(Document): def get_weekly_off_date_list(self, year_start_date, year_end_date): from frappe.utils import getdate year_start_date, year_end_date = getdate(year_start_date), getdate(year_end_date) - + from dateutil import relativedelta from datetime import timedelta import calendar - + date_list = [] weekday = getattr(calendar, (self.weekly_off).upper()) reference_date = year_start_date + relativedelta.relativedelta(weekday=weekday) - + while reference_date <= year_end_date: date_list.append(reference_date) reference_date += timedelta(days=7) - + return date_list - + def clear_table(self): self.set('holiday_list_details', []) def update_default_holiday_list(self): - frappe.db.sql("""update `tabHoliday List` set is_default = 0 + frappe.db.sql("""update `tabHoliday List` set is_default = 0 where ifnull(is_default, 0) = 1 and fiscal_year = %s""", (self.fiscal_year,)) diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.py b/erpnext/hr/doctype/leave_allocation/leave_allocation.py index f16f615057..cbb64263cf 100755 --- a/erpnext/hr/doctype/leave_allocation/leave_allocation.py +++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.py @@ -4,67 +4,46 @@ from __future__ import unicode_literals import frappe from frappe.utils import cint, flt -from frappe import msgprint - +from frappe import _ + from frappe.model.document import Document class LeaveAllocation(Document): def validate(self): self.validate_new_leaves_allocated_value() self.check_existing_leave_allocation() - self.validate_new_leaves_allocated() - + def on_update_after_submit(self): self.validate_new_leaves_allocated_value() - self.validate_new_leaves_allocated() def on_update(self): self.get_total_allocated_leaves() - + def on_cancel(self): self.check_for_leave_application() - + def validate_new_leaves_allocated_value(self): """validate that leave allocation is in multiples of 0.5""" if flt(self.new_leaves_allocated) % 0.5: - guess = round(flt(self.new_leaves_allocated) * 2.0) / 2.0 - - msgprint("""New Leaves Allocated should be a multiple of 0.5. - Perhaps you should enter %s or %s""" % (guess, guess + 0.5), - raise_exception=1) - + frappe.throw(_("Leaves must be allocated in multiples of 0.5")) + def check_existing_leave_allocation(self): """check whether leave for same type is already allocated or not""" leave_allocation = frappe.db.sql("""select name from `tabLeave Allocation` where employee=%s and leave_type=%s and fiscal_year=%s and docstatus=1""", (self.employee, self.leave_type, self.fiscal_year)) if leave_allocation: - msgprint("""%s is already allocated to Employee: %s for Fiscal Year: %s. - Please refere Leave Allocation: \ - %s""" % \ - (self.leave_type, self.employee, self.fiscal_year, - leave_allocation[0][0], leave_allocation[0][0]), raise_exception=1) - - def validate_new_leaves_allocated(self): - """check if Total Leaves Allocated >= Leave Applications""" - self.total_leaves_allocated = flt(self.carry_forwarded_leaves) + \ - flt(self.new_leaves_allocated) - leaves_applied = self.get_leaves_applied(self.fiscal_year) - if leaves_applied > self.total_leaves_allocated: - expected_new_leaves = flt(self.new_leaves_allocated) + \ - (leaves_applied - self.total_leaves_allocated) - msgprint("""Employee: %s has already applied for %s leaves. - Hence, New Leaves Allocated should be atleast %s""" % \ - (self.employee, leaves_applied, expected_new_leaves), - raise_exception=1) - + frappe.msgprint(_("Leaves for type {0} already allocated for Employee {1} for Fiscal Year {0}").format(self.leave_type, + self.employee, self.fiscal_year)) + frappe.throw('{0}'.format(leave_allocation[0][0])) + def get_leave_bal(self, prev_fyear): return self.get_leaves_allocated(prev_fyear) - self.get_leaves_applied(prev_fyear) - + def get_leaves_applied(self, fiscal_year): leaves_applied = frappe.db.sql("""select SUM(ifnull(total_leave_days, 0)) from `tabLeave Application` where employee=%s and leave_type=%s - and fiscal_year=%s and docstatus=1""", + and fiscal_year=%s and docstatus=1""", (self.employee, self.leave_type, fiscal_year)) return leaves_applied and flt(leaves_applied[0][0]) or 0 @@ -74,7 +53,7 @@ class LeaveAllocation(Document): and fiscal_year=%s and docstatus=1 and name!=%s""", (self.employee, self.leave_type, fiscal_year, self.name)) return leaves_allocated and flt(leaves_allocated[0][0]) or 0 - + def allow_carry_forward(self): """check whether carry forward is allowed or not for this leave type""" cf = frappe.db.sql("""select is_carry_forward from `tabLeave Type` where name = %s""", @@ -82,15 +61,14 @@ class LeaveAllocation(Document): cf = cf and cint(cf[0][0]) or 0 if not cf: frappe.db.set(self,'carry_forward',0) - msgprint("Sorry! You cannot carry forward %s" % (self.leave_type), - raise_exception=1) + frappe.throw("Cannot carry forward {0}".format(self.leave_type)) def get_carry_forwarded_leaves(self): if self.carry_forward: self.allow_carry_forward() - prev_fiscal_year = frappe.db.sql("""select name from `tabFiscal Year` - where year_start_date = (select date_add(year_start_date, interval -1 year) - from `tabFiscal Year` where name=%s) + prev_fiscal_year = frappe.db.sql("""select name from `tabFiscal Year` + where year_start_date = (select date_add(year_start_date, interval -1 year) + from `tabFiscal Year` where name=%s) order by name desc limit 1""", self.fiscal_year) prev_fiscal_year = prev_fiscal_year and prev_fiscal_year[0][0] or '' prev_bal = 0 @@ -112,10 +90,7 @@ class LeaveAllocation(Document): where employee=%s and leave_type=%s and fiscal_year=%s and docstatus=1""", (self.employee, self.leave_type, self.fiscal_year)) if exists: - msgprint("""Cannot cancel this Leave Allocation as \ - Employee : %s has already applied for %s. - Please check Leave Application: \ - %s""" % \ - (self.employee, self.leave_type, exists[0][0], exists[0][0])) - raise Exception + frappe.msgprint(_("Cannot cancel because Employee {0} is already approved for {1}").format(self.employee, + self.leave_type)) + frappe.throw('{0}'.format(exists[0][0])) diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py index 5de3495ff3..126291191f 100755 --- a/erpnext/hr/doctype/leave_application/leave_application.py +++ b/erpnext/hr/doctype/leave_application/leave_application.py @@ -13,7 +13,7 @@ class LeaveDayBlockedError(frappe.ValidationError): pass class OverlapError(frappe.ValidationError): pass class InvalidLeaveApproverError(frappe.ValidationError): pass class LeaveApproverIdentityError(frappe.ValidationError): pass - + from frappe.model.controller import DocListController class LeaveApplication(DocListController): def setup(self): @@ -21,7 +21,7 @@ class LeaveApplication(DocListController): self.previous_doc = frappe.db.get_value(self.doctype, self.name, "*", as_dict=True) else: self.previous_doc = None - + def validate(self): self.validate_to_date() self.validate_balance_leaves() @@ -30,7 +30,7 @@ class LeaveApplication(DocListController): self.show_block_day_warning() self.validate_block_days() self.validate_leave_approver() - + def on_update(self): if (not self.previous_doc and self.leave_approver) or (self.previous_doc and \ self.status == "Open" and self.previous_doc.leave_approver != self.leave_approver): @@ -40,25 +40,24 @@ class LeaveApplication(DocListController): self.previous_doc.status == "Open" and self.status == "Rejected": # notify employee about rejection self.notify_employee(self.status) - + def on_submit(self): if self.status != "Approved": - frappe.msgprint("""Only Leave Applications with status 'Approved' can be Submitted.""", - raise_exception=True) + frappe.throw(_("Only Leave Applications with status 'Approved' can be submitted")) # notify leave applier about approval self.notify_employee(self.status) - + def on_cancel(self): # notify leave applier about cancellation self.notify_employee("cancelled") def show_block_day_warning(self): - from erpnext.hr.doctype.leave_block_list.leave_block_list import get_applicable_block_dates + from erpnext.hr.doctype.leave_block_list.leave_block_list import get_applicable_block_dates - block_dates = get_applicable_block_dates(self.from_date, self.to_date, + block_dates = get_applicable_block_dates(self.from_date, self.to_date, self.employee, self.company, all_lists=True) - + if block_dates: frappe.msgprint(_("Warning: Leave application contains following block dates") + ":") for d in block_dates: @@ -67,20 +66,20 @@ class LeaveApplication(DocListController): def validate_block_days(self): from erpnext.hr.doctype.leave_block_list.leave_block_list import get_applicable_block_dates - block_dates = get_applicable_block_dates(self.from_date, self.to_date, + block_dates = get_applicable_block_dates(self.from_date, self.to_date, self.employee, self.company) - + if block_dates: if self.status == "Approved": - frappe.msgprint(_("Cannot approve leave as you are not authorized to approve leaves on Block Dates.")) + frappe.msgprint(_("Cannot approve leave as you are not authorized to approve leaves on Block Dates")) raise LeaveDayBlockedError - + def get_holidays(self): - tot_hol = frappe.db.sql("""select count(*) from `tabHoliday` h1, `tabHoliday List` h2, `tabEmployee` e1 - where e1.name = %s and h1.parent = h2.name and e1.holiday_list = h2.name + tot_hol = frappe.db.sql("""select count(*) from `tabHoliday` h1, `tabHoliday List` h2, `tabEmployee` e1 + where e1.name = %s and h1.parent = h2.name and e1.holiday_list = h2.name and h1.holiday_date between %s and %s""", (self.employee, self.from_date, self.to_date)) if not tot_hol: - tot_hol = frappe.db.sql("""select count(*) from `tabHoliday` h1, `tabHoliday List` h2 + tot_hol = frappe.db.sql("""select count(*) from `tabHoliday` h1, `tabHoliday List` h2 where h1.parent = h2.name and h1.holiday_date between %s and %s and ifnull(h2.is_default,0) = 1 and h2.fiscal_year = %s""", (self.from_date, self.to_date, self.fiscal_year)) @@ -100,17 +99,15 @@ class LeaveApplication(DocListController): def validate_to_date(self): if self.from_date and self.to_date and \ (getdate(self.to_date) < getdate(self.from_date)): - msgprint("To date cannot be before from date") - raise Exception - + frappe.throw(_("To date cannot be before from date")) + def validate_balance_leaves(self): if self.from_date and self.to_date: self.total_leave_days = self.get_total_leave_days()["total_leave_days"] - + if self.total_leave_days == 0: - msgprint(_("The day(s) on which you are applying for leave coincide with holiday(s). You need not apply for leave."), - raise_exception=1) - + frappe.throw(_("The day(s) on which you are applying for leave are holiday. You need not apply for leave.")) + if not is_lwp(self.leave_type): self.leave_balance = get_leave_balance(self.employee, self.leave_type, self.fiscal_year)["leave_balance"] @@ -118,94 +115,96 @@ class LeaveApplication(DocListController): if self.status != "Rejected" \ and self.leave_balance - self.total_leave_days < 0: #check if this leave type allow the remaining balance to be in negative. If yes then warn the user and continue to save else warn the user and don't save. - msgprint("There is not enough leave balance for Leave Type: %s" % \ - (self.leave_type,), - raise_exception=not(frappe.db.get_value("Leave Type", self.leave_type,"allow_negative") or None)) - + if frappe.db.get_value("Leave Type", self.leave_type, "allow_negative"): + frappe.msgprint(_("Note: There is not enough leave balance for Leave Type {0}").format(self.leave_type)) + else: + frappe.throw(_("There is not enough leave balance for Leave Type {0}").format(self.leave_type)) + + def validate_leave_overlap(self): if not self.name: self.name = "New Leave Application" - - for d in frappe.db.sql("""select name, leave_type, posting_date, - from_date, to_date - from `tabLeave Application` - where + + for d in frappe.db.sql("""select name, leave_type, posting_date, + from_date, to_date + from `tabLeave Application` + where employee = %(employee)s and docstatus < 2 and status in ("Open", "Approved") - and (from_date between %(from_date)s and %(to_date)s + and (from_date between %(from_date)s and %(to_date)s or to_date between %(from_date)s and %(to_date)s or %(from_date)s between from_date and to_date) and name != %(name)s""", self.as_dict(), as_dict = 1): - - msgprint("Employee : %s has already applied for %s between %s and %s on %s. Please refer Leave Application : %s" % (self.employee, cstr(d['leave_type']), formatdate(d['from_date']), formatdate(d['to_date']), formatdate(d['posting_date']), d['name'], d['name']), raise_exception = OverlapError) + + frappe.msgprint(_("Employee {0} has already applied for {1} between {2} and {3}").format(self.employee, + cstr(d['leave_type']), formatdate(d['from_date']), formatdate(d['to_date']))) + frappe.throw('{0}'.format(d["name"]), OverlapError) def validate_max_days(self): max_days = frappe.db.get_value("Leave Type", self.leave_type, "max_days_allowed") if max_days and self.total_leave_days > max_days: - frappe.throw("Sorry ! You cannot apply for %s for more than %s days" % + frappe.throw("Sorry ! You cannot apply for %s for more than %s days" % (self.leave_type, max_days)) - + def validate_leave_approver(self): employee = frappe.get_doc("Employee", self.employee) - leave_approvers = [l.leave_approver for l in + leave_approvers = [l.leave_approver for l in employee.get("employee_leave_approvers")] - + if len(leave_approvers) and self.leave_approver not in leave_approvers: - msgprint(("[" + _("For Employee") + ' "' + self.employee + '"] ' - + _("Leave Approver can be one of") + ": " - + comma_or(leave_approvers)), raise_exception=InvalidLeaveApproverError) - - elif self.leave_approver and not frappe.db.sql("""select name from `tabUserRole` + frappe.throw(_("Leave approver must be one of {0}").format(comma_or(leave_approvers)), InvalidLeaveApproverError) + + elif self.leave_approver and not frappe.db.sql("""select name from `tabUserRole` where parent=%s and role='Leave Approver'""", self.leave_approver): - msgprint(get_fullname(self.leave_approver) + ": " \ - + _("does not have role 'Leave Approver'"), raise_exception=InvalidLeaveApproverError) - + frappe.throw(_("{0} must have role 'Leave Approver'").format(get_fullname(self.leave_approver)), + InvalidLeaveApproverError) + elif self.docstatus==1 and len(leave_approvers) and self.leave_approver != frappe.session.user: msgprint(_("Only the selected Leave Approver can submit this Leave Application"), raise_exception=LeaveApproverIdentityError) - + def notify_employee(self, status): employee = frappe.get_doc("Employee", self.employee) if not employee.user_id: return - + def _get_message(url=False): if url: name = get_url_to_form(self.doctype, self.name) else: name = self.name - + return (_("Leave Application") + ": %s - %s") % (name, _(status)) - + self.notify({ # for post in messages "message": _get_message(url=True), "message_to": employee.user_id, "subject": _get_message(), }) - + def notify_leave_approver(self): employee = frappe.get_doc("Employee", self.employee) - + def _get_message(url=False): name = self.name employee_name = cstr(employee.employee_name) if url: name = get_url_to_form(self.doctype, self.name) employee_name = get_url_to_form("Employee", self.employee, label=employee_name) - + return (_("New Leave Application") + ": %s - " + _("Employee") + ": %s") % (name, employee_name) - + self.notify({ # for post in messages "message": _get_message(url=True), "message_to": self.leave_approver, - + # for email "subject": _get_message() }) - + def notify(self, args): args = frappe._dict(args) from frappe.core.page.messages.messages import post @@ -213,62 +212,62 @@ class LeaveApplication(DocListController): "notify": cint(self.follow_via_email)}) @frappe.whitelist() -def get_leave_balance(employee, leave_type, fiscal_year): - leave_all = frappe.db.sql("""select total_leaves_allocated +def get_leave_balance(employee, leave_type, fiscal_year): + leave_all = frappe.db.sql("""select total_leaves_allocated from `tabLeave Allocation` where employee = %s and leave_type = %s - and fiscal_year = %s and docstatus = 1""", (employee, + and fiscal_year = %s and docstatus = 1""", (employee, leave_type, fiscal_year)) - + leave_all = leave_all and flt(leave_all[0][0]) or 0 - - leave_app = frappe.db.sql("""select SUM(total_leave_days) - from `tabLeave Application` + + leave_app = frappe.db.sql("""select SUM(total_leave_days) + from `tabLeave Application` where employee = %s and leave_type = %s and fiscal_year = %s and status="Approved" and docstatus = 1""", (employee, leave_type, fiscal_year)) leave_app = leave_app and flt(leave_app[0][0]) or 0 - + ret = {'leave_balance': leave_all - leave_app} return ret def is_lwp(leave_type): lwp = frappe.db.sql("select is_lwp from `tabLeave Type` where name = %s", leave_type) return lwp and cint(lwp[0][0]) or 0 - + @frappe.whitelist() def get_events(start, end): events = [] employee = frappe.db.get_default("employee", frappe.session.user) company = frappe.db.get_default("company", frappe.session.user) - + from frappe.widgets.reportview import build_match_conditions match_conditions = build_match_conditions("Leave Application") - + # show department leaves for employee if "Employee" in frappe.get_roles(): add_department_leaves(events, start, end, employee, company) add_leaves(events, start, end, employee, company, match_conditions) - + add_block_dates(events, start, end, employee, company) add_holidays(events, start, end, employee, company) - + return events - + def add_department_leaves(events, start, end, employee, company): department = frappe.db.get_value("Employee", employee, "department") - + if not department: return - + # department leaves department_employees = frappe.db.sql_list("""select name from tabEmployee where department=%s and company=%s""", (department, company)) - + match_conditions = "employee in (\"%s\")" % '", "'.join(department_employees) add_leaves(events, start, end, employee, company, match_conditions=match_conditions) - + def add_leaves(events, start, end, employee, company, match_conditions=None): - query = """select name, from_date, to_date, employee_name, half_day, + query = """select name, from_date, to_date, employee_name, half_day, status, employee, docstatus from `tabLeave Application` where (from_date between %s and %s or to_date between %s and %s) @@ -276,7 +275,7 @@ def add_leaves(events, start, end, employee, company, match_conditions=None): and status!="Rejected" """ if match_conditions: query += " and " + match_conditions - + for d in frappe.db.sql(query, (start, end, start, end), as_dict=True): e = { "name": d.name, @@ -311,9 +310,9 @@ def add_holidays(events, start, end, employee, company): applicable_holiday_list = frappe.db.get_value("Employee", employee, "holiday_list") if not applicable_holiday_list: return - + for holiday in frappe.db.sql("""select name, holiday_date, description - from `tabHoliday` where parent=%s and holiday_date between %s and %s""", + from `tabHoliday` where parent=%s and holiday_date between %s and %s""", (applicable_holiday_list, start, end), as_dict=True): events.append({ "doctype": "Holiday", @@ -325,24 +324,24 @@ def add_holidays(events, start, end, employee, company): @frappe.whitelist() def query_for_permitted_employees(doctype, txt, searchfield, start, page_len, filters): txt = "%" + cstr(txt) + "%" - + if "Leave Approver" in frappe.user.get_roles(): user = frappe.session.user.replace('"', '\"') condition = """and (exists(select ela.name from `tabEmployee Leave Approver` ela - where ela.parent=`tabEmployee`.name and ela.leave_approver= "%s") or - not exists(select ela.name from `tabEmployee Leave Approver` ela + where ela.parent=`tabEmployee`.name and ela.leave_approver= "%s") or + not exists(select ela.name from `tabEmployee Leave Approver` ela where ela.parent=`tabEmployee`.name) or user_id = "%s")""" % (user, user) else: from frappe.widgets.reportview import build_match_conditions condition = build_match_conditions("Employee") condition = ("and " + condition) if condition else "" - + return frappe.db.sql("""select name, employee_name from `tabEmployee` where status = 'Active' and docstatus < 2 and (`%s` like %s or employee_name like %s) %s order by case when name like %s then 0 else 1 end, case when employee_name like %s then 0 else 1 end, - name limit %s, %s""" % tuple([searchfield] + ["%s"]*2 + [condition] + ["%s"]*4), + name limit %s, %s""" % tuple([searchfield] + ["%s"]*2 + [condition] + ["%s"]*4), (txt, txt, txt, txt, start, page_len)) diff --git a/erpnext/hr/doctype/leave_control_panel/leave_control_panel.py b/erpnext/hr/doctype/leave_control_panel/leave_control_panel.py index 4a8795affd..d3a21fab2b 100644 --- a/erpnext/hr/doctype/leave_control_panel/leave_control_panel.py +++ b/erpnext/hr/doctype/leave_control_panel/leave_control_panel.py @@ -4,16 +4,16 @@ from __future__ import unicode_literals import frappe -from frappe.utils import cint, cstr, flt, nowdate +from frappe.utils import cint, cstr, flt, nowdate, comma_and from frappe import msgprint, _ - + from frappe.model.document import Document class LeaveControlPanel(Document): - def get_employees(self): + def get_employees(self): lst1 = [[self.employee_type,"employment_type"],[self.branch,"branch"],[self.designation,"designation"],[self.department, "department"],[self.grade,"grade"]] condition = "where " flag = 0 @@ -26,7 +26,7 @@ class LeaveControlPanel(Document): flag = 1 emp_query = "select name from `tabEmployee` " if flag == 1: - emp_query += condition + emp_query += condition e = frappe.db.sql(emp_query) return e @@ -41,7 +41,7 @@ class LeaveControlPanel(Document): employees = self.get_employees() if not employees: frappe.throw(_("No employee found")) - + for d in self.get_employees(): try: la = frappe.get_doc('Leave Allocation') @@ -59,4 +59,4 @@ class LeaveControlPanel(Document): except: pass if leave_allocated_for: - msgprint("Leaves Allocated Successfully for " + ", ".join(leave_allocated_for)) + msgprint(_("Leaves Allocated Successfully for {0}").format(comma_and(leave_allocated_for))) diff --git a/erpnext/hr/doctype/salary_manager/salary_manager.py b/erpnext/hr/doctype/salary_manager/salary_manager.py index 05d73c7f49..e73bd69cd7 100644 --- a/erpnext/hr/doctype/salary_manager/salary_manager.py +++ b/erpnext/hr/doctype/salary_manager/salary_manager.py @@ -4,57 +4,56 @@ from __future__ import unicode_literals import frappe from frappe.utils import cint, flt -from frappe import msgprint +from frappe import _ from frappe.model.document import Document class SalaryManager(Document): - + def get_emp_list(self): """ - Returns list of active employees based on selected criteria - and for which salary structure exists + Returns list of active employees based on selected criteria + and for which salary structure exists """ - + cond = self.get_filter_condition() cond += self.get_joining_releiving_condition() - + emp_list = frappe.db.sql(""" select t1.name - from `tabEmployee` t1, `tabSalary Structure` t2 - where t1.docstatus!=2 and t2.docstatus != 2 + from `tabEmployee` t1, `tabSalary Structure` t2 + where t1.docstatus!=2 and t2.docstatus != 2 and t1.name = t2.employee %s """% cond) return emp_list - - + + def get_filter_condition(self): self.check_mandatory() - + cond = '' for f in ['company', 'branch', 'department', 'designation', 'grade']: if self.get(f): - cond += " and t1." + f + " = '" + self.get(f).replace("'", "\'") + "'" - + cond += " and t1." + f + " = '" + self.get(f).replace("'", "\'") + "'" + return cond - + def get_joining_releiving_condition(self): m = self.get_month_details(self.fiscal_year, self.month) cond = """ - and ifnull(t1.date_of_joining, '0000-00-00') <= '%(month_end_date)s' - and ifnull(t1.relieving_date, '2199-12-31') >= '%(month_start_date)s' + and ifnull(t1.date_of_joining, '0000-00-00') <= '%(month_end_date)s' + and ifnull(t1.relieving_date, '2199-12-31') >= '%(month_start_date)s' """ % m return cond - - + + def check_mandatory(self): for f in ['company', 'month', 'fiscal_year']: if not self.get(f): - msgprint("Please select %s to proceed" % f, raise_exception=1) - - + frappe.throw(_("Please set {0}").format(f)) + def get_month_details(self, year, month): ysd = frappe.db.get_value("Fiscal Year", year, "year_start_date") if ysd: @@ -67,22 +66,22 @@ class SalaryManager(Document): month_days = cint(calendar.monthrange(cint(msd.year) ,cint(month))[1]) # days in month med = datetime.date(msd.year, cint(month), month_days) # month end date return { - 'year': msd.year, - 'month_start_date': msd, - 'month_end_date': med, + 'year': msd.year, + 'month_start_date': msd, + 'month_end_date': med, 'month_days': month_days } def create_sal_slip(self): """ Creates salary slip for selected employees if already not created - + """ - + emp_list = self.get_emp_list() ss_list = [] for emp in emp_list: - if not frappe.db.sql("""select name from `tabSalary Slip` + if not frappe.db.sql("""select name from `tabSalary Slip` where docstatus!= 2 and employee = %s and month = %s and fiscal_year = %s and company = %s """, (emp[0], self.month, self.fiscal_year, self.company)): ss = frappe.get_doc({ @@ -95,18 +94,18 @@ class SalaryManager(Document): }) ss.insert() ss_list.append(ss.name) - + return self.create_log(ss_list) - - + + def create_log(self, ss_list): log = "No employee for the above selected criteria OR salary slip already created" if ss_list: log = "Created Salary Slip has been created: \

%s" % '
'.join(ss_list) return log - - + + def get_sal_slip_list(self): """ Returns list of salary slips based on selected criteria @@ -114,17 +113,17 @@ class SalaryManager(Document): """ cond = self.get_filter_condition() ss_list = frappe.db.sql(""" - select t1.name from `tabSalary Slip` t1 + select t1.name from `tabSalary Slip` t1 where t1.docstatus = 0 and month = %s and fiscal_year = %s %s """ % ('%s', '%s', cond), (self.month, self.fiscal_year)) return ss_list - - + + def submit_salary_slip(self): """ Submit all salary slips based on selected criteria """ - ss_list = self.get_sal_slip_list() + ss_list = self.get_sal_slip_list() not_submitted_ss = [] for ss in ss_list: ss_obj = frappe.get_doc("Salary Slip",ss[0]) @@ -132,31 +131,31 @@ class SalaryManager(Document): frappe.db.set(ss_obj, 'email_check', cint(self.send_mail)) if cint(self.send_email) == 1: ss_obj.send_mail_funct() - + frappe.db.set(ss_obj, 'docstatus', 1) except Exception,e: not_submitted_ss.append(ss[0]) - msgprint(e) + frappe.msgprint(e) continue - + return self.create_submit_log(ss_list, not_submitted_ss) - - + + def create_submit_log(self, all_ss, not_submitted_ss): log = '' if not all_ss: log = "No salary slip found to submit for the above selected criteria" else: all_ss = [d[0] for d in all_ss] - - submitted_ss = list(set(all_ss) - set(not_submitted_ss)) + + submitted_ss = list(set(all_ss) - set(not_submitted_ss)) if submitted_ss: mail_sent_msg = self.send_email and " (Mail has been sent to the employee)" or "" log = """ Submitted Salary Slips%s:\

%s

""" % (mail_sent_msg, '
'.join(submitted_ss)) - + if not_submitted_ss: log += """ Not Submitted Salary Slips: \ @@ -167,33 +166,33 @@ class SalaryManager(Document): send mail, uncheck 'Send Email' checkbox.
\ Then try to submit Salary Slip again. """% ('
'.join(not_submitted_ss)) - return log - - + return log + + def get_total_salary(self): """ Get total salary amount from submitted salary slip based on selected criteria """ cond = self.get_filter_condition() tot = frappe.db.sql(""" - select sum(rounded_total) from `tabSalary Slip` t1 + select sum(rounded_total) from `tabSalary Slip` t1 where t1.docstatus = 1 and month = %s and fiscal_year = %s %s """ % ('%s', '%s', cond), (self.month, self.fiscal_year)) - + return flt(tot[0][0]) - - + + def get_acc_details(self): """ get default bank account,default salary acount from company """ amt = self.get_total_salary() - default_bank_account = frappe.db.get_value("Company", self.company, + default_bank_account = frappe.db.get_value("Company", self.company, "default_bank_account") if not default_bank_account: - msgprint("You can set Default Bank Account in Company master.") + frappe.msgprint(_("You can set Default Bank Account in Company master")) return { 'default_bank_account' : default_bank_account, 'amount' : amt - } \ No newline at end of file + } diff --git a/erpnext/hr/doctype/salary_slip/salary_slip.py b/erpnext/hr/doctype/salary_slip/salary_slip.py index 8c34037516..12733e3c06 100644 --- a/erpnext/hr/doctype/salary_slip/salary_slip.py +++ b/erpnext/hr/doctype/salary_slip/salary_slip.py @@ -10,12 +10,12 @@ from frappe.model.naming import make_autoname from frappe import msgprint, _ from erpnext.setup.utils import get_company_currency - + from erpnext.utilities.transaction_base import TransactionBase class SalarySlip(TransactionBase): def autoname(self): - self.name = make_autoname('Sal Slip/' +self.employee + '/.#####') + self.name = make_autoname('Sal Slip/' +self.employee + '/.#####') def get_emp_and_leave_details(self): if self.employee: @@ -25,19 +25,19 @@ class SalarySlip(TransactionBase): self.pull_sal_struct(struct) def check_sal_struct(self): - struct = frappe.db.sql("""select name from `tabSalary Structure` + struct = frappe.db.sql("""select name from `tabSalary Structure` where employee=%s and is_active = 'Yes'""", self.employee) if not struct: - msgprint("Please create Salary Structure for employee '%s'" % self.employee) + msgprint(_("Please create Salary Structure for employee {0}").format(self.employee)) self.employee = None return struct and struct[0][0] or '' def pull_sal_struct(self, struct): from erpnext.hr.doctype.salary_structure.salary_structure import get_mapped_doc self.update(get_mapped_doc(struct, self)) - + def pull_emp_details(self): - emp = frappe.db.get_value("Employee", self.employee, + emp = frappe.db.get_value("Employee", self.employee, ["bank_name", "bank_ac_no", "esic_card_no", "pf_number"], as_dict=1) if emp: self.bank_name = emp.bank_name @@ -50,39 +50,36 @@ class SalarySlip(TransactionBase): self.fiscal_year = frappe.get_default("fiscal_year") if not self.month: self.month = "%02d" % getdate(nowdate()).month - + m = frappe.get_doc('Salary Manager').get_month_details(self.fiscal_year, self.month) holidays = self.get_holidays_for_employee(m) - + if not cint(frappe.db.get_value("HR Settings", "HR Settings", "include_holidays_in_total_working_days")): m["month_days"] -= len(holidays) if m["month_days"] < 0: - msgprint(_("Bummer! There are more holidays than working days this month."), - raise_exception=True) - + frappe.throw(_("There are more holidays than working days this month.")) + if not lwp: lwp = self.calculate_lwp(holidays, m) self.total_days_in_month = m['month_days'] self.leave_without_pay = lwp payment_days = flt(self.get_payment_days(m)) - flt(lwp) self.payment_days = payment_days > 0 and payment_days or 0 - + def get_payment_days(self, m): payment_days = m['month_days'] emp = frappe.db.sql("select date_of_joining, relieving_date from `tabEmployee` \ where name = %s", self.employee, as_dict=1)[0] - + if emp['relieving_date']: if getdate(emp['relieving_date']) > m['month_start_date'] and \ getdate(emp['relieving_date']) < m['month_end_date']: payment_days = getdate(emp['relieving_date']).day elif getdate(emp['relieving_date']) < m['month_start_date']: - frappe.msgprint(_("Relieving Date of employee is ") + cstr(emp['relieving_date'] - + _(". Please set status of the employee as 'Left'")), raise_exception=1) - - + frappe.throw(_("Employee relieved on {0} must be set as 'Left'").format(emp["relieving_date"])) + if emp['date_of_joining']: if getdate(emp['date_of_joining']) > m['month_start_date'] and \ getdate(emp['date_of_joining']) < m['month_end_date']: @@ -91,19 +88,19 @@ class SalarySlip(TransactionBase): payment_days = 0 return payment_days - + def get_holidays_for_employee(self, m): - 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""", + 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, m['month_start_date'], m['month_end_date'])) if not holidays: - holidays = frappe.db.sql("""select t1.holiday_date - from `tabHoliday` t1, `tabHoliday List` t2 - where t1.parent = t2.name and ifnull(t2.is_default, 0) = 1 + holidays = frappe.db.sql("""select t1.holiday_date + from `tabHoliday` t1, `tabHoliday List` t2 + where t1.parent = t2.name and ifnull(t2.is_default, 0) = 1 and t2.fiscal_year = %s - and t1.holiday_date between %s and %s""", (self.fiscal_year, + and t1.holiday_date between %s and %s""", (self.fiscal_year, m['month_start_date'], m['month_end_date'])) holidays = [cstr(i[0]) for i in holidays] return holidays @@ -115,10 +112,10 @@ class SalarySlip(TransactionBase): if dt not in holidays: leave = frappe.db.sql(""" select t1.name, t1.half_day - from `tabLeave Application` t1, `tabLeave Type` t2 - where t2.name = t1.leave_type - and ifnull(t2.is_lwp, 0) = 1 - and t1.docstatus = 1 + from `tabLeave Application` t1, `tabLeave Type` t2 + where t2.name = t1.leave_type + and ifnull(t2.is_lwp, 0) = 1 + and t1.docstatus = 1 and t1.employee = %s and %s between from_date and to_date """, (self.employee, dt)) @@ -127,21 +124,19 @@ class SalarySlip(TransactionBase): return lwp def check_existing(self): - ret_exist = frappe.db.sql("""select name from `tabSalary Slip` - where month = %s and fiscal_year = %s and docstatus != 2 - and employee = %s and name != %s""", + ret_exist = frappe.db.sql("""select name from `tabSalary Slip` + where month = %s and fiscal_year = %s and docstatus != 2 + and employee = %s and name != %s""", (self.month, self.fiscal_year, self.employee, self.name)) if ret_exist: self.employee = '' - msgprint("Salary Slip of employee '%s' already created for this month" - % self.employee, raise_exception=1) - + frappe.throw("Salary Slip of employee {0} already created for this month".format(self.employee)) def validate(self): from frappe.utils import money_in_words self.check_existing() - - if not (len(self.get("earning_details")) or + + if not (len(self.get("earning_details")) or len(self.get("deduction_details"))): self.get_emp_and_leave_details() else: @@ -149,7 +144,7 @@ class SalarySlip(TransactionBase): if not self.net_pay: self.calculate_net_pay() - + company_currency = get_company_currency(self.company) self.total_in_words = money_in_words(self.rounded_total, company_currency) @@ -164,46 +159,46 @@ class SalarySlip(TransactionBase): else: d.e_modified_amount = d.e_amount self.gross_pay += flt(d.e_modified_amount) - + def calculate_ded_total(self): self.total_deduction = 0 for d in self.get('deduction_details'): if cint(d.d_depends_on_lwp) == 1: - d.d_modified_amount = _round(flt(d.d_amount) * flt(self.payment_days) + d.d_modified_amount = _round(flt(d.d_amount) * flt(self.payment_days) / cint(self.total_days_in_month), 2) elif not self.payment_days: d.d_modified_amount = 0 else: d.d_modified_amount = d.d_amount - + self.total_deduction += flt(d.d_modified_amount) - + def calculate_net_pay(self): self.calculate_earning_total() self.calculate_ded_total() self.net_pay = flt(self.gross_pay) - flt(self.total_deduction) - self.rounded_total = _round(self.net_pay) + self.rounded_total = _round(self.net_pay) def on_submit(self): - if(self.email_check == 1): + if(self.email_check == 1): self.send_mail_funct() - - def send_mail_funct(self): + + def send_mail_funct(self): from frappe.utils.email_lib import sendmail receiver = frappe.db.get_value("Employee", self.employee, "company_email") if receiver: subj = 'Salary Slip - ' + cstr(self.month) +'/'+cstr(self.fiscal_year) - earn_ret=frappe.db.sql("""select e_type, e_modified_amount from `tabSalary Slip Earning` + earn_ret=frappe.db.sql("""select e_type, e_modified_amount from `tabSalary Slip Earning` where parent = %s""", self.name) - ded_ret=frappe.db.sql("""select d_type, d_modified_amount from `tabSalary Slip Deduction` + ded_ret=frappe.db.sql("""select d_type, d_modified_amount from `tabSalary Slip Deduction` where parent = %s""", self.name) - + earn_table = '' ded_table = '' - if earn_ret: + if earn_ret: earn_table += "" - + for e in earn_ret: if not e[1]: earn_table += '' % cstr(e[0]) @@ -211,11 +206,11 @@ class SalarySlip(TransactionBase): earn_table += '' \ % (cstr(e[0]), cstr(e[1])) earn_table += '
%s0.00
%s%s
' - + if ded_ret: - + ded_table += "" - + for d in ded_ret: if not d[1]: ded_table +='%s' % cstr(d[0]) @@ -223,10 +218,10 @@ class SalarySlip(TransactionBase): ded_table +='' \ % (cstr(d[0]), cstr(d[1])) ded_table += '
0.00
%s%s
' - - letter_head = frappe.db.get_value("Letter Head", {"is_default": 1, "disabled": 0}, + + letter_head = frappe.db.get_value("Letter Head", {"is_default": 1, "disabled": 0}, "content") - + msg = '''
%s
@@ -248,15 +243,15 @@ class SalarySlip(TransactionBase): - + - + - +
Designation : %s Grade : %s
Bank Account No. : %s Bank Name : %s
Arrear Amount : %s Payment days : %s
@@ -287,14 +282,14 @@ class SalarySlip(TransactionBase): -
Net Pay(in words) : %s
''' % (cstr(letter_head), cstr(self.employee), - cstr(self.employee_name), cstr(self.month), cstr(self.fiscal_year), - cstr(self.department), cstr(self.branch), cstr(self.designation), - cstr(self.grade), cstr(self.bank_account_no), cstr(self.bank_name), - cstr(self.arrear_amount), cstr(self.payment_days), earn_table, ded_table, - cstr(flt(self.gross_pay)), cstr(flt(self.total_deduction)), + ''' % (cstr(letter_head), cstr(self.employee), + cstr(self.employee_name), cstr(self.month), cstr(self.fiscal_year), + cstr(self.department), cstr(self.branch), cstr(self.designation), + cstr(self.grade), cstr(self.bank_account_no), cstr(self.bank_name), + cstr(self.arrear_amount), cstr(self.payment_days), earn_table, ded_table, + cstr(flt(self.gross_pay)), cstr(flt(self.total_deduction)), cstr(flt(self.net_pay)), cstr(self.total_in_words)) sendmail([receiver], subject=subj, msg = msg) else: - msgprint("Company Email ID not found, hence mail not sent") + msgprint(_("Company Email ID not found, hence mail not sent")) diff --git a/erpnext/hr/doctype/salary_structure/salary_structure.py b/erpnext/hr/doctype/salary_structure/salary_structure.py index 2bbc99bf6b..6843644d40 100644 --- a/erpnext/hr/doctype/salary_structure/salary_structure.py +++ b/erpnext/hr/doctype/salary_structure/salary_structure.py @@ -6,7 +6,7 @@ import frappe from frappe.utils import cstr, flt from frappe.model.naming import make_autoname -from frappe import msgprint, _ +from frappe import _ from frappe.model.document import Document @@ -17,7 +17,7 @@ class SalaryStructure(Document): def get_employee_details(self): ret = {} - det = frappe.db.sql("""select employee_name, branch, designation, department, grade + det = frappe.db.sql("""select employee_name, branch, designation, department, grade from `tabEmployee` where name = %s""", self.employee) if det: ret = { @@ -31,7 +31,7 @@ class SalaryStructure(Document): return ret def get_ss_values(self,employee): - basic_info = frappe.db.sql("""select bank_name, bank_ac_no, esic_card_no, pf_number + basic_info = frappe.db.sql("""select bank_name, bank_ac_no, esic_card_no, pf_number from `tabEmployee` where name =%s""", employee) ret = {'bank_name': basic_info and basic_info[0][0] or '', 'bank_ac_no': basic_info and basic_info[0][1] or '', @@ -49,33 +49,32 @@ class SalaryStructure(Document): elif(tab_fname == 'deduction_details'): child.d_type = cstr(li[0]) child.d_modified_amt = 0 - - def make_earn_ded_table(self): + + def make_earn_ded_table(self): self.make_table('Earning Type','earning_details','Salary Structure Earning') self.make_table('Deduction Type','deduction_details', 'Salary Structure Deduction') def check_existing(self): - ret = frappe.db.sql("""select name from `tabSalary Structure` where is_active = 'Yes' + ret = frappe.db.sql("""select name from `tabSalary Structure` where is_active = 'Yes' and employee = %s and name!=%s""", (self.employee,self.name)) if ret and self.is_active=='Yes': - msgprint(_("""Another Salary Structure '%s' is active for employee '%s'. Please make its status 'Inactive' to proceed.""") % - (cstr(ret), self.employee), raise_exception=1) + frappe.throw(_("Another Salary Structure {0} is active for employee {0}. Please make its status 'Inactive' to proceed.").format(cstr(ret), self.employee)) def validate_amount(self): if flt(self.net_pay) < 0: - msgprint(_("Net pay can not be negative"), raise_exception=1) + frappe.throw(_("Net pay cannot be negative")) - def validate(self): + def validate(self): self.check_existing() self.validate_amount() - + @frappe.whitelist() def make_salary_slip(source_name, target_doc=None): return get_mapped_doc(source_name, target_doc).as_dict() - + def get_mapped_doc(source_name, target_doc=None): from frappe.model.mapper import get_mapped_doc - + def postprocess(source, target): sal_slip = frappe.get_doc(target) sal_slip.run_method("pull_emp_details") @@ -84,24 +83,24 @@ def get_mapped_doc(source_name, target_doc=None): doc = get_mapped_doc("Salary Structure", source_name, { "Salary Structure": { - "doctype": "Salary Slip", + "doctype": "Salary Slip", "field_map": { "total_earning": "gross_pay" } - }, + }, "Salary Structure Deduction": { - "doctype": "Salary Slip Deduction", + "doctype": "Salary Slip Deduction", "field_map": [ ["depend_on_lwp", "d_depends_on_lwp"], ["d_modified_amt", "d_amount"], ["d_modified_amt", "d_modified_amount"] ], "add_if_empty": True - }, + }, "Salary Structure Earning": { - "doctype": "Salary Slip Earning", + "doctype": "Salary Slip Earning", "field_map": [ - ["depend_on_lwp", "e_depends_on_lwp"], + ["depend_on_lwp", "e_depends_on_lwp"], ["modified_value", "e_modified_amount"], ["modified_value", "e_amount"] ], diff --git a/erpnext/hr/doctype/upload_attendance/upload_attendance.py b/erpnext/hr/doctype/upload_attendance/upload_attendance.py index 1ba31e9f20..af86eb97e0 100644 --- a/erpnext/hr/doctype/upload_attendance/upload_attendance.py +++ b/erpnext/hr/doctype/upload_attendance/upload_attendance.py @@ -6,7 +6,7 @@ from __future__ import unicode_literals import frappe from frappe.utils import cstr, add_days, date_diff -from frappe import msgprint, _ +from frappe import _ from frappe.utils.datautils import UnicodeWriter from frappe.model.document import Document @@ -17,32 +17,32 @@ class UploadAttendance(Document): def get_template(): if not frappe.has_permission("Attendance", "create"): raise frappe.PermissionError - + args = frappe.local.form_dict w = UnicodeWriter() w = add_header(w) - + w = add_data(w, args) # write out response as a type csv frappe.response['result'] = cstr(w.getvalue()) frappe.response['type'] = 'csv' frappe.response['doctype'] = "Attendance" - + def add_header(w): status = ", ".join((frappe.get_meta("Attendance").get_field("status").options or "").strip().split("\n")) w.writerow(["Notes:"]) w.writerow(["Please do not change the template headings"]) w.writerow(["Status should be one of these values: " + status]) w.writerow(["If you are overwriting existing attendance records, 'ID' column mandatory"]) - w.writerow(["ID", "Employee", "Employee Name", "Date", "Status", + w.writerow(["ID", "Employee", "Employee Name", "Date", "Status", "Fiscal Year", "Company", "Naming Series"]) return w - + def add_data(w, args): from erpnext.accounts.utils import get_fiscal_year - + dates = get_dates(args) employees = get_active_employees() existing_attendance_records = get_existing_attendance_records(args) @@ -54,9 +54,9 @@ def add_data(w, args): existing_attendance = existing_attendance_records[tuple([date, employee.name])] row = [ existing_attendance and existing_attendance.name or "", - employee.name, employee.employee_name, date, + employee.name, employee.employee_name, date, existing_attendance and existing_attendance.status or "", - get_fiscal_year(date)[0], employee.company, + get_fiscal_year(date)[0], employee.company, existing_attendance and existing_attendance.naming_series or get_naming_series(), ] w.writerow(row) @@ -67,28 +67,27 @@ def get_dates(args): no_of_days = date_diff(add_days(args["to_date"], 1), args["from_date"]) dates = [add_days(args["from_date"], i) for i in range(0, no_of_days)] return dates - + def get_active_employees(): - employees = frappe.db.sql("""select name, employee_name, company + employees = frappe.db.sql("""select name, employee_name, company from tabEmployee where docstatus < 2 and status = 'Active'""", as_dict=1) return employees - + def get_existing_attendance_records(args): - attendance = frappe.db.sql("""select name, att_date, employee, status, naming_series - from `tabAttendance` where att_date between %s and %s and docstatus < 2""", + attendance = frappe.db.sql("""select name, att_date, employee, status, naming_series + from `tabAttendance` where att_date between %s and %s and docstatus < 2""", (args["from_date"], args["to_date"]), as_dict=1) - + existing_attendance = {} for att in attendance: existing_attendance[tuple([att.att_date, att.employee])] = att - + return existing_attendance - + def get_naming_series(): series = frappe.get_meta("Attendance").get_field("naming_series").options.strip().split("\n") if not series: - msgprint("""Please create naming series for Attendance \ - through Setup -> Numbering Series.""", raise_exception=1) + frappe.throw(_("Please setup numbering series for Attendance via Setup > Numbering Series")) return series[0] @@ -96,10 +95,10 @@ def get_naming_series(): def upload(): if not frappe.has_permission("Attendance", "create"): raise frappe.PermissionError - + from frappe.utils.datautils import read_csv_content_from_uploaded_file from frappe.modules import scrub - + rows = read_csv_content_from_uploaded_file() if not rows: msg = [_("Please select a csv file")] @@ -109,10 +108,9 @@ def upload(): columns[3] = "att_date" ret = [] error = False - + from frappe.utils.datautils import check_record, import_doc - doctype_dl = frappe.get_meta("Attendance") - + for i, row in enumerate(rows[5:]): if not row: continue row_idx = i + 5 @@ -120,18 +118,18 @@ def upload(): d["doctype"] = "Attendance" if d.name: d["docstatus"] = frappe.db.get_value("Attendance", d.name, "docstatus") - + try: check_record(d) ret.append(import_doc(d, "Attendance", 1, row_idx, submit=True)) except Exception, e: error = True - ret.append('Error for row (#%d) %s : %s' % (row_idx, + ret.append('Error for row (#%d) %s : %s' % (row_idx, len(row)>1 and row[1] or "", cstr(e))) frappe.errprint(frappe.get_traceback()) if error: - frappe.db.rollback() + frappe.db.rollback() else: frappe.db.commit() return {"messages": ret, "error": error} diff --git a/erpnext/hr/utils.py b/erpnext/hr/utils.py index fc9e7a23a6..87a9e0b68a 100644 --- a/erpnext/hr/utils.py +++ b/erpnext/hr/utils.py @@ -10,8 +10,8 @@ def get_leave_approver_list(): roles = [r[0] for r in frappe.db.sql("""select distinct parent from `tabUserRole` where role='Leave Approver'""")] if not roles: - frappe.msgprint(_("No Leave Approvers. Please assign 'Leave Approver' Role to atleast one user.")) - + frappe.msgprint(_("No Leave Approvers. Please assign 'Leave Approver' Role to atleast one user")) + return roles @@ -20,6 +20,5 @@ def get_expense_approver_list(): roles = [r[0] for r in frappe.db.sql("""select distinct parent from `tabUserRole` where role='Expense Approver'""")] if not roles: - frappe.msgprint("No Expense Approvers. Please assign 'Expense Approver' \ - Role to atleast one user.") + frappe.msgprint(_("No Expense Approvers. Please assign 'Expense Approver' Role to atleast one user")) return roles diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py index 206c963046..40218ce0f2 100644 --- a/erpnext/manufacturing/doctype/bom/bom.py +++ b/erpnext/manufacturing/doctype/bom/bom.py @@ -5,10 +5,7 @@ from __future__ import unicode_literals import frappe from frappe.utils import cint, cstr, flt, now, nowdate -from frappe import msgprint, _ - - - +from frappe import _ from frappe.model.document import Document class BOM(Document): @@ -64,11 +61,7 @@ class BOM(Document): def validate_rm_item(self, item): if item[0]['name'] == self.item: - msgprint("Item_code: %s in materials tab cannot be same as FG Item", - item[0]['name'], raise_exception=1) - - if not item or item[0]['docstatus'] == 2: - msgprint("Item %s does not exist in system" % item[0]['item_code'], raise_exception = 1) + frappe.throw(_("Raw material cannot be same as main Item")) def set_bom_material_details(self): for item in self.get("bom_materials"): @@ -188,12 +181,10 @@ class BOM(Document): """ Validate main FG item""" item = self.get_item_det(self.item) if not item: - msgprint("Item %s does not exists in the system or expired." % - self.item, raise_exception = 1) + frappe.throw(_("Item {0} does not exists in the system or has expired").format(self.item)) elif item[0]['is_manufactured_item'] != 'Yes' \ and item[0]['is_sub_contracted_item'] != 'Yes': - msgprint("""As Item: %s is not a manufactured / sub-contracted item, \ - you can not make BOM for it""" % self.item, raise_exception = 1) + frappe.throw(_("Item {0} must be manufactured or sub-contracted").format(self.item)) else: ret = frappe.db.get_value("Item", self.item, ["description", "stock_uom"]) self.description = ret[0] @@ -204,8 +195,7 @@ class BOM(Document): self.op = [] for d in self.get('bom_operations'): if cstr(d.operation_no) in self.op: - msgprint("Operation no: %s is repeated in Operations Table" % - d.operation_no, raise_exception=1) + frappe.throw(_("Operation {0} is repeated in Operations Table").format(d.operation_no)) else: # add operation in op list self.op.append(cstr(d.operation_no)) @@ -216,26 +206,20 @@ class BOM(Document): for m in self.get('bom_materials'): # check if operation no not in op table if self.with_operations and cstr(m.operation_no) not in self.op: - msgprint("""Operation no: %s against item: %s at row no: %s \ - is not present at Operations table""" % - (m.operation_no, m.item_code, m.idx), raise_exception = 1) + frappe.throw(_("Operation {0} not present in Operations Table").format(m.operation_no)) item = self.get_item_det(m.item_code) if item[0]['is_manufactured_item'] == 'Yes': if not m.bom_no: - msgprint("Please enter BOM No aginst item: %s at row no: %s" % - (m.item_code, m.idx), raise_exception=1) + frappe.throw(_("BOM number is required for manufactured Item {0} in row {1}").format(m.item, m.idx)) else: self.validate_bom_no(m.item_code, m.bom_no, m.idx) elif m.bom_no: - msgprint("""As Item %s is not a manufactured / sub-contracted item, \ - you can not enter BOM against it (Row No: %s).""" % - (m.item_code, m.idx), raise_exception = 1) + frappe.throw(_("BOM number not allowed for non-manufactured Item {0} in row {1}").format(m.item_code, m.idx)) if flt(m.qty) <= 0: - msgprint("Please enter qty against raw material: %s at row no: %s" % - (m.item_code, m.idx), raise_exception = 1) + frappe.throw(_("Quantity required for Item {0} in row {1}").format(m.item_code, m.idx)) self.check_if_item_repeated(m.item_code, m.operation_no, check_list) @@ -245,14 +229,11 @@ class BOM(Document): and is_active=1 and docstatus=1""", (bom_no, item), as_dict =1) if not bom: - msgprint("""Incorrect BOM No: %s against item: %s at row no: %s. - It may be inactive or not submitted or does not belong to this item.""" % - (bom_no, item, idx), raise_exception = 1) + frappe.throw(_("BOM {0} for Item {1} in row {2} is inactive or not submitted").format(bom_no, item, idx)) def check_if_item_repeated(self, item, op, check_list): if [cstr(item), cstr(op)] in check_list: - msgprint(_("Item") + " %s " % (item,) + _("has been entered atleast twice") - + (cstr(op) and _(" against same operation") or ""), raise_exception=1) + frappe.throw(_("Item {0} has been entered multiple times against same operation").format(item)) else: check_list.append([cstr(item), cstr(op)]) @@ -268,8 +249,7 @@ class BOM(Document): count = count + 1 for b in boms: if b[0] == self.name: - msgprint("""Recursion Occured => '%s' cannot be '%s' of '%s'. - """ % (cstr(b[0]), cstr(d[2]), self.name), raise_exception = 1) + frappe.throw(_("BOM recursion: {0} cannot be parent or child of {2}").format(b[0], self.name)) if b[0]: bom_list.append(b[0]) @@ -389,12 +369,9 @@ class BOM(Document): and docstatus = 1 and is_active = 1)""", self.name) if act_pbom and act_pbom[0][0]: - action = self.docstatus < 2 and _("deactivate") or _("cancel") - msgprint(_("Cannot ") + action + _(": It is linked to other active BOM(s)"), - raise_exception=1) + frappe.throw(_("Cannot deactive or cancle BOM as it is linked with other BOMs")) def get_bom_items_as_dict(bom, qty=1, fetch_exploded=1): - import json item_dict = {} query = """select diff --git a/erpnext/manufacturing/doctype/bom_replace_tool/bom_replace_tool.py b/erpnext/manufacturing/doctype/bom_replace_tool/bom_replace_tool.py index b772fcb3d3..63030b588b 100644 --- a/erpnext/manufacturing/doctype/bom_replace_tool/bom_replace_tool.py +++ b/erpnext/manufacturing/doctype/bom_replace_tool/bom_replace_tool.py @@ -4,8 +4,8 @@ from __future__ import unicode_literals import frappe from frappe.utils import cstr, flt -from frappe import msgprint, _ - +from frappe import _ + from frappe.model.document import Document class BOMReplaceTool(Document): @@ -17,22 +17,22 @@ class BOMReplaceTool(Document): for bom in bom_list: bom_obj = frappe.get_doc("BOM", bom) updated_bom = bom_obj.update_cost_and_exploded_items(updated_bom) - + frappe.msgprint(_("BOM replaced")) def validate_bom(self): if cstr(self.current_bom) == cstr(self.new_bom): - msgprint("Current BOM and New BOM can not be same", raise_exception=1) - + frappe.throw(_("Current BOM and New BOM can not be same")) + def update_new_bom(self): - current_bom_unitcost = frappe.db.sql("""select total_cost/quantity + current_bom_unitcost = frappe.db.sql("""select total_cost/quantity from `tabBOM` where name = %s""", self.current_bom) current_bom_unitcost = current_bom_unitcost and flt(current_bom_unitcost[0][0]) or 0 - frappe.db.sql("""update `tabBOM Item` set bom_no=%s, - rate=%s, amount=qty*%s where bom_no = %s and docstatus < 2""", + frappe.db.sql("""update `tabBOM Item` set bom_no=%s, + rate=%s, amount=qty*%s where bom_no = %s and docstatus < 2""", (self.new_bom, current_bom_unitcost, current_bom_unitcost, self.current_bom)) - + def get_parent_boms(self): - return [d[0] for d in frappe.db.sql("""select distinct parent + return [d[0] for d in frappe.db.sql("""select distinct parent from `tabBOM Item` where ifnull(bom_no, '') = %s and docstatus < 2""", - self.new_bom)] \ No newline at end of file + self.new_bom)] diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py index af92413be6..78270e53ca 100644 --- a/erpnext/manufacturing/doctype/production_order/production_order.py +++ b/erpnext/manufacturing/doctype/production_order/production_order.py @@ -16,31 +16,31 @@ class ProductionOrder(Document): def validate(self): if self.docstatus == 0: self.status = "Draft" - + from erpnext.utilities import validate_status - validate_status(self.status, ["Draft", "Submitted", "Stopped", + validate_status(self.status, ["Draft", "Submitted", "Stopped", "In Process", "Completed", "Cancelled"]) self.validate_bom_no() self.validate_sales_order() self.validate_warehouse() - + from erpnext.utilities.transaction_base import validate_uom_is_integer validate_uom_is_integer(self, "stock_uom", ["qty", "produced_qty"]) - + def validate_bom_no(self): if self.bom_no: - bom = frappe.db.sql("""select name from `tabBOM` where name=%s and docstatus=1 + bom = frappe.db.sql("""select name from `tabBOM` where name=%s and docstatus=1 and is_active=1 and item=%s""" , (self.bom_no, self.production_item), as_dict =1) if not bom: - frappe.throw("""Incorrect BOM: %s entered. - May be BOM not exists or inactive or not submitted + frappe.throw("""Incorrect BOM: %s entered. + May be BOM not exists or inactive or not submitted or for some other item.""" % cstr(self.bom_no)) - + def validate_sales_order(self): if self.sales_order: - so = frappe.db.sql("""select name, delivery_date from `tabSales Order` + so = frappe.db.sql("""select name, delivery_date from `tabSales Order` where name=%s and docstatus = 1""", self.sales_order, as_dict=1)[0] if not so.name: @@ -48,39 +48,39 @@ class ProductionOrder(Document): if not self.expected_delivery_date: self.expected_delivery_date = so.delivery_date - + self.validate_production_order_against_so() - + def validate_warehouse(self): from erpnext.stock.utils import validate_warehouse_company - + for w in [self.fg_warehouse, self.wip_warehouse]: validate_warehouse_company(w, self.company) - + def validate_production_order_against_so(self): # already ordered qty ordered_qty_against_so = frappe.db.sql("""select sum(qty) from `tabProduction Order` - where production_item = %s and sales_order = %s and docstatus < 2 and name != %s""", + where production_item = %s and sales_order = %s and docstatus < 2 and name != %s""", (self.production_item, self.sales_order, self.name))[0][0] total_qty = flt(ordered_qty_against_so) + flt(self.qty) - + # get qty from Sales Order Item table - so_item_qty = frappe.db.sql("""select sum(qty) from `tabSales Order Item` - where parent = %s and item_code = %s""", + so_item_qty = frappe.db.sql("""select sum(qty) from `tabSales Order Item` + where parent = %s and item_code = %s""", (self.sales_order, self.production_item))[0][0] # get qty from Packing Item table - dnpi_qty = frappe.db.sql("""select sum(qty) from `tabPacked Item` - where parent = %s and parenttype = 'Sales Order' and item_code = %s""", + dnpi_qty = frappe.db.sql("""select sum(qty) from `tabPacked Item` + where parent = %s and parenttype = 'Sales Order' and item_code = %s""", (self.sales_order, self.production_item))[0][0] # total qty in SO so_qty = flt(so_item_qty) + flt(dnpi_qty) - + if total_qty > so_qty: - frappe.throw(_("Total production order qty for item") + ": " + - cstr(self.production_item) + _(" against sales order") + ": " + - cstr(self.sales_order) + _(" will be ") + cstr(total_qty) + ", " + - _("which is greater than sales order qty ") + "(" + cstr(so_qty) + ")" + + frappe.throw(_("Total production order qty for item") + ": " + + cstr(self.production_item) + _(" against sales order") + ": " + + cstr(self.sales_order) + _(" will be ") + cstr(total_qty) + ", " + + _("which is greater than sales order qty ") + "(" + cstr(so_qty) + ")" + _("Please reduce qty."), exc=OverProductionError) def stop_unstop(self, status): @@ -88,7 +88,7 @@ class ProductionOrder(Document): self.update_status(status) qty = (flt(self.qty)-flt(self.produced_qty)) * ((status == 'Stopped') and -1 or 1) self.update_planned_qty(qty) - msgprint("Production Order has been %s" % status) + frappe.msgprint(_("Production Order status is {0}").format(status)) def update_status(self, status): @@ -108,14 +108,14 @@ class ProductionOrder(Document): frappe.throw(_("WIP Warehouse required before Submit")) frappe.db.set(self,'status', 'Submitted') self.update_planned_qty(self.qty) - + def on_cancel(self): # Check whether any stock entry exists against this Production Order - stock_entry = frappe.db.sql("""select name from `tabStock Entry` + stock_entry = frappe.db.sql("""select name from `tabStock Entry` where production_order = %s and docstatus = 1""", self.name) if stock_entry: - frappe.throw("""Submitted Stock Entry %s exists against this production order. + frappe.throw("""Submitted Stock Entry %s exists against this production order. Hence can not be cancelled.""" % stock_entry[0][0]) frappe.db.set(self,'status', 'Cancelled') @@ -132,27 +132,27 @@ class ProductionOrder(Document): from erpnext.stock.utils import update_bin update_bin(args) -@frappe.whitelist() +@frappe.whitelist() def get_item_details(item): res = frappe.db.sql("""select stock_uom, description from `tabItem` where (ifnull(end_of_life, "")="" or end_of_life > now()) and name=%s""", item, as_dict=1) - + if not res: return {} - + res = res[0] - bom = frappe.db.sql("""select name from `tabBOM` where item=%s + bom = frappe.db.sql("""select name from `tabBOM` where item=%s and ifnull(is_default, 0)=1""", item) if bom: res.bom_no = bom[0][0] - + return res @frappe.whitelist() def make_stock_entry(production_order_id, purpose): production_order = frappe.get_doc("Production Order", production_order_id) - + stock_entry = frappe.new_doc("Stock Entry") stock_entry.purpose = purpose stock_entry.production_order = production_order_id @@ -160,12 +160,12 @@ def make_stock_entry(production_order_id, purpose): stock_entry.bom_no = production_order.bom_no stock_entry.use_multi_level_bom = production_order.use_multi_level_bom stock_entry.fg_completed_qty = flt(production_order.qty) - flt(production_order.produced_qty) - + if purpose=="Material Transfer": stock_entry.to_warehouse = production_order.wip_warehouse else: stock_entry.from_warehouse = production_order.wip_warehouse stock_entry.to_warehouse = production_order.fg_warehouse - + stock_entry.run_method("get_items") return stock_entry.as_dict() diff --git a/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py b/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py index e3fe7c3d9a..5556fbe113 100644 --- a/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py +++ b/erpnext/manufacturing/doctype/production_planning_tool/production_planning_tool.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import frappe -from frappe.utils import cstr, flt, cint, nowdate, add_days +from frappe.utils import cstr, flt, cint, nowdate, add_days, comma_and from frappe import msgprint, _ @@ -16,19 +16,19 @@ class ProductionPlanningTool(Document): def get_so_details(self, so): """Pull other details from so""" - so = frappe.db.sql("""select transaction_date, customer, grand_total + so = frappe.db.sql("""select transaction_date, customer, grand_total from `tabSales Order` where name = %s""", so, as_dict = 1) ret = { 'sales_order_date': so and so[0]['transaction_date'] or '', 'customer' : so[0]['customer'] or '', 'grand_total': so[0]['grand_total'] } - return ret - + return ret + def get_item_details(self, item_code): """ Pull other item details from item master""" - item = frappe.db.sql("""select description, stock_uom, default_bom + item = frappe.db.sql("""select description, stock_uom, default_bom from `tabItem` where name = %s""", item_code, as_dict =1) ret = { 'description' : item and item[0]['description'], @@ -42,7 +42,7 @@ class ProductionPlanningTool(Document): def clear_item_table(self): self.set('pp_details', []) - + def validate_company(self): if not self.company: frappe.throw(_("Please enter Company")) @@ -56,10 +56,10 @@ class ProductionPlanningTool(Document): so_filter += ' and so.transaction_date <= "' + self.to_date + '"' if self.customer: so_filter += ' and so.customer = "' + self.customer + '"' - + if self.fg_item: item_filter += ' and item.name = "' + self.fg_item + '"' - + open_so = frappe.db.sql(""" select distinct so.name, so.transaction_date, so.customer, so.grand_total from `tabSales Order` so, `tabSales Order Item` so_item @@ -68,15 +68,15 @@ class ProductionPlanningTool(Document): and so.company = %s and ifnull(so_item.qty, 0) > ifnull(so_item.delivered_qty, 0) %s and (exists (select name from `tabItem` item where item.name=so_item.item_code - and (ifnull(item.is_pro_applicable, 'No') = 'Yes' + and (ifnull(item.is_pro_applicable, 'No') = 'Yes' or ifnull(item.is_sub_contracted_item, 'No') = 'Yes') %s) or exists (select name from `tabPacked Item` pi where pi.parent = so.name and pi.parent_item = so_item.item_code and exists (select name from `tabItem` item where item.name=pi.item_code - and (ifnull(item.is_pro_applicable, 'No') = 'Yes' + and (ifnull(item.is_pro_applicable, 'No') = 'Yes' or ifnull(item.is_sub_contracted_item, 'No') = 'Yes') %s))) """ % ('%s', so_filter, item_filter, item_filter), self.company, as_dict=1) - + self.add_so_in_table(open_so) def add_so_in_table(self, open_so): @@ -94,7 +94,7 @@ class ProductionPlanningTool(Document): def get_items_from_so(self): """ Pull items from Sales Order, only proction item - and subcontracted item will be pulled from Packing item + and subcontracted item will be pulled from Packing item and add items in the table """ items = self.get_items() @@ -105,36 +105,36 @@ class ProductionPlanningTool(Document): if not so_list: msgprint(_("Please enter sales order in the above table")) return [] - + items = frappe.db.sql("""select distinct parent, item_code, warehouse, (qty - ifnull(delivered_qty, 0)) as pending_qty from `tabSales Order Item` so_item where parent in (%s) and docstatus = 1 and ifnull(qty, 0) > ifnull(delivered_qty, 0) and exists (select * from `tabItem` item where item.name=so_item.item_code - and (ifnull(item.is_pro_applicable, 'No') = 'Yes' + and (ifnull(item.is_pro_applicable, 'No') = 'Yes' or ifnull(item.is_sub_contracted_item, 'No') = 'Yes'))""" % \ (", ".join(["%s"] * len(so_list))), tuple(so_list), as_dict=1) - + packed_items = frappe.db.sql("""select distinct pi.parent, pi.item_code, pi.warehouse as reserved_warhouse, - (((so_item.qty - ifnull(so_item.delivered_qty, 0)) * pi.qty) / so_item.qty) + (((so_item.qty - ifnull(so_item.delivered_qty, 0)) * pi.qty) / so_item.qty) as pending_qty from `tabSales Order Item` so_item, `tabPacked Item` pi - where so_item.parent = pi.parent and so_item.docstatus = 1 + where so_item.parent = pi.parent and so_item.docstatus = 1 and pi.parent_item = so_item.item_code and so_item.parent in (%s) and ifnull(so_item.qty, 0) > ifnull(so_item.delivered_qty, 0) and exists (select * from `tabItem` item where item.name=pi.item_code - and (ifnull(item.is_pro_applicable, 'No') = 'Yes' + and (ifnull(item.is_pro_applicable, 'No') = 'Yes' or ifnull(item.is_sub_contracted_item, 'No') = 'Yes'))""" % \ (", ".join(["%s"] * len(so_list))), tuple(so_list), as_dict=1) return items + packed_items - + def add_items(self, items): self.clear_item_table() for p in items: - item_details = frappe.db.sql("""select description, stock_uom, default_bom + item_details = frappe.db.sql("""select description, stock_uom, default_bom from tabItem where name=%s""", p['item_code']) pi = self.append('pp_details', {}) pi.sales_order = p['parent'] @@ -145,27 +145,27 @@ class ProductionPlanningTool(Document): pi.bom_no = item_details and item_details[0][2] or '' pi.so_pending_qty = flt(p['pending_qty']) pi.planned_qty = flt(p['pending_qty']) - + def validate_data(self): self.validate_company() for d in self.get('pp_details'): self.validate_bom_no(d) if not flt(d.planned_qty): - frappe.throw("Please Enter Planned Qty for item: %s at row no: %s" % + frappe.throw("Please Enter Planned Qty for item: %s at row no: %s" % (d.item_code, d.idx)) - + def validate_bom_no(self, d): if not d.bom_no: - frappe.throw("Please enter bom no for item: %s at row no: %s" % + frappe.throw("Please enter bom no for item: %s at row no: %s" % (d.item_code, d.idx)) else: - bom = frappe.db.sql("""select name from `tabBOM` where name = %s and item = %s - and docstatus = 1 and is_active = 1""", + bom = frappe.db.sql("""select name from `tabBOM` where name = %s and item = %s + and docstatus = 1 and is_active = 1""", (d.bom_no, d.item_code), as_dict = 1) if not bom: frappe.throw("""Incorrect BOM No: %s entered for item: %s at row no: %s - May be BOM is inactive or for other item or does not exists in the system""" % + May be BOM is inactive or for other item or does not exists in the system""" % (d.bom_no, d.item_doce, d.idx)) def raise_production_order(self): @@ -180,9 +180,9 @@ class ProductionPlanningTool(Document): if pro: pro = ["""%s""" % \ (p, p) for p in pro] - msgprint(_("Production Order(s) created:\n\n") + '\n'.join(pro)) + msgprint(_("{0} created").format(comma_and(pro))) else : - msgprint(_("No Production Order created.")) + msgprint(_("No Production Orders created")) def get_distinct_items_and_boms(self): """ Club similar BOM and item for processing @@ -191,7 +191,7 @@ class ProductionPlanningTool(Document): } """ item_dict, bom_dict = {}, {} - for d in self.get("pp_details"): + for d in self.get("pp_details"): bom_dict.setdefault(d.bom_no, []).append([d.sales_order, flt(d.planned_qty)]) item_dict[(d.item_code, d.sales_order, d.warehouse)] = { "production_item" : d.item_code, @@ -207,7 +207,7 @@ class ProductionPlanningTool(Document): "status" : "Draft", } return bom_dict, item_dict - + def create_production_order(self, items): """Create production order. Called from Production Planning Tool""" from erpnext.manufacturing.doctype.production_order.production_order import OverProductionError @@ -216,16 +216,16 @@ class ProductionPlanningTool(Document): for key in items: pro = frappe.new_doc("Production Order") pro.update(items[key]) - + frappe.flags.mute_messages = True try: pro.insert() pro_list.append(pro.name) - except OverProductionError, e: + except OverProductionError: pass - + frappe.flags.mute_messages = False - + return pro_list def download_raw_materials(self): @@ -236,41 +236,41 @@ class ProductionPlanningTool(Document): return self.get_csv() def get_raw_materials(self, bom_dict): - """ Get raw materials considering sub-assembly items + """ Get raw materials considering sub-assembly items { "item_code": [qty_required, description, stock_uom, min_order_qty] } """ item_list = [] - + for bom, so_wise_qty in bom_dict.items(): bom_wise_item_details = {} if self.use_multi_level_bom: - # get all raw materials with sub assembly childs - for d in frappe.db.sql("""select fb.item_code, - ifnull(sum(fb.qty_consumed_per_unit), 0) as qty, - fb.description, fb.stock_uom, it.min_order_qty - from `tabBOM Explosion Item` fb,`tabItem` it - where it.name = fb.item_code and ifnull(it.is_pro_applicable, 'No') = 'No' - and ifnull(it.is_sub_contracted_item, 'No') = 'No' - and fb.docstatus<2 and fb.parent=%s + # get all raw materials with sub assembly childs + for d in frappe.db.sql("""select fb.item_code, + ifnull(sum(fb.qty_consumed_per_unit), 0) as qty, + fb.description, fb.stock_uom, it.min_order_qty + from `tabBOM Explosion Item` fb,`tabItem` it + where it.name = fb.item_code and ifnull(it.is_pro_applicable, 'No') = 'No' + and ifnull(it.is_sub_contracted_item, 'No') = 'No' + and fb.docstatus<2 and fb.parent=%s group by item_code, stock_uom""", bom, as_dict=1): bom_wise_item_details.setdefault(d.item_code, d) else: - # Get all raw materials considering SA items as raw materials, + # Get all raw materials considering SA items as raw materials, # so no childs of SA items - for d in frappe.db.sql("""select bom_item.item_code, - ifnull(sum(bom_item.qty_consumed_per_unit), 0) as qty, - bom_item.description, bom_item.stock_uom, item.min_order_qty - from `tabBOM Item` bom_item, tabItem item - where bom_item.parent = %s and bom_item.docstatus < 2 - and bom_item.item_code = item.name + for d in frappe.db.sql("""select bom_item.item_code, + ifnull(sum(bom_item.qty_consumed_per_unit), 0) as qty, + bom_item.description, bom_item.stock_uom, item.min_order_qty + from `tabBOM Item` bom_item, tabItem item + where bom_item.parent = %s and bom_item.docstatus < 2 + and bom_item.item_code = item.name group by item_code""", bom, as_dict=1): bom_wise_item_details.setdefault(d.item_code, d) for item, item_details in bom_wise_item_details.items(): for so_qty in so_wise_qty: - item_list.append([item, flt(item_details.qty) * so_qty[1], item_details.description, + item_list.append([item, flt(item_details.qty) * so_qty[1], item_details.description, item_details.stock_uom, item_details.min_order_qty, so_qty[0]]) self.make_items_dict(item_list) @@ -286,18 +286,18 @@ class ProductionPlanningTool(Document): total_qty = sum([flt(d[0]) for d in self.item_dict[item]]) for item_details in self.item_dict[item]: item_list.append([item, item_details[1], item_details[2], item_details[0]]) - item_qty = frappe.db.sql("""select warehouse, indented_qty, ordered_qty, actual_qty + item_qty = frappe.db.sql("""select warehouse, indented_qty, ordered_qty, actual_qty from `tabBin` where item_code = %s""", item, as_dict=1) i_qty, o_qty, a_qty = 0, 0, 0 for w in item_qty: i_qty, o_qty, a_qty = i_qty + flt(w.indented_qty), o_qty + flt(w.ordered_qty), a_qty + flt(w.actual_qty) - item_list.append(['', '', '', '', w.warehouse, flt(w.indented_qty), + item_list.append(['', '', '', '', w.warehouse, flt(w.indented_qty), flt(w.ordered_qty), flt(w.actual_qty)]) if item_qty: item_list.append(['', '', '', '', 'Total', i_qty, o_qty, a_qty]) return item_list - + def raise_purchase_request(self): """ Raise Material Request if projected qty is less than qty required @@ -306,10 +306,10 @@ class ProductionPlanningTool(Document): self.validate_data() if not self.purchase_request_for_warehouse: frappe.throw(_("Please enter Warehouse for which Material Request will be raised")) - - bom_dict = self.get_distinct_items_and_boms()[0] + + bom_dict = self.get_distinct_items_and_boms()[0] self.get_raw_materials(bom_dict) - + if self.item_dict: self.insert_purchase_request() @@ -348,15 +348,15 @@ class ProductionPlanningTool(Document): items_to_be_requested[item]["No Sales Order"] += requested_qty return items_to_be_requested - + def get_projected_qty(self): items = self.item_dict.keys() - item_projected_qty = frappe.db.sql("""select item_code, sum(projected_qty) - from `tabBin` where item_code in (%s) group by item_code""" % + item_projected_qty = frappe.db.sql("""select item_code, sum(projected_qty) + from `tabBin` where item_code in (%s) group by item_code""" % (", ".join(["%s"]*len(items)),), tuple(items)) return dict(item_projected_qty) - + def insert_purchase_request(self): items_to_be_requested = self.get_requested_items() @@ -397,11 +397,10 @@ class ProductionPlanningTool(Document): pr_doc.ignore_permissions = 1 pr_doc.submit() purchase_request_list.append(pr_doc.name) - + if purchase_request_list: pur_req = ["""%s""" % \ (p, p) for p in purchase_request_list] - msgprint("Material Request(s) created: \n%s" % - "\n".join(pur_req)) + msgprint(_("Material Requests {0} created").format(comma_and(pur_req))) else: msgprint(_("Nothing to request")) diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py index 2225acd53b..bce9c52688 100644 --- a/erpnext/projects/doctype/project/project.py +++ b/erpnext/projects/doctype/project/project.py @@ -5,13 +5,13 @@ from __future__ import unicode_literals import frappe from frappe.utils import flt, getdate -from frappe import msgprint +from frappe import _ from erpnext.utilities.transaction_base import delete_events from frappe.model.document import Document class Project(Document): - + def get_gross_profit(self): pft, per_pft =0, 0 pft = flt(self.project_value) - flt(self.est_material_cost) @@ -19,19 +19,18 @@ class Project(Document): per_pft = (flt(pft) / flt(self.project_value)) * 100 ret = {'gross_margin_value': pft, 'per_gross_margin': per_pft} return ret - + def validate(self): """validate start date before end date""" if self.project_start_date and self.completion_date: if getdate(self.completion_date) < getdate(self.project_start_date): - msgprint("Expected Completion Date can not be less than Project Start Date") - raise Exception - + frappe.throw(_("Expected Completion Date can not be less than Project Start Date")) + def on_update(self): self.add_calendar_event() - + def update_percent_complete(self): - total = frappe.db.sql("""select count(*) from tabTask where project=%s""", + total = frappe.db.sql("""select count(*) from tabTask where project=%s""", self.name)[0][0] if total: completed = frappe.db.sql("""select count(*) from tabTask where @@ -42,7 +41,7 @@ class Project(Document): def add_calendar_event(self): # delete any earlier event for this project delete_events(self.doctype, self.name) - + # add events for milestone in self.get("project_milestones"): if milestone.milestone_date: @@ -57,6 +56,6 @@ class Project(Document): "ref_type": self.doctype, "ref_name": self.name }).insert() - + def on_trash(self): delete_events(self.doctype, self.name) diff --git a/erpnext/projects/doctype/task/task.py b/erpnext/projects/doctype/task/task.py index a4dfb4776b..7fbaa45138 100644 --- a/erpnext/projects/doctype/task/task.py +++ b/erpnext/projects/doctype/task/task.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe, json from frappe.utils import getdate, today -from frappe import msgprint +from frappe import _ from frappe.model.document import Document @@ -15,32 +15,30 @@ class Task(Document): return { "project": self.project } - + def get_customer_details(self): cust = frappe.db.sql("select customer_name from `tabCustomer` where name=%s", self.customer) if cust: ret = {'customer_name': cust and cust[0][0] or ''} return ret - + def validate(self): if self.exp_start_date and self.exp_end_date and getdate(self.exp_start_date) > getdate(self.exp_end_date): - msgprint("'Expected Start Date' can not be greater than 'Expected End Date'") - raise Exception - + frappe.throw(_("'Expected Start Date' can not be greater than 'Expected End Date'")) + if self.act_start_date and self.act_end_date and getdate(self.act_start_date) > getdate(self.act_end_date): - msgprint("'Actual Start Date' can not be greater than 'Actual End Date'") - raise Exception - + frappe.throw(_("'Actual Start Date' can not be greater than 'Actual End Date'")) + self.update_status() def update_status(self): status = frappe.db.get_value("Task", self.name, "status") if self.status=="Working" and status !="Working" and not self.act_start_date: self.act_start_date = today() - + if self.status=="Closed" and status != "Closed" and not self.act_end_date: self.act_end_date = today() - + def on_update(self): """update percent complete in project""" if self.project: @@ -55,14 +53,14 @@ def get_events(start, end, filters=None): conditions = build_match_conditions("Task") conditions and (" and " + conditions) or "" - + if filters: filters = json.loads(filters) for key in filters: if filters[key]: conditions += " and " + key + ' = "' + filters[key].replace('"', '\"') + '"' - - data = frappe.db.sql("""select name, exp_start_date, exp_end_date, + + data = frappe.db.sql("""select name, exp_start_date, exp_end_date, subject, status, project from `tabTask` where ((exp_start_date between '%(start)s' and '%(end)s') \ or (exp_end_date between '%(start)s' and '%(end)s')) @@ -79,7 +77,7 @@ def get_project(doctype, txt, searchfield, start, page_len, filters): return frappe.db.sql(""" select name from `tabProject` where %(key)s like "%(txt)s" %(mcond)s - order by name - limit %(start)s, %(page_len)s """ % {'key': searchfield, + order by name + limit %(start)s, %(page_len)s """ % {'key': searchfield, 'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype), - 'start': start, 'page_len': page_len}) \ No newline at end of file + 'start': start, 'page_len': page_len}) diff --git a/erpnext/projects/doctype/time_log/time_log.py b/erpnext/projects/doctype/time_log/time_log.py index f184db37f4..eb8afc7729 100644 --- a/erpnext/projects/doctype/time_log/time_log.py +++ b/erpnext/projects/doctype/time_log/time_log.py @@ -6,7 +6,7 @@ from __future__ import unicode_literals import frappe from frappe import _ -from frappe.utils import cstr +from frappe.utils import cstr, comma_and class OverlapError(frappe.ValidationError): pass @@ -14,12 +14,12 @@ class OverlapError(frappe.ValidationError): pass from frappe.model.document import Document class TimeLog(Document): - + def validate(self): self.set_status() self.validate_overlap() self.calculate_total_hours() - + def calculate_total_hours(self): from frappe.utils import time_diff_in_hours self.hours = time_diff_in_hours(self.to_time, self.from_time) @@ -30,36 +30,35 @@ class TimeLog(Document): 1: "Submitted", 2: "Cancelled" }[self.docstatus or 0] - + if self.time_log_batch: self.status="Batched for Billing" - + if self.sales_invoice: self.status="Billed" - - def validate_overlap(self): + + def validate_overlap(self): existing = frappe.db.sql_list("""select name from `tabTime Log` where owner=%s and ( - (from_time between %s and %s) or - (to_time between %s and %s) or - (%s between from_time and to_time)) + (from_time between %s and %s) or + (to_time between %s and %s) or + (%s between from_time and to_time)) and name!=%s and ifnull(task, "")=%s - and docstatus < 2""", - (self.owner, self.from_time, self.to_time, self.from_time, + and docstatus < 2""", + (self.owner, self.from_time, self.to_time, self.from_time, self.to_time, self.from_time, self.name or "No Name", cstr(self.task))) if existing: - frappe.msgprint(_("This Time Log conflicts with") + ":" + ', '.join(existing), - raise_exception=OverlapError) - + frappe.throw(_("This Time Log conflicts with {0}").format(comma_and(existing)), OverlapError) + def before_cancel(self): self.set_status() - + def before_update_after_submit(self): self.set_status() - + @frappe.whitelist() def get_events(start, end): from frappe.widgets.reportview import build_match_conditions @@ -67,7 +66,7 @@ def get_events(start, end): frappe.msgprint(_("No Permission"), raise_exception=1) match = build_match_conditions("Time Log") - data = frappe.db.sql("""select name, from_time, to_time, + data = frappe.db.sql("""select name, from_time, to_time, activity_type, task, project from `tabTime Log` where from_time between '%(start)s' and '%(end)s' or to_time between '%(start)s' and '%(end)s' %(match)s""" % { @@ -75,12 +74,12 @@ def get_events(start, end): "end": end, "match": match and (" and " + match) or "" }, as_dict=True, update={"allDay": 0}) - + for d in data: d.title = d.name + ": " + (d.activity_type or "[Activity Type not set]") if d.task: d.title += " for Task: " + d.task if d.project: d.title += " for Project: " + d.project - + return data diff --git a/erpnext/projects/doctype/time_log_batch/time_log_batch.py b/erpnext/projects/doctype/time_log_batch/time_log_batch.py index b8204e4855..882ed99d48 100644 --- a/erpnext/projects/doctype/time_log_batch/time_log_batch.py +++ b/erpnext/projects/doctype/time_log_batch/time_log_batch.py @@ -29,8 +29,7 @@ class TimeLogBatch(Document): def validate_time_log_is_submitted(self, tl): if tl.status != "Submitted" and self.docstatus == 0: - frappe.msgprint(_("Time Log must have status 'Submitted'") + \ - " :" + tl.name + " (" + _(tl.status) + ")", raise_exception=True) + frappe.throw(_("Time Log {0} must be 'Submitted'").format(tl.name)) def set_status(self): self.status = { diff --git a/erpnext/selling/doctype/installation_note/installation_note.py b/erpnext/selling/doctype/installation_note/installation_note.py index 1fa91ccc7c..7d2d3d0663 100644 --- a/erpnext/selling/doctype/installation_note/installation_note.py +++ b/erpnext/selling/doctype/installation_note/installation_note.py @@ -6,7 +6,7 @@ import frappe from frappe.utils import cstr, getdate -from frappe import msgprint +from frappe import _ from erpnext.stock.utils import get_valid_serial_nos from erpnext.utilities.transaction_base import TransactionBase @@ -46,15 +46,14 @@ class InstallationNote(TransactionBase): def is_serial_no_added(self, item_code, serial_no): ar_required = frappe.db.get_value("Item", item_code, "has_serial_no") if ar_required == 'Yes' and not serial_no: - msgprint("Serial No is mandatory for item: " + item_code, raise_exception=1) + frappe.throw(_("Serial No is mandatory for Item {0}").format(item_code)) elif ar_required != 'Yes' and cstr(serial_no).strip(): - msgprint("If serial no required, please select 'Yes' in 'Has Serial No' in Item :" + - item_code, raise_exception=1) + frappe.throw(_("Item {0} is not a serialized Item").format(item_code)) def is_serial_no_exist(self, item_code, serial_no): for x in serial_no: if not frappe.db.exists("Serial No", x): - msgprint("Serial No " + x + " does not exist in the system", raise_exception=1) + frappe.throw(_("Serial No {0} does not exist").format(x)) def is_serial_no_installed(self,cur_s_no,item_code): for x in cur_s_no: @@ -62,8 +61,7 @@ class InstallationNote(TransactionBase): status = status and status[0][0] or '' if status == 'Installed': - msgprint("Item "+item_code+" with serial no. " + x + " already installed", - raise_exception=1) + frappe.throw(_("Item {0} with Serial No {1} is already installed").format(item_code, x)) def get_prevdoc_serial_no(self, prevdoc_detail_docname): serial_nos = frappe.db.get_value("Delivery Note Item", @@ -73,8 +71,7 @@ class InstallationNote(TransactionBase): def is_serial_no_match(self, cur_s_no, prevdoc_s_no, prevdoc_docname): for sr in cur_s_no: if sr not in prevdoc_s_no: - msgprint("Serial No. " + sr + " is not matching with the Delivery Note " + - prevdoc_docname, raise_exception = 1) + frappe.throw(_("Serial No {0} does not belong to Delivery Note {1}").format(sr, prevdoc_docname)) def validate_serial_no(self): cur_s_no, prevdoc_s_no, sr_list = [], [], [] @@ -95,12 +92,11 @@ class InstallationNote(TransactionBase): if d.prevdoc_docname: d_date = frappe.db.get_value("Delivery Note", d.prevdoc_docname, "posting_date") if d_date > getdate(self.inst_date): - msgprint("Installation Date can not be before Delivery Date " + cstr(d_date) + - " for item "+d.item_code, raise_exception=1) + frappe.throw(_("Installation date cannot be before delivery date for Item {0}").format(d.item_code)) def check_item_table(self): if not(self.get('installed_item_details')): - msgprint("Please fetch items from Delivery Note selected", raise_exception=1) + frappe.throw(_("Please pull items from Delivery Note")) def on_update(self): frappe.db.set(self, 'status', 'Draft') diff --git a/erpnext/selling/doctype/lead/lead.py b/erpnext/selling/doctype/lead/lead.py index 8163be3111..c400e555fe 100644 --- a/erpnext/selling/doctype/lead/lead.py +++ b/erpnext/selling/doctype/lead/lead.py @@ -4,10 +4,10 @@ from __future__ import unicode_literals import frappe from frappe import _ -from frappe.utils import cstr, validate_email_add, cint +from frappe.utils import cstr, validate_email_add, cint, comma_and from frappe import session - + from erpnext.controllers.selling_controller import SellingController class Lead(SellingController): @@ -15,7 +15,7 @@ class Lead(SellingController): customer = frappe.db.get_value("Customer", {"lead_name": self.name}) if customer: self.set("__is_customer", customer) - + def validate(self): self._prev = frappe._dict({ "contact_date": frappe.db.get_value("Lead", self.name, "contact_date") if \ @@ -23,20 +23,20 @@ class Lead(SellingController): "contact_by": frappe.db.get_value("Lead", self.name, "contact_by") if \ (not cint(self.get("__islocal"))) else None, }) - + self.set_status() - + if self.source == 'Campaign' and not self.campaign_name and session['user'] != 'Guest': frappe.throw("Please specify campaign name") - + if self.email_id: if not validate_email_add(self.email_id): frappe.throw('Please enter valid email id.') - + def on_update(self): self.check_email_id_is_unique() self.add_calendar_event() - + def add_calendar_event(self, opts=None, force=False): super(Lead, self).add_calendar_event({ "owner": self.lead_owner, @@ -48,22 +48,21 @@ class Lead(SellingController): def check_email_id_is_unique(self): if self.email_id: # validate email is unique - email_list = frappe.db.sql("""select name from tabLead where email_id=%s""", + email_list = frappe.db.sql("""select name from tabLead where email_id=%s""", self.email_id) if len(email_list) > 1: items = [e[0] for e in email_list if e[0]!=self.name] - frappe.msgprint(_("""Email Id must be unique, already exists for: """) + \ - ", ".join(items), raise_exception=True) + frappe.throw(_("Email id must be unique, already exists for {0}").format(comma_and(items))) def on_trash(self): frappe.db.sql("""update `tabSupport Ticket` set lead='' where lead=%s""", self.name) - + self.delete_events() - + def has_customer(self): return frappe.db.get_value("Customer", {"lead_name": self.name}) - + def has_opportunity(self): return frappe.db.get_value("Opportunity", {"lead": self.name, "docstatus": 1, "status": ["!=", "Lost"]}) @@ -74,7 +73,7 @@ def make_customer(source_name, target_doc=None): def _make_customer(source_name, target_doc=None, ignore_permissions=False): from frappe.model.mapper import get_mapped_doc - + def set_missing_values(source, target): if source.company_name: target.customer_type = "Company" @@ -82,10 +81,10 @@ def _make_customer(source_name, target_doc=None, ignore_permissions=False): else: target.customer_type = "Individual" target.customer_name = source.lead_name - + target.customer_group = frappe.db.get_default("customer_group") - - doclist = get_mapped_doc("Lead", source_name, + + doclist = get_mapped_doc("Lead", source_name, {"Lead": { "doctype": "Customer", "field_map": { @@ -95,14 +94,14 @@ def _make_customer(source_name, target_doc=None, ignore_permissions=False): "fax": "fax_1" } }}, target_doc, set_missing_values, ignore_permissions=ignore_permissions) - + return doclist - + @frappe.whitelist() def make_opportunity(source_name, target_doc=None): from frappe.model.mapper import get_mapped_doc - - doclist = get_mapped_doc("Lead", source_name, + + doclist = get_mapped_doc("Lead", source_name, {"Lead": { "doctype": "Opportunity", "field_map": { @@ -115,19 +114,19 @@ def make_opportunity(source_name, target_doc=None): "mobile_no": "contact_mobile" } }}, target_doc) - + return doclist - + @frappe.whitelist() def get_lead_details(lead): if not lead: return {} - + from erpnext.accounts.party import set_address_details out = frappe._dict() - + lead_doc = frappe.get_doc("Lead", lead) lead = lead_doc - + out.update({ "territory": lead.territory, "customer_name": lead.company_name or lead.lead_name, @@ -136,7 +135,7 @@ def get_lead_details(lead): "contact_mobile": lead.mobile_no, "contact_phone": lead.phone, }) - + set_address_details(out, lead, "Lead") - return out \ No newline at end of file + return out diff --git a/erpnext/selling/doctype/opportunity/opportunity.py b/erpnext/selling/doctype/opportunity/opportunity.py index c87c9836fe..9ba6e56382 100644 --- a/erpnext/selling/doctype/opportunity/opportunity.py +++ b/erpnext/selling/doctype/opportunity/opportunity.py @@ -8,13 +8,13 @@ from frappe.utils import cstr, cint from frappe import msgprint, _ - + from erpnext.utilities.transaction_base import TransactionBase class Opportunity(TransactionBase): fname = 'enq_details' tname = 'Opportunity Item' - + def get_item_details(self, item_code): item = frappe.db.sql("""select item_name, stock_uom, description_html, description, item_group, brand from `tabItem` where name = %s""", item_code, as_dict=1) @@ -28,7 +28,7 @@ class Opportunity(TransactionBase): return ret def get_cust_address(self,name): - details = frappe.db.sql("""select customer_name, address, territory, customer_group + details = frappe.db.sql("""select customer_name, address, territory, customer_group from `tabCustomer` where name = %s and docstatus != 2""", (name), as_dict = 1) if details: ret = { @@ -39,28 +39,28 @@ class Opportunity(TransactionBase): } # ********** get primary contact details (this is done separately coz. , in case there is no primary contact thn it would not be able to fetch customer details in case of join query) - contact_det = frappe.db.sql("""select contact_name, contact_no, email_id - from `tabContact` where customer = %s and is_customer = 1 + contact_det = frappe.db.sql("""select contact_name, contact_no, email_id + from `tabContact` where customer = %s and is_customer = 1 and is_primary_contact = 'Yes' and docstatus != 2""", name, as_dict = 1) ret['contact_person'] = contact_det and contact_det[0]['contact_name'] or '' ret['contact_no'] = contact_det and contact_det[0]['contact_no'] or '' ret['email_id'] = contact_det and contact_det[0]['email_id'] or '' - + return ret else: msgprint("Customer : %s does not exist in system." % (name)) raise Exception - + def on_update(self): self.add_calendar_event() def add_calendar_event(self, opts=None, force=False): if not opts: opts = frappe._dict() - + opts.description = "" - + if self.customer: if self.contact_person: opts.description = 'Contact '+cstr(self.contact_person) @@ -71,23 +71,22 @@ class Opportunity(TransactionBase): opts.description = 'Contact '+cstr(self.contact_display) else: opts.description = 'Contact lead '+cstr(self.lead) - + opts.subject = opts.description opts.description += '. By : ' + cstr(self.contact_by) - + if self.to_discuss: opts.description += ' To Discuss : ' + cstr(self.to_discuss) - + super(Opportunity, self).add_calendar_event(opts, force) def validate_item_details(self): if not self.get('enquiry_details'): - msgprint("Please select items for which enquiry needs to be made") - raise Exception + frappe.throw(_("Items required")) def validate_lead_cust(self): if self.enquiry_from == 'Lead' and not self.lead: - msgprint("Lead Id is mandatory if 'Opportunity From' is selected as Lead", raise_exception=1) + frappe.throw(_("Lead must be set if Opportunity is made from Lead")) elif self.enquiry_from == 'Customer' and not self.customer: msgprint("Customer is mandatory if 'Opportunity From' is selected as Customer", raise_exception=1) @@ -98,24 +97,24 @@ class Opportunity(TransactionBase): "contact_by": frappe.db.get_value("Opportunity", self.name, "contact_by") if \ (not cint(self.get("__islocal"))) else None, }) - + self.set_status() self.validate_item_details() self.validate_uom_is_integer("uom", "qty") self.validate_lead_cust() - + from erpnext.accounts.utils import validate_fiscal_year validate_fiscal_year(self.transaction_date, self.fiscal_year, "Opportunity Date") def on_submit(self): if self.lead: frappe.get_doc("Lead", self.lead).set_status(update=True) - + def on_cancel(self): if self.has_quotation(): frappe.throw(_("Cannot Cancel Opportunity as Quotation Exists")) self.set_status(update=True) - + def declare_enquiry_lost(self,arg): if not self.has_quotation(): frappe.db.set(self, 'status', 'Lost') @@ -125,40 +124,40 @@ class Opportunity(TransactionBase): def on_trash(self): self.delete_events() - + def has_quotation(self): return frappe.db.get_value("Quotation Item", {"prevdoc_docname": self.name, "docstatus": 1}) - + @frappe.whitelist() def make_quotation(source_name, target_doc=None): from frappe.model.mapper import get_mapped_doc - + def set_missing_values(source, target): quotation = frappe.get_doc(target) quotation.run_method("onload_post_render") quotation.run_method("calculate_taxes_and_totals") - + doclist = get_mapped_doc("Opportunity", source_name, { "Opportunity": { - "doctype": "Quotation", + "doctype": "Quotation", "field_map": { - "enquiry_from": "quotation_to", - "enquiry_type": "order_type", - "name": "enq_no", + "enquiry_from": "quotation_to", + "enquiry_type": "order_type", + "name": "enq_no", }, "validation": { "docstatus": ["=", 1] } - }, + }, "Opportunity Item": { - "doctype": "Quotation Item", + "doctype": "Quotation Item", "field_map": { - "parent": "prevdoc_docname", - "parenttype": "prevdoc_doctype", + "parent": "prevdoc_docname", + "parenttype": "prevdoc_doctype", "uom": "stock_uom" }, "add_if_empty": True } }, target_doc, set_missing_values) - - return doclist \ No newline at end of file + + return doclist diff --git a/erpnext/selling/doctype/quotation/quotation.py b/erpnext/selling/doctype/quotation/quotation.py index d6ade9e0cb..d7f58a7f6f 100644 --- a/erpnext/selling/doctype/quotation/quotation.py +++ b/erpnext/selling/doctype/quotation/quotation.py @@ -5,7 +5,7 @@ from __future__ import unicode_literals import frappe from frappe.utils import cstr -from frappe import _, msgprint +from frappe import _ from erpnext.controllers.selling_controller import SellingController @@ -20,31 +20,28 @@ class Quotation(SellingController): chk_dupl_itm = [] for d in self.get('quotation_details'): if [cstr(d.item_code),cstr(d.description)] in chk_dupl_itm: - msgprint("Item %s has been entered twice. Please change description atleast to continue" % d.item_code) - raise Exception + frappe.throw(_("Item {0} with same description entered twice").format(d.item_code)) else: chk_dupl_itm.append([cstr(d.item_code),cstr(d.description)]) def validate_order_type(self): super(Quotation, self).validate_order_type() - + if self.order_type in ['Maintenance', 'Service']: for d in self.get('quotation_details'): is_service_item = frappe.db.sql("select is_service_item from `tabItem` where name=%s", d.item_code) is_service_item = is_service_item and is_service_item[0][0] or 'No' - + if is_service_item == 'No': - msgprint("You can not select non service item "+d.item_code+" in Maintenance Quotation") - raise Exception + frappe.throw(_("Item {0} must be Service Item").format(d.item_code)) else: for d in self.get('quotation_details'): is_sales_item = frappe.db.sql("select is_sales_item from `tabItem` where name=%s", d.item_code) is_sales_item = is_sales_item and is_sales_item[0][0] or 'No' - + if is_sales_item == 'No': - msgprint("You can not select non sales item "+d.item_code+" in Sales Quotation") - raise Exception - + frappe.throw(_("Item {0} must be Sales Item").format(d.item_code)) + def validate(self): super(Quotation, self).validate() self.set_status() @@ -56,7 +53,7 @@ class Quotation(SellingController): for opportunity in list(set([d.prevdoc_docname for d in self.get("quotation_details")])): if opportunity: frappe.get_doc("Opportunity", opportunity).set_status(update=True) - + def declare_order_lost(self, arg): if not self.has_sales_order(): frappe.db.set(self, 'status', 'Lost') @@ -64,26 +61,25 @@ class Quotation(SellingController): self.update_opportunity() else: frappe.throw(_("Cannot set as Lost as Sales Order is made.")) - + def check_item_table(self): if not self.get('quotation_details'): - msgprint("Please enter item details") - raise Exception - + frappe.throw(_("Please enter item details")) + def on_submit(self): self.check_item_table() - + # Check for Approving Authority frappe.get_doc('Authorization Control').validate_approving_authority(self.doctype, self.company, self.grand_total, self) - + #update enquiry status self.update_opportunity() - + def on_cancel(self): #update enquiry status self.set_status() self.update_opportunity() - + def print_other_charges(self,docname): print_lst = [] for d in self.get('other_charges'): @@ -92,51 +88,51 @@ class Quotation(SellingController): lst1.append(d.total) print_lst.append(lst1) return print_lst - - + + @frappe.whitelist() def make_sales_order(source_name, target_doc=None): return _make_sales_order(source_name, target_doc) - + def _make_sales_order(source_name, target_doc=None, ignore_permissions=False): from frappe.model.mapper import get_mapped_doc - + customer = _make_customer(source_name, ignore_permissions) - + def set_missing_values(source, target): if customer: target.customer = customer.name target.customer_name = customer.customer_name - + si = frappe.get_doc(target) si.ignore_permissions = ignore_permissions si.run_method("onload_post_render") - + doclist = get_mapped_doc("Quotation", source_name, { "Quotation": { - "doctype": "Sales Order", + "doctype": "Sales Order", "validation": { "docstatus": ["=", 1] } - }, + }, "Quotation Item": { - "doctype": "Sales Order Item", + "doctype": "Sales Order Item", "field_map": { "parent": "prevdoc_docname" } - }, + }, "Sales Taxes and Charges": { "doctype": "Sales Taxes and Charges", "add_if_empty": True - }, + }, "Sales Team": { "doctype": "Sales Team", "add_if_empty": True } }, target_doc, set_missing_values, ignore_permissions=ignore_permissions) - + # postprocess: fetch shipping address, set missing values - + return doclist def _make_customer(source_name, ignore_permissions=False): @@ -152,7 +148,7 @@ def _make_customer(source_name, ignore_permissions=False): if quotation[1] == "Shopping Cart": customer.customer_group = frappe.db.get_value("Shopping Cart Settings", None, "default_customer_group") - + try: customer.insert() return customer diff --git a/erpnext/selling/doctype/sales_bom/sales_bom.py b/erpnext/selling/doctype/sales_bom/sales_bom.py index 5601d7ff67..724e009c49 100644 --- a/erpnext/selling/doctype/sales_bom/sales_bom.py +++ b/erpnext/selling/doctype/sales_bom/sales_bom.py @@ -4,6 +4,8 @@ from __future__ import unicode_literals import frappe +from frappe import _ + from frappe.model.document import Document class SalesBOM(Document): @@ -11,7 +13,7 @@ class SalesBOM(Document): def autoname(self): self.name = self.new_item_code - + def validate(self): self.validate_main_item() @@ -22,23 +24,22 @@ class SalesBOM(Document): """main item must have Is Stock Item as No and Is Sales Item as Yes""" if not frappe.db.sql("""select name from tabItem where name=%s and ifnull(is_stock_item,'')='No' and ifnull(is_sales_item,'')='Yes'""", self.new_item_code): - frappe.msgprint("""Parent Item %s is either a Stock Item or a not a Sales Item""", - raise_exception=1) + frappe.throw(_("Parent Item {0} must be not Stock Item and must be a Sales Item").format(self.new_item_code)) def get_item_details(self, name): - det = frappe.db.sql("""select description, stock_uom from `tabItem` + det = frappe.db.sql("""select description, stock_uom from `tabItem` where name = %s""", name) return { - 'description' : det and det[0][0] or '', + 'description' : det and det[0][0] or '', 'uom': det and det[0][1] or '' } def get_new_item_code(doctype, txt, searchfield, start, page_len, filters): from erpnext.controllers.queries import get_match_cond - - return frappe.db.sql("""select name, item_name, description from tabItem + + return frappe.db.sql("""select name, item_name, description from tabItem where is_stock_item="No" and is_sales_item="Yes" and name not in (select name from `tabSales BOM`) and %s like %s - %s limit %s, %s""" % (searchfield, "%s", - get_match_cond(doctype),"%s", "%s"), - ("%%%s%%" % txt, start, page_len)) \ No newline at end of file + %s limit %s, %s""" % (searchfield, "%s", + get_match_cond(doctype),"%s", "%s"), + ("%%%s%%" % txt, start, page_len)) diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index 103144ff16..d4054dd7e8 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -5,9 +5,9 @@ from __future__ import unicode_literals import frappe import frappe.utils -from frappe.utils import cstr, flt, getdate +from frappe.utils import cstr, flt, getdate, comma_and -from frappe import msgprint +from frappe import _ from frappe.model.mapper import get_mapped_doc from erpnext.controllers.selling_controller import SellingController @@ -23,22 +23,19 @@ class SalesOrder(SellingController): # validate transaction date v/s delivery date if self.delivery_date: if getdate(self.transaction_date) > getdate(self.delivery_date): - msgprint("Expected Delivery Date cannot be before Sales Order Date") - raise Exception + frappe.throw(_("Expected Delivery Date cannot be before Sales Order Date")) def validate_po(self): # validate p.o date v/s delivery date if self.po_date and self.delivery_date and getdate(self.po_date) > getdate(self.delivery_date): - msgprint("Expected Delivery Date cannot be before Purchase Order Date") - raise Exception + frappe.throw(_("Expected Delivery Date cannot be before Purchase Order Date")) if self.po_no and self.customer: so = frappe.db.sql("select name from `tabSales Order` \ where ifnull(po_no, '') = %s and name != %s and docstatus < 2\ and customer = %s", (self.po_no, self.name, self.customer)) if so and so[0][0]: - msgprint("""Another Sales Order (%s) exists against same PO No and Customer. - Please be sure, you are not making duplicate entry.""" % so[0][0]) + frappe.msgprint(_("Warning: Sales Order {0} already exists against same Purchase Order number").format(so[0][0])) def validate_for_items(self): check_list, flag = [], 0 @@ -49,16 +46,15 @@ class SalesOrder(SellingController): if frappe.db.get_value("Item", d.item_code, "is_stock_item") == 'Yes': if not d.warehouse: - msgprint("""Please enter Reserved Warehouse for item %s - as it is stock Item""" % d.item_code, raise_exception=1) + frappe.throw(_("Reserved warehouse required for stock item {0}").format(d.item_code)) if e in check_list: - msgprint("Item %s has been entered twice." % d.item_code) + frappe.throw(_("Item {0} has been entered twice").format(d.item_code)) else: check_list.append(e) else: if f in chk_dupl_itm: - msgprint("Item %s has been entered twice." % d.item_code) + frappe.throw(_("Item {0} has been entered twice").format(d.item_code)) else: chk_dupl_itm.append(f) @@ -74,16 +70,14 @@ class SalesOrder(SellingController): if d.prevdoc_docname: res = frappe.db.sql("select name from `tabQuotation` where name=%s and order_type = %s", (d.prevdoc_docname, self.order_type)) if not res: - msgprint("""Order Type (%s) should be same in Quotation: %s \ - and current Sales Order""" % (self.order_type, d.prevdoc_docname)) + frappe.msgprint(_("Quotation {0} not of type {1}").format(d.prevdoc_docname, self.order_type)) def validate_order_type(self): super(SalesOrder, self).validate_order_type() def validate_delivery_date(self): if self.order_type == 'Sales' and not self.delivery_date: - msgprint("Please enter 'Expected Delivery Date'") - raise Exception + frappe.throw(_("Please enter 'Expected Delivery Date'")) self.validate_sales_mntc_quotation() @@ -93,8 +87,7 @@ class SalesOrder(SellingController): and (customer = %s or ifnull(customer,'')='')""", (self.project_name, self.customer)) if not res: - msgprint("Customer - %s does not belong to project - %s. \n\nIf you want to use project for multiple customers then please make customer details blank in project - %s."%(self.customer,self.project_name,self.project_name)) - raise Exception + frappe.throw(_("Customer {0} does not belong to project {1}").format(self.customer, self.project_name)) def validate(self): super(SalesOrder, self).validate() @@ -169,8 +162,8 @@ class SalesOrder(SellingController): def on_cancel(self): # Cannot cancel stopped SO if self.status == 'Stopped': - msgprint("Sales Order : '%s' cannot be cancelled as it is Stopped. Unstop it for any further transactions" %(self.name)) - raise Exception + frappe.throw(_("Stopped order cannot be cancelled. Unstop to cancel.")) + self.check_nextdoc_docstatus() self.update_stock_ledger(update_stock = -1) @@ -180,55 +173,56 @@ class SalesOrder(SellingController): def check_nextdoc_docstatus(self): # Checks Delivery Note - submit_dn = frappe.db.sql("select t1.name from `tabDelivery Note` t1,`tabDelivery Note Item` t2 where t1.name = t2.parent and t2.against_sales_order = %s and t1.docstatus = 1", self.name) + submit_dn = frappe.db.sql_list("""select t1.name from `tabDelivery Note` t1,`tabDelivery Note Item` t2 + where t1.name = t2.parent and t2.against_sales_order = %s and t1.docstatus = 1""", self.name) if submit_dn: - msgprint("Delivery Note : " + cstr(submit_dn[0][0]) + " has been submitted against " + cstr(self.doctype) + ". Please cancel Delivery Note : " + cstr(submit_dn[0][0]) + " first and then cancel "+ cstr(self.doctype), raise_exception = 1) + frappe.throw(_("Delivery Notes {0} must be cancelled before cancelling this Sales Order").format(comma_and(submit_dn))) # Checks Sales Invoice - submit_rv = frappe.db.sql("""select t1.name + submit_rv = frappe.db.sql_list("""select t1.name from `tabSales Invoice` t1,`tabSales Invoice Item` t2 where t1.name = t2.parent and t2.sales_order = %s and t1.docstatus = 1""", self.name) if submit_rv: - msgprint("Sales Invoice : " + cstr(submit_rv[0][0]) + " has already been submitted against " +cstr(self.doctype)+ ". Please cancel Sales Invoice : "+ cstr(submit_rv[0][0]) + " first and then cancel "+ cstr(self.doctype), raise_exception = 1) + frappe.throw(_("Sales Invoice {0} must be cancelled before cancelling this Sales Order").format(comma_and(submit_rv))) #check maintenance schedule - submit_ms = frappe.db.sql("select t1.name from `tabMaintenance Schedule` t1, `tabMaintenance Schedule Item` t2 where t2.parent=t1.name and t2.prevdoc_docname = %s and t1.docstatus = 1",self.name) + submit_ms = frappe.db.sql_list("""select t1.name from `tabMaintenance Schedule` t1, + `tabMaintenance Schedule Item` t2 + where t2.parent=t1.name and t2.prevdoc_docname = %s and t1.docstatus = 1""", self.name) if submit_ms: - msgprint("Maintenance Schedule : " + cstr(submit_ms[0][0]) + " has already been submitted against " +cstr(self.doctype)+ ". Please cancel Maintenance Schedule : "+ cstr(submit_ms[0][0]) + " first and then cancel "+ cstr(self.doctype), raise_exception = 1) + frappe.throw(_("Maintenance Schedule {0} must be cancelled before cancelling this Sales Order").format(comma_and(submit_ms))) # check maintenance visit - submit_mv = frappe.db.sql("select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent=t1.name and t2.prevdoc_docname = %s and t1.docstatus = 1",self.name) + submit_mv = frappe.db.sql_list("""select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 + where t2.parent=t1.name and t2.prevdoc_docname = %s and t1.docstatus = 1""",self.name) if submit_mv: - msgprint("Maintenance Visit : " + cstr(submit_mv[0][0]) + " has already been submitted against " +cstr(self.doctype)+ ". Please cancel Maintenance Visit : " + cstr(submit_mv[0][0]) + " first and then cancel "+ cstr(self.doctype), raise_exception = 1) + frappe.throw(_("Maintenance Visit {0} must be cancelled before cancelling this Sales Order").format(comma_and(submit_mv))) # check production order - pro_order = frappe.db.sql("""select name from `tabProduction Order` where sales_order = %s and docstatus = 1""", self.name) + pro_order = frappe.db.sql_list("""select name from `tabProduction Order` + where sales_order = %s and docstatus = 1""", self.name) if pro_order: - msgprint("""Production Order: %s exists against this sales order. - Please cancel production order first and then cancel this sales order""" % - pro_order[0][0], raise_exception=1) + frappe.throw(_("Production Order {0} must be cancelled before cancelling this Sales Order").format(comma_and(pro_order))) def check_modified_date(self): mod_db = frappe.db.get_value("Sales Order", self.name, "modified") date_diff = frappe.db.sql("select TIMEDIFF('%s', '%s')" % ( mod_db, cstr(self.modified))) if date_diff and date_diff[0][0]: - msgprint("%s: %s has been modified after you have opened. Please Refresh" - % (self.doctype, self.name), raise_exception=1) + frappe.throw(_("{0} {1} has been modified. Please Refresh").format(self.doctype, self.name)) def stop_sales_order(self): self.check_modified_date() self.update_stock_ledger(-1) frappe.db.set(self, 'status', 'Stopped') - msgprint("""%s: %s has been Stopped. To make transactions against this Sales Order - you need to Unstop it.""" % (self.doctype, self.name)) + frappe.msgprint(_("{0} {1} status is Stopped").format(self.doctype, self.name)) def unstop_sales_order(self): self.check_modified_date() self.update_stock_ledger(1) frappe.db.set(self, 'status', 'Submitted') - msgprint("%s: %s has been Unstopped" % (self.doctype, self.name)) + frappe.msgprint(_("{0} {1} status is Unstopped").format(self.doctype, self.name)) def update_stock_ledger(self, update_stock): diff --git a/erpnext/selling/report/customers_not_buying_since_long_time/customers_not_buying_since_long_time.py b/erpnext/selling/report/customers_not_buying_since_long_time/customers_not_buying_since_long_time.py index a5899f424c..35cdf59c50 100644 --- a/erpnext/selling/report/customers_not_buying_since_long_time/customers_not_buying_since_long_time.py +++ b/erpnext/selling/report/customers_not_buying_since_long_time/customers_not_buying_since_long_time.py @@ -4,15 +4,16 @@ from __future__ import unicode_literals import frappe from frappe.utils import cint +from frappe import _ def execute(filters=None): if not filters: filters ={} days_since_last_order = filters.get("days_since_last_order") if cint(days_since_last_order) <= 0: - frappe.msgprint("Please mention positive value in 'Days Since Last Order' field",raise_exception=1) + frappe.throw(_("'Days Since Last Order' must be greater than or equal to zero")) - columns = get_columns() + columns = get_columns() customers = get_so_details() data = [] @@ -20,43 +21,43 @@ def execute(filters=None): if cint(cust[8]) >= cint(days_since_last_order): cust.insert(7,get_last_so_amt(cust[0])) data.append(cust) - return columns, data + return columns, data def get_so_details(): - return frappe.db.sql("""select - cust.name, - cust.customer_name, - cust.territory, - cust.customer_group, - count(distinct(so.name)) as 'num_of_order', + return frappe.db.sql("""select + cust.name, + cust.customer_name, + cust.territory, + cust.customer_group, + count(distinct(so.name)) as 'num_of_order', sum(net_total) as 'total_order_value', - sum(if(so.status = "Stopped", - so.net_total * so.per_delivered/100, + sum(if(so.status = "Stopped", + so.net_total * so.per_delivered/100, so.net_total)) as 'total_order_considered', - max(so.transaction_date) as 'last_sales_order_date', - DATEDIFF(CURDATE(), max(so.transaction_date)) as 'days_since_last_order' - from `tabCustomer` cust, `tabSales Order` so + max(so.transaction_date) as 'last_sales_order_date', + DATEDIFF(CURDATE(), max(so.transaction_date)) as 'days_since_last_order' + from `tabCustomer` cust, `tabSales Order` so where cust.name = so.customer and so.docstatus = 1 group by cust.name order by 'days_since_last_order' desc """,as_list=1) def get_last_so_amt(customer): res = frappe.db.sql("""select net_total from `tabSales Order` - where customer ='%(customer)s' and docstatus = 1 order by transaction_date desc + where customer ='%(customer)s' and docstatus = 1 order by transaction_date desc limit 1""" % {'customer':customer}) return res and res[0][0] or 0 def get_columns(): return [ - "Customer:Link/Customer:120", - "Customer Name:Data:120", - "Territory::120", + "Customer:Link/Customer:120", + "Customer Name:Data:120", + "Territory::120", "Customer Group::120", - "Number of Order::120", - "Total Order Value:Currency:120", - "Total Order Considered:Currency:160", + "Number of Order::120", + "Total Order Value:Currency:120", + "Total Order Considered:Currency:160", "Last Order Amount:Currency:160", - "Last Sales Order Date:Date:160", + "Last Sales Order Date:Date:160", "Days Since Last Order::160" - ] \ No newline at end of file + ] diff --git a/erpnext/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.py b/erpnext/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.py index 2d7b3e3691..b272a83d27 100644 --- a/erpnext/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.py +++ b/erpnext/selling/report/sales_person_target_variance_item_group_wise/sales_person_target_variance_item_group_wise.py @@ -5,14 +5,12 @@ from __future__ import unicode_literals import frappe from frappe import _, msgprint from frappe.utils import flt -import time from erpnext.accounts.utils import get_fiscal_year from erpnext.controllers.trends import get_period_date_ranges, get_period_month_ranges -from frappe.model.meta import get_field_precision def execute(filters=None): if not filters: filters = {} - + columns = get_columns(filters) period_month_ranges = get_period_month_ranges(filters["period"], filters["fiscal_year"]) sim_map = get_salesperson_item_month_map(filters) @@ -37,7 +35,7 @@ def execute(filters=None): data.append(row) return columns, sorted(data, key=lambda x: (x[0], x[1])) - + def get_columns(filters): for fieldname in ["fiscal_year", "period", "target_on"]: if not filters.get(fieldname): @@ -55,26 +53,26 @@ def get_columns(filters): label = label % (from_date.strftime("%b") + " - " + to_date.strftime("%b")) else: label = label % from_date.strftime("%b") - + columns.append(label+":Float:120") - return columns + ["Total Target:Float:120", "Total Achieved:Float:120", + return columns + ["Total Target:Float:120", "Total Achieved:Float:120", "Total Variance:Float:120"] #Get sales person & item group details def get_salesperson_details(filters): - return frappe.db.sql("""select sp.name, td.item_group, td.target_qty, - td.target_amount, sp.distribution_id - from `tabSales Person` sp, `tabTarget Detail` td - where td.parent=sp.name and td.fiscal_year=%s order by sp.name""", + return frappe.db.sql("""select sp.name, td.item_group, td.target_qty, + td.target_amount, sp.distribution_id + from `tabSales Person` sp, `tabTarget Detail` td + where td.parent=sp.name and td.fiscal_year=%s order by sp.name""", (filters["fiscal_year"]), as_dict=1) #Get target distribution details of item group def get_target_distribution_details(filters): target_details = {} - - for d in frappe.db.sql("""select bd.name, bdd.month, bdd.percentage_allocation - from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd + + for d in frappe.db.sql("""select bd.name, bdd.month, bdd.percentage_allocation + from `tabBudget Distribution Detail` bdd, `tabBudget Distribution` bd where bdd.parent=bd.name and bd.fiscal_year=%s""", (filters["fiscal_year"]), as_dict=1): target_details.setdefault(d.name, {}).setdefault(d.month, flt(d.percentage_allocation)) @@ -83,13 +81,13 @@ def get_target_distribution_details(filters): #Get achieved details from sales order def get_achieved_details(filters): start_date, end_date = get_fiscal_year(fiscal_year = filters["fiscal_year"])[1:] - - item_details = frappe.db.sql("""select soi.item_code, soi.qty, soi.base_amount, so.transaction_date, - st.sales_person, MONTHNAME(so.transaction_date) as month_name - from `tabSales Order Item` soi, `tabSales Order` so, `tabSales Team` st - where soi.parent=so.name and so.docstatus=1 and - st.parent=so.name and so.transaction_date>=%s and - so.transaction_date<=%s""" % ('%s', '%s'), + + item_details = frappe.db.sql("""select soi.item_code, soi.qty, soi.base_amount, so.transaction_date, + st.sales_person, MONTHNAME(so.transaction_date) as month_name + from `tabSales Order Item` soi, `tabSales Order` so, `tabSales Team` st + where soi.parent=so.name and so.docstatus=1 and + st.parent=so.name and so.transaction_date>=%s and + so.transaction_date<=%s""" % ('%s', '%s'), (start_date, end_date), as_dict=1) item_actual_details = {} @@ -117,7 +115,7 @@ def get_salesperson_item_month_map(filters): tav_dict = sim_map[sd.name][sd.item_group][month] month_percentage = tdd.get(sd.distribution_id, {}).get(month, 0) \ if sd.distribution_id else 100.0/12 - + for ad in achieved_details.get(sd.name, {}).get(sd.item_group, []): if (filters["target_on"] == "Quantity"): tav_dict.target = flt(sd.target_qty) * month_percentage / 100 @@ -132,4 +130,4 @@ def get_salesperson_item_month_map(filters): return sim_map def get_item_group(item_name): - return frappe.db.get_value("Item", item_name, "item_group") \ No newline at end of file + return frappe.db.get_value("Item", item_name, "item_group") diff --git a/erpnext/setup/doctype/authorization_control/authorization_control.py b/erpnext/setup/doctype/authorization_control/authorization_control.py index 8a401f07be..25d2de0708 100644 --- a/erpnext/setup/doctype/authorization_control/authorization_control.py +++ b/erpnext/setup/doctype/authorization_control/authorization_control.py @@ -4,12 +4,11 @@ from __future__ import unicode_literals import frappe -from frappe.utils import cstr, flt, has_common, make_esc +from frappe.utils import cstr, flt, has_common, make_esc, comma_or + +from frappe import session, _ -from frappe import session, msgprint -from erpnext.setup.utils import get_company_currency - from erpnext.utilities.transaction_base import TransactionBase class AuthorizationControl(TransactionBase): @@ -24,27 +23,18 @@ class AuthorizationControl(TransactionBase): for x in det: amt_list.append(flt(x[0])) max_amount = max(amt_list) - + app_dtl = frappe.db.sql("select approving_user, approving_role from `tabAuthorization Rule` where transaction = %s and (value = %s or value > %s) and docstatus != 2 and based_on = %s and company = %s %s" % ('%s', '%s', '%s', '%s', '%s', condition), (doctype_name, flt(max_amount), total, based_on, company)) - + if not app_dtl: - app_dtl = frappe.db.sql("select approving_user, approving_role from `tabAuthorization Rule` where transaction = %s and (value = %s or value > %s) and docstatus != 2 and based_on = %s and ifnull(company,'') = '' %s" % ('%s', '%s', '%s', '%s', condition), (doctype_name, flt(max_amount), total, based_on)) + app_dtl = frappe.db.sql("select approving_user, approving_role from `tabAuthorization Rule` where transaction = %s and (value = %s or value > %s) and docstatus != 2 and based_on = %s and ifnull(company,'') = '' %s" % ('%s', '%s', '%s', '%s', condition), (doctype_name, flt(max_amount), total, based_on)) for d in app_dtl: if(d[0]): appr_users.append(d[0]) if(d[1]): appr_roles.append(d[1]) - + if not has_common(appr_roles, frappe.user.get_roles()) and not has_common(appr_users, [session['user']]): - msg, add_msg = '','' - if max_amount: - dcc = get_company_currency(self.company) - if based_on == 'Grand Total': msg = "since Grand Total exceeds %s. %s" % (dcc, flt(max_amount)) - elif based_on == 'Itemwise Discount': msg = "since Discount exceeds %s for Item Code : %s" % (cstr(max_amount)+'%', item) - elif based_on == 'Average Discount' or based_on == 'Customerwise Discount': msg = "since Discount exceeds %s" % (cstr(max_amount)+'%') - - if appr_users: add_msg = "Users : "+cstr(appr_users) - if appr_roles: add_msg = "Roles : "+cstr(appr_roles) - if appr_users and appr_roles: add_msg = "Users : "+cstr(appr_users)+" or "+"Roles : "+cstr(appr_roles) - msgprint("You are not authorize to submit this %s %s. Please send for approval to %s" % (doctype_name, msg, add_msg)) + frappe.msgprint(_("Not authroized since {0} exceeds limits").format(_(based_on))) + frappe.throw(_("Can be approved by {0}").format(comma_or(appr_roles + appr_users))) raise Exception @@ -64,12 +54,12 @@ class AuthorizationControl(TransactionBase): if chk == 1: if based_on == 'Itemwise Discount': add_cond2 += " and ifnull(master_name,'') = ''" appr = frappe.db.sql("select value from `tabAuthorization Rule` where transaction = %s and value <= %s and based_on = %s and company = %s and docstatus != 2 %s %s" % ('%s', '%s', '%s', '%s', cond, add_cond2), (doctype_name, total, based_on, company)) - + if not appr: appr = frappe.db.sql("select value from `tabAuthorization Rule` where transaction = %s and value <= %s and based_on = %s and ifnull(company,'') = '' and docstatus != 2 %s %s"% ('%s', '%s', '%s', cond, add_cond2), (doctype_name, total, based_on)) self.get_appr_user_role(appr, doctype_name, total, based_on, cond+add_cond2, item, company) - - + + # Bifurcate Authorization based on type # -------------------------------------- def bifurcate_based_on_type(self, doctype_name, total, av_dis, based_on, doc_obj, val, company): @@ -108,39 +98,39 @@ class AuthorizationControl(TransactionBase): # Individual User # ================ # Check for authorization set for individual user - + based_on = [x[0] for x in frappe.db.sql("select distinct based_on from `tabAuthorization Rule` where transaction = %s and system_user = %s and (company = %s or ifnull(company,'')='') and docstatus != 2", (doctype_name, session['user'], company))] for d in based_on: self.bifurcate_based_on_type(doctype_name, total, av_dis, d, doc_obj, 1, company) - + # Remove user specific rules from global authorization rules for r in based_on: if r in final_based_on and r != 'Itemwise Discount': final_based_on.remove(r) - + # Specific Role # =============== # Check for authorization set on particular roles - based_on = [x[0] for x in frappe.db.sql("""select based_on - from `tabAuthorization Rule` - where transaction = %s and system_role IN (%s) and based_on IN (%s) - and (company = %s or ifnull(company,'')='') + based_on = [x[0] for x in frappe.db.sql("""select based_on + from `tabAuthorization Rule` + where transaction = %s and system_role IN (%s) and based_on IN (%s) + and (company = %s or ifnull(company,'')='') and docstatus != 2 """ % ('%s', "'"+"','".join(frappe.user.get_roles())+"'", "'"+"','".join(final_based_on)+"'", '%s'), (doctype_name, company))] - + for d in based_on: self.bifurcate_based_on_type(doctype_name, total, av_dis, d, doc_obj, 2, company) - + # Remove role specific rules from global authorization rules for r in based_on: if r in final_based_on and r != 'Itemwise Discount': final_based_on.remove(r) - + # Global Rule # ============= # Check for global authorization for g in final_based_on: self.bifurcate_based_on_type(doctype_name, total, av_dis, g, doc_obj, 0, company) - + #======================================================================================================================== # payroll related check def get_value_based_rule(self,doctype_name,employee,total_claimed_amount,company): @@ -153,29 +143,29 @@ class AuthorizationControl(TransactionBase): val_lst = [y[0] for y in val] else: val_lst.append(0) - + max_val = max(val_lst) rule = frappe.db.sql("select name, to_emp, to_designation, approving_role, approving_user from `tabAuthorization Rule` where transaction=%s and company = %s and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s)) and ifnull(value,0)= %s and docstatus!=2",(doctype_name,company,employee,employee,flt(max_val)), as_dict=1) if not rule: rule = frappe.db.sql("select name, to_emp, to_designation, approving_role, approving_user from `tabAuthorization Rule` where transaction=%s and ifnull(company,'') = '' and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s)) and ifnull(value,0)= %s and docstatus!=2",(doctype_name,employee,employee,flt(max_val)), as_dict=1) return rule - + #--------------------------------------------------------------------------------------------------------------------- # related to payroll module only def get_approver_name(self, doctype_name, total, doc_obj=''): app_user=[] app_specific_user =[] rule ={} - + if doc_obj: if doctype_name == 'Expense Claim': rule = self.get_value_based_rule(doctype_name,doc_obj.employee,doc_obj.total_claimed_amount, doc_obj.company) elif doctype_name == 'Appraisal': - rule = frappe.db.sql("select name, to_emp, to_designation, approving_role, approving_user from `tabAuthorization Rule` where transaction=%s and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s)) and company = %s and docstatus!=2",(doctype_name,doc_obj.employee, doc_obj.employee, doc_obj.company),as_dict=1) + rule = frappe.db.sql("select name, to_emp, to_designation, approving_role, approving_user from `tabAuthorization Rule` where transaction=%s and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s)) and company = %s and docstatus!=2",(doctype_name,doc_obj.employee, doc_obj.employee, doc_obj.company),as_dict=1) if not rule: - rule = frappe.db.sql("select name, to_emp, to_designation, approving_role, approving_user from `tabAuthorization Rule` where transaction=%s and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s)) and ifnull(company,'') = '' and docstatus!=2",(doctype_name,doc_obj.employee, doc_obj.employee),as_dict=1) - + rule = frappe.db.sql("select name, to_emp, to_designation, approving_role, approving_user from `tabAuthorization Rule` where transaction=%s and (to_emp=%s or to_designation IN (select designation from `tabEmployee` where name=%s)) and ifnull(company,'') = '' and docstatus!=2",(doctype_name,doc_obj.employee, doc_obj.employee),as_dict=1) + if rule: for m in rule: if m['to_emp'] or m['to_designation']: @@ -186,7 +176,7 @@ class AuthorizationControl(TransactionBase): for x in user_lst: if not x in app_user: app_user.append(x) - + if len(app_specific_user) >0: return app_specific_user else: diff --git a/erpnext/setup/doctype/authorization_rule/authorization_rule.py b/erpnext/setup/doctype/authorization_rule/authorization_rule.py index 1c6daf26b2..58fb231a57 100644 --- a/erpnext/setup/doctype/authorization_rule/authorization_rule.py +++ b/erpnext/setup/doctype/authorization_rule/authorization_rule.py @@ -4,8 +4,8 @@ from __future__ import unicode_literals import frappe -from frappe.utils import cint, cstr, flt, has_common -from frappe import msgprint +from frappe.utils import cstr, flt +from frappe import _, msgprint from frappe.model.document import Document @@ -13,75 +13,41 @@ class AuthorizationRule(Document): def check_duplicate_entry(self): - exists = frappe.db.sql("""select name, docstatus from `tabAuthorization Rule` - where transaction = %s and based_on = %s and system_user = %s - and system_role = %s and approving_user = %s and approving_role = %s - and to_emp =%s and to_designation=%s and name != %s""", - (self.transaction, self.based_on, cstr(self.system_user), - cstr(self.system_role), cstr(self.approving_user), - cstr(self.approving_role), cstr(self.to_emp), + exists = frappe.db.sql("""select name, docstatus from `tabAuthorization Rule` + where transaction = %s and based_on = %s and system_user = %s + and system_role = %s and approving_user = %s and approving_role = %s + and to_emp =%s and to_designation=%s and name != %s""", + (self.transaction, self.based_on, cstr(self.system_user), + cstr(self.system_role), cstr(self.approving_user), + cstr(self.approving_role), cstr(self.to_emp), cstr(self.to_designation), self.name)) auth_exists = exists and exists[0][0] or '' if auth_exists: - if cint(exists[0][1]) == 2: - msgprint("""Duplicate Entry. Please untrash Authorization Rule : %s \ - from Recycle Bin""" % (auth_exists), raise_exception=1) - else: - msgprint("Duplicate Entry. Please check Authorization Rule : %s" % - (auth_exists), raise_exception=1) - - - def validate_master_name(self): - if self.based_on == 'Customerwise Discount' and \ - not frappe.db.sql("""select name from tabCustomer - where name = %s and docstatus != 2""", (self.master_name)): - msgprint("Please select valid Customer Name for Customerwise Discount", - raise_exception=1) - elif self.based_on == 'Itemwise Discount' and \ - not frappe.db.sql("select name from tabItem where name = %s and docstatus != 2", - (self.master_name)): - msgprint("Please select valid Item Name for Itemwise Discount", raise_exception=1) - elif (self.based_on == 'Grand Total' or \ - self.based_on == 'Average Discount') and self.master_name: - msgprint("Please remove Customer/Item Name for %s." % - self.based_on, raise_exception=1) + frappe.throw(_("Duplicate Entry. Please check Authorization Rule {0}").format(auth_exists)) def validate_rule(self): if self.transaction != 'Appraisal': if not self.approving_role and not self.approving_user: - msgprint("Please enter Approving Role or Approving User", raise_exception=1) + frappe.throw(_("Please enter Approving Role or Approving User")) elif self.system_user and self.system_user == self.approving_user: - msgprint("Approving User cannot be same as user the rule is Applicable To (User)", - raise_exception=1) + frappe.throw(_("Approving User cannot be same as user the rule is Applicable To")) elif self.system_role and self.system_role == self.approving_role: - msgprint("Approving Role cannot be same as user the rule is \ - Applicable To (Role).", raise_exception=1) - elif self.system_user and self.approving_role and \ - has_common([self.approving_role], [x[0] for x in \ - frappe.db.sql("select role from `tabUserRole` where parent = %s", \ - (self.system_user))]): - msgprint("System User : %s is assigned role : %s. So rule does not make sense" % - (self.system_user,self.approving_role), raise_exception=1) + frappe.throw(_("Approving Role cannot be same as role the rule is Applicable To")) elif self.transaction in ['Purchase Order', 'Purchase Receipt', \ 'Purchase Invoice', 'Stock Entry'] and self.based_on \ in ['Average Discount', 'Customerwise Discount', 'Itemwise Discount']: - msgprint("You cannot set authorization on basis of Discount for %s" % - self.transaction, raise_exception=1) + frappe.throw(_("Cannot set authorization on basis of Discount for {0}").format(self.transaction)) elif self.based_on == 'Average Discount' and flt(self.value) > 100.00: - msgprint("Discount cannot given for more than 100%", raise_exception=1) + frappe.throw(_("Discount must be less than 100")) elif self.based_on == 'Customerwise Discount' and not self.master_name: - msgprint("Please enter Customer Name for 'Customerwise Discount'", - raise_exception=1) + frappe.throw(_("Customer required for 'Customerwise Discount'")) else: - if self.transaction == 'Appraisal' and self.based_on != 'Not Applicable': - msgprint("Based on should be 'Not Applicable' while setting authorization rule\ - for 'Appraisal'", raise_exception=1) - - + if self.transaction == 'Appraisal': + self.based_on = "Not Applicable" def validate(self): self.check_duplicate_entry() self.validate_rule() self.validate_master_name() - if not self.value: self.value = 0.0 \ No newline at end of file + if not self.value: self.value = 0.0 diff --git a/erpnext/setup/doctype/backup_manager/backup_googledrive.py b/erpnext/setup/doctype/backup_manager/backup_googledrive.py index 0ea64ba26f..70bda35aa1 100644 --- a/erpnext/setup/doctype/backup_manager/backup_googledrive.py +++ b/erpnext/setup/doctype/backup_manager/backup_googledrive.py @@ -20,7 +20,7 @@ import mimetypes import frappe import oauth2client.client from frappe.utils import cstr -from frappe import _, msgprint +from frappe import _ from apiclient.discovery import build from apiclient.http import MediaFileUpload @@ -71,17 +71,17 @@ def backup_to_gdrive(): backup = new_backup() path = os.path.join(frappe.local.site_path, "public", "backups") filename = os.path.join(path, os.path.basename(backup.backup_path_db)) - + # upload files to database folder - upload_files(filename, 'application/x-gzip', drive_service, + upload_files(filename, 'application/x-gzip', drive_service, frappe.db.get_value("Backup Manager", None, "database_folder_id")) - + # upload files to files folder did_not_upload = [] error_log = [] - + files_folder_id = frappe.db.get_value("Backup Manager", None, "files_folder_id") - + frappe.db.close() path = os.path.join(frappe.local.site_path, "public", "files") for filename in os.listdir(path): @@ -94,7 +94,7 @@ def backup_to_gdrive(): mimetype = 'application/x-gzip' else: mimetype = mimetypes.types_map.get("." + ext) or "application/octet-stream" - + #Compare Local File with Server File children = drive_service.children().list(folderId=files_folder_id).execute() for child in children.get('items', []): @@ -108,29 +108,28 @@ def backup_to_gdrive(): except Exception, e: did_not_upload.append(filename) error_log.append(cstr(e)) - + frappe.connect() return did_not_upload, list(set(error_log)) def get_gdrive_flow(): from oauth2client.client import OAuth2WebServerFlow from frappe import conf - - if not "gdrive_client_id" in conf: - frappe.msgprint(_("Please set Google Drive access keys in") + " conf.py", - raise_exception=True) - flow = OAuth2WebServerFlow(conf.gdrive_client_id, conf.gdrive_client_secret, + if not "gdrive_client_id" in conf: + frappe.throw(_("Please set Google Drive access keys in {0}"),format("site_config.json")) + + flow = OAuth2WebServerFlow(conf.gdrive_client_id, conf.gdrive_client_secret, "https://www.googleapis.com/auth/drive", 'urn:ietf:wg:oauth:2.0:oob') return flow - + @frappe.whitelist() def gdrive_callback(verification_code = None): flow = get_gdrive_flow() if verification_code: credentials = flow.step2_exchange(verification_code) allowed = 1 - + # make folders to save id http = httplib2.Http() http = credentials.authorize(http) @@ -145,7 +144,7 @@ def gdrive_callback(verification_code = None): final_credentials = credentials.to_json() frappe.db.set_value("Backup Manager", "Backup Manager", "gdrive_credentials", final_credentials) - frappe.msgprint("Updated") + frappe.msgprint(_("Updated")) def create_erpnext_folder(service): if not frappe.db: diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index 7355bd2b28..6526832027 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -3,9 +3,9 @@ from __future__ import unicode_literals import frappe -from frappe import _, msgprint +from frappe import _ -from frappe.utils import cstr, cint +from frappe.utils import cint import frappe.defaults @@ -13,10 +13,10 @@ from frappe.model.document import Document class Company(Document): - + def onload(self): self.set("__transactions_exist", self.check_if_transactions_exist()) - + def check_if_transactions_exist(self): exists = False for doctype in ["Sales Invoice", "Delivery Note", "Sales Order", "Quotation", @@ -25,31 +25,30 @@ class Company(Document): limit 1""" % (doctype, "%s"), self.name): exists = True break - + return exists - + def validate(self): if self.get('__islocal') and len(self.abbr) > 5: - frappe.msgprint("Abbreviation cannot have more than 5 characters", - raise_exception=1) - + frappe.throw(_("Abbreviation cannot have more than 5 characters")) + self.previous_default_currency = frappe.db.get_value("Company", self.name, "default_currency") if self.default_currency and self.previous_default_currency and \ self.default_currency != self.previous_default_currency and \ self.check_if_transactions_exist(): - msgprint(_("Sorry! You cannot change company's default currency, because there are existing transactions against it. You will need to cancel those transactions if you want to change the default currency."), raise_exception=True) + frappe.throw(_("Cannot change company's default currency, because there are existing transactions. Transactions must be cancelled to change the default currency.")) def on_update(self): - if not frappe.db.sql("""select name from tabAccount + if not frappe.db.sql("""select name from tabAccount where company=%s and docstatus<2 limit 1""", self.name): self.create_default_accounts() self.create_default_warehouses() self.create_default_web_page() - - if not frappe.db.get_value("Cost Center", {"group_or_ledger": "Ledger", + + if not frappe.db.get_value("Cost Center", {"group_or_ledger": "Ledger", "company": self.name}): self.create_default_cost_center() - + self.set_default_accounts() if self.default_currency: @@ -58,7 +57,7 @@ class Company(Document): def create_default_warehouses(self): for whname in ("Stores", "Work In Progress", "Finished Goods"): if not frappe.db.exists("Warehouse", whname + " - " + self.abbr): - stock_group = frappe.db.get_value("Account", {"account_type": "Stock", + stock_group = frappe.db.get_value("Account", {"account_type": "Stock", "group_or_ledger": "Group"}) if stock_group: frappe.get_doc({ @@ -67,7 +66,7 @@ class Company(Document): "company": self.name, "create_account_under": stock_group }).insert() - + def create_default_web_page(self): if not frappe.db.get_value("Website Settings", None, "home_page") and \ not frappe.db.sql("select name from tabCompany where name!=%s", self.name): @@ -80,7 +79,7 @@ class Company(Document): "description": "Standard Home Page for " + self.name, "main_section": webfile.read() % self.as_dict() }).insert() - + # update in home page in settings website_settings = frappe.get_doc("Website Settings", "Website Settings") website_settings.home_page = webpage.name @@ -109,7 +108,7 @@ class Company(Document): self.create_standard_accounts() frappe.db.set(self, "receivables_group", "Accounts Receivable - " + self.abbr) frappe.db.set(self, "payables_group", "Accounts Payable - " + self.abbr) - + def import_chart_of_account(self): chart = frappe.get_doc("Chart of Accounts", self.chart_of_accounts) chart.create_accounts(self.name) @@ -120,7 +119,7 @@ class Company(Document): "freeze_account": "No", "master_type": "", }) - + for d in self.fld_dict.keys(): account.set(d, (d == 'parent_account' and lst[self.fld_dict[d]]) and lst[self.fld_dict[d]] +' - '+ self.abbr or lst[self.fld_dict[d]]) account.insert() @@ -128,17 +127,17 @@ class Company(Document): def set_default_accounts(self): def _set_default_accounts(accounts): for field, account_type in accounts.items(): - account = frappe.db.get_value("Account", {"account_type": account_type, + account = frappe.db.get_value("Account", {"account_type": account_type, "group_or_ledger": "Ledger", "company": self.name}) if account and not self.get(field): frappe.db.set(self, field, account) - + _set_default_accounts({ "default_cash_account": "Cash", "default_bank_account": "Bank" }) - + if cint(frappe.db.get_value("Accounts Settings", None, "auto_accounting_for_stock")): _set_default_accounts({ "stock_received_but_not_billed": "Stock Received But Not Billed", @@ -153,9 +152,9 @@ class Company(Document): 'company':self.name, 'group_or_ledger':'Group', 'parent_cost_center':'' - }, + }, { - 'cost_center_name':'Main', + 'cost_center_name':'Main', 'company':self.name, 'group_or_ledger':'Ledger', 'parent_cost_center':self.name + ' - ' + self.abbr @@ -165,11 +164,11 @@ class Company(Document): cc.update({"doctype": "Cost Center"}) cc_doc = frappe.get_doc(cc) cc_doc.ignore_permissions = True - + if cc.get("cost_center_name") == self.name: cc_doc.ignore_mandatory = True cc_doc.insert() - + frappe.db.set(self, "cost_center", "Main - " + self.abbr) def on_trash(self): @@ -180,33 +179,33 @@ class Company(Document): if not rec: #delete tabAccount frappe.db.sql("delete from `tabAccount` where company = %s order by lft desc, rgt desc", self.name) - + #delete cost center child table - budget detail frappe.db.sql("delete bd.* from `tabBudget Detail` bd, `tabCost Center` cc where bd.parent = cc.name and cc.company = %s", self.name) #delete cost center frappe.db.sql("delete from `tabCost Center` WHERE company = %s order by lft desc, rgt desc", self.name) - + if not frappe.db.get_value("Stock Ledger Entry", {"company": self.name}): frappe.db.sql("""delete from `tabWarehouse` where company=%s""", self.name) - + frappe.defaults.clear_default("company", value=self.name) - + frappe.db.sql("""update `tabSingles` set value="" - where doctype='Global Defaults' and field='default_company' + where doctype='Global Defaults' and field='default_company' and value=%s""", self.name) - + def before_rename(self, olddn, newdn, merge=False): if merge: frappe.throw(_("Sorry, companies cannot be merged")) - + def after_rename(self, olddn, newdn, merge=False): frappe.db.set(self, "company_name", newdn) - frappe.db.sql("""update `tabDefaultValue` set defvalue=%s + frappe.db.sql("""update `tabDefaultValue` set defvalue=%s where defkey='Company' and defvalue=%s""", (newdn, olddn)) frappe.defaults.clear_cache() - + def create_standard_accounts(self): self.fld_dict = { 'account_name': 0, @@ -217,7 +216,7 @@ class Company(Document): 'company': 5, 'tax_rate': 6 } - + acc_list_common = [ ['Application of Funds (Assets)','','Group','','Balance Sheet',self.name,''], ['Current Assets','Application of Funds (Assets)','Group','','Balance Sheet',self.name,''], @@ -282,7 +281,7 @@ class Company(Document): ['Current Liabilities','Source of Funds (Liabilities)','Group','','Balance Sheet',self.name,''], ['Accounts Payable','Current Liabilities','Group','','Balance Sheet',self.name,''], ['Stock Liabilities','Current Liabilities','Group','','Balance Sheet',self.name,''], - ['Stock Received But Not Billed', 'Stock Liabilities', 'Ledger', 'Stock Received But Not Billed', 'Balance Sheet', self.name, ''], + ['Stock Received But Not Billed', 'Stock Liabilities', 'Ledger', 'Stock Received But Not Billed', 'Balance Sheet', self.name, ''], ['Duties and Taxes','Current Liabilities','Group','','Balance Sheet',self.name,''], ['Loans (Liabilities)','Current Liabilities','Group','','Balance Sheet',self.name,''], ['Secured Loans','Loans (Liabilities)','Group','','Balance Sheet',self.name,''], @@ -291,7 +290,7 @@ class Company(Document): ['Temporary Accounts (Liabilities)','Source of Funds (Liabilities)','Group','','Balance Sheet',self.name,''], ['Temporary Account (Liabilities)','Temporary Accounts (Liabilities)','Ledger','','Balance Sheet',self.name,''] ] - + acc_list_india = [ ['CENVAT Capital Goods','Tax Assets','Ledger','Chargeable','Balance Sheet',self.name,''], ['CENVAT','Tax Assets','Ledger','Chargeable','Balance Sheet',self.name,''], @@ -342,23 +341,23 @@ class Company(Document): @frappe.whitelist() def replace_abbr(company, old, new): frappe.db.set_value("Company", company, "abbr", new) - + def _rename_record(dt): for d in frappe.db.sql("select name from `tab%s` where company=%s" % (dt, '%s'), company): parts = d[0].split(" - ") if parts[-1].lower() == old.lower(): name_without_abbr = " - ".join(parts[:-1]) frappe.rename_doc(dt, d[0], name_without_abbr + " - " + new) - + for dt in ["Account", "Cost Center", "Warehouse"]: _rename_record(dt) frappe.db.commit() def get_name_with_abbr(name, company): - company_abbr = frappe.db.get_value("Company", company, "abbr") + company_abbr = frappe.db.get_value("Company", company, "abbr") parts = name.split(" - ") if parts[-1].lower() != company_abbr.lower(): parts.append(company_abbr) - + return " - ".join(parts) diff --git a/erpnext/setup/doctype/currency_exchange/currency_exchange.py b/erpnext/setup/doctype/currency_exchange/currency_exchange.py index e22f035b92..c15c2151c6 100644 --- a/erpnext/setup/doctype/currency_exchange/currency_exchange.py +++ b/erpnext/setup/doctype/currency_exchange/currency_exchange.py @@ -5,16 +5,16 @@ from __future__ import unicode_literals import frappe -from frappe import _, msgprint +from frappe import _ from frappe.model.controller import DocListController class CurrencyExchange(DocListController): - + def autoname(self): self.name = self.from_currency + "-" + self.to_currency - + def validate(self): self.validate_value("exchange_rate", ">", 0) - + if self.from_currency == self.to_currency: - msgprint(_("From Currency and To Currency cannot be same"), raise_exception=True) \ No newline at end of file + frappe.throw(_("From Currency and To Currency cannot be same")) diff --git a/erpnext/setup/doctype/customer_group/customer_group.py b/erpnext/setup/doctype/customer_group/customer_group.py index 11a15faae3..0eefebe989 100644 --- a/erpnext/setup/doctype/customer_group/customer_group.py +++ b/erpnext/setup/doctype/customer_group/customer_group.py @@ -3,45 +3,20 @@ from __future__ import unicode_literals import frappe -from frappe import msgprint +from frappe import _ + - from frappe.utils.nestedset import NestedSet class CustomerGroup(NestedSet): nsm_parent_field = 'parent_customer_group'; - def validate(self): - if frappe.db.sql("select name from `tabCustomer Group` where name = %s and docstatus = 2", - (self.customer_group_name)): - msgprint("""Another %s record is trashed. - To untrash please go to Setup -> Recycle Bin.""" % - (self.customer_group_name), raise_exception = 1) - def on_update(self): self.validate_name_with_customer() super(CustomerGroup, self).on_update() self.validate_one_root() - + def validate_name_with_customer(self): if frappe.db.exists("Customer", self.name): - frappe.msgprint("An Customer exists with same name (%s), \ - please change the Customer Group name or rename the Customer" % + frappe.msgprint(_("An Customer exists with same name (%s), \ + please change the Customer Group name or rename the Customer") % self.name, raise_exception=1) - - def on_trash(self): - cust = frappe.db.sql("select name from `tabCustomer` where ifnull(customer_group, '') = %s", - self.name) - cust = [d[0] for d in cust] - if cust: - msgprint("""Customer Group: %s can not be trashed/deleted \ - because it is used in customer: %s. - To trash/delete this, remove/change customer group in customer master""" % - (self.name, cust or ''), raise_exception=1) - - if frappe.db.sql("select name from `tabCustomer Group` where parent_customer_group = %s \ - and docstatus != 2", self.name): - msgprint("Child customer group exists for this customer group. \ - You can not trash/cancel/delete this customer group.", raise_exception=1) - - # rebuild tree - super(CustomerGroup, self).on_trash() diff --git a/erpnext/setup/doctype/global_defaults/global_defaults.py b/erpnext/setup/doctype/global_defaults/global_defaults.py index 93d75a1d2e..90861dec2a 100644 --- a/erpnext/setup/doctype/global_defaults/global_defaults.py +++ b/erpnext/setup/doctype/global_defaults/global_defaults.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals """Global Defaults""" import frappe +from frappe import _ import frappe.defaults from frappe.utils import cint @@ -25,17 +26,17 @@ keydict = { from frappe.model.document import Document class GlobalDefaults(Document): - + def on_update(self): """update defaults""" self.validate_session_expiry() self.set_country_and_timezone() - + for key in keydict: frappe.db.set_default(key, self.get(keydict[key], '')) - + # update year start date and year end date from fiscal_year - year_start_end_date = frappe.db.sql("""select year_start_date, year_end_date + year_start_end_date = frappe.db.sql("""select year_start_date, year_end_date from `tabFiscal Year` where name=%s""", self.current_fiscal_year) ysd = year_start_end_date[0][0] or '' @@ -44,20 +45,19 @@ class GlobalDefaults(Document): if ysd and yed: frappe.db.set_default('year_start_date', ysd.strftime('%Y-%m-%d')) frappe.db.set_default('year_end_date', yed.strftime('%Y-%m-%d')) - + # enable default currency if self.default_currency: frappe.db.set_value("Currency", self.default_currency, "enabled", 1) - + # clear cache frappe.clear_cache() - + def validate_session_expiry(self): if self.session_expiry: parts = self.session_expiry.split(":") if len(parts)!=2 or not (cint(parts[0]) or cint(parts[1])): - frappe.msgprint("""Session Expiry must be in format hh:mm""", - raise_exception=1) + frappe.throw(_("Session Expiry must be in format {0}").format("hh:mm")) def set_country_and_timezone(self): frappe.db.set_default("country", self.country) diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py index 4b0dc117c8..700e39a61b 100644 --- a/erpnext/setup/doctype/item_group/item_group.py +++ b/erpnext/setup/doctype/item_group/item_group.py @@ -34,5 +34,4 @@ class ItemGroup(NestedSet, WebsiteGenerator): def validate_name_with_item(self): if frappe.db.exists("Item", self.name): - frappe.msgprint("An item exists with same name (%s), please change the \ - item group name or rename the item" % self.name, raise_exception=1) + frappe.throw(frappe._("An item exists with same name ({0}), please change the item group name or rename the item").format(self.name)) diff --git a/erpnext/setup/doctype/jobs_email_settings/jobs_email_settings.py b/erpnext/setup/doctype/jobs_email_settings/jobs_email_settings.py index 94874f2233..5d8bab84b7 100644 --- a/erpnext/setup/doctype/jobs_email_settings/jobs_email_settings.py +++ b/erpnext/setup/doctype/jobs_email_settings/jobs_email_settings.py @@ -11,10 +11,9 @@ from frappe.utils import cint from frappe.model.document import Document class JobsEmailSettings(Document): - + def validate(self): if cint(self.extract_emails) and not (self.email_id and self.host and \ self.username and self.password): - - frappe.msgprint(_("""Host, Email and Password required if emails are to be pulled"""), - raise_exception=True) \ No newline at end of file + + frappe.throw(_("""Host, Email and Password required if emails are to be pulled""")) diff --git a/erpnext/setup/doctype/notification_control/notification_control.py b/erpnext/setup/doctype/notification_control/notification_control.py index 87674ecd11..1e57ad5eb7 100644 --- a/erpnext/setup/doctype/notification_control/notification_control.py +++ b/erpnext/setup/doctype/notification_control/notification_control.py @@ -4,8 +4,7 @@ from __future__ import unicode_literals import frappe -from frappe import msgprint - +from frappe import _ from frappe.model.document import Document @@ -18,5 +17,5 @@ class NotificationControl(Document): def set_message(self, arg = ''): fn = self.select_transaction.lower().replace(' ', '_') + '_message' frappe.db.set(self, fn, self.custom_message) - msgprint("Custom Message for %s updated!" % self.select_transaction) + frappe.msgprint(_("Message updated")) diff --git a/erpnext/setup/doctype/territory/territory.py b/erpnext/setup/doctype/territory/territory.py index 83eae91c37..890e7789c9 100644 --- a/erpnext/setup/doctype/territory/territory.py +++ b/erpnext/setup/doctype/territory/territory.py @@ -6,17 +6,17 @@ import frappe from frappe.utils import flt +from frappe import _ from frappe.utils.nestedset import NestedSet - + class Territory(NestedSet): nsm_parent_field = 'parent_territory' - def validate(self): + def validate(self): for d in self.get('target_details'): if not flt(d.target_qty) and not flt(d.target_amount): - msgprint("Either target qty or target amount is mandatory.") - raise Exception + frappe.throw(_("Either target qty or target amount is mandatory")) def on_update(self): super(Territory, self).on_update() diff --git a/erpnext/setup/utils.py b/erpnext/setup/utils.py index 0bd614fe57..63d18d24f6 100644 --- a/erpnext/setup/utils.py +++ b/erpnext/setup/utils.py @@ -13,33 +13,29 @@ def get_company_currency(company): if not currency: throw(_('Please specify Default Currency in Company Master \ and Global Defaults')) - + return currency def get_root_of(doctype): """Get root element of a DocType with a tree structure""" - result = frappe.db.sql_list("""select name from `tab%s` - where lft=1 and rgt=(select max(rgt) from `tab%s` where docstatus < 2)""" % + result = frappe.db.sql_list("""select name from `tab%s` + where lft=1 and rgt=(select max(rgt) from `tab%s` where docstatus < 2)""" % (doctype, doctype)) return result[0] if result else None - + def get_ancestors_of(doctype, name): """Get ancestor elements of a DocType with a tree structure""" lft, rgt = frappe.db.get_value(doctype, name, ["lft", "rgt"]) - result = frappe.db.sql_list("""select name from `tab%s` + result = frappe.db.sql_list("""select name from `tab%s` where lft<%s and rgt>%s order by lft desc""" % (doctype, "%s", "%s"), (lft, rgt)) return result or [] @frappe.whitelist() def get_price_list_currency(price_list): - price_list_currency = frappe.db.get_value("Price List", {"name": price_list, + price_list_currency = frappe.db.get_value("Price List", {"name": price_list, "enabled": 1}, "currency") if not price_list_currency: - throw("{message}: {price_list} {disabled}".format(**{ - "message": _("Price List"), - "price_list": price_list, - "disabled": _("is disabled.") - })) + throw(_("Price List {0} is disabled").format(price_list)) else: - return {"price_list_currency": price_list_currency} \ No newline at end of file + return {"price_list_currency": price_list_currency} diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py index e91c36dd74..95882c694c 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.py +++ b/erpnext/stock/doctype/delivery_note/delivery_note.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import frappe -from frappe.utils import cstr, flt, cint +from frappe.utils import flt, cint from frappe import msgprint, _ import frappe.defaults @@ -54,9 +54,7 @@ class DeliveryNote(SellingController): if frappe.db.get_value("Selling Settings", None, 'so_required') == 'Yes': for d in self.get('delivery_note_details'): if not d.against_sales_order: - msgprint("Sales Order No. required against item %s"%d.item_code) - raise Exception - + frappe.throw(_("Sales Order required for Item {0}").format(d.item_code)) def validate(self): super(DeliveryNote, self).validate() @@ -108,8 +106,7 @@ class DeliveryNote(SellingController): where name = %s and (customer = %s or ifnull(customer,'')='')""", (self.project_name, self.customer)) if not res: - msgprint("Customer - %s does not belong to project - %s. \n\nIf you want to use project for multiple customers then please make customer details blank in project - %s."%(self.customer,self.project_name,self.project_name)) - raise Exception + frappe.throw(_("Customer {0} does not belong to project {1}").format(self.customer, self.project_name)) def validate_for_items(self): check_list, chk_dupl_itm = [], [] @@ -119,14 +116,12 @@ class DeliveryNote(SellingController): if frappe.db.get_value("Item", d.item_code, "is_stock_item") == 'Yes': if e in check_list: - msgprint("Please check whether item %s has been entered twice wrongly." - % d.item_code) + msgprint(_("Note: Item {0} entered multiple times").format(d.item_code)) else: check_list.append(e) else: if f in chk_dupl_itm: - msgprint("Please check whether item %s has been entered twice wrongly." - % d.item_code) + msgprint(_("Note: Item {0} entered multiple times").format(d.item_code)) else: chk_dupl_itm.append(f) @@ -134,8 +129,7 @@ class DeliveryNote(SellingController): for d in self.get_item_list(): if frappe.db.get_value("Item", d['item_code'], "is_stock_item") == "Yes": if not d['warehouse']: - msgprint("Please enter Warehouse for item %s as it is stock item" - % d['item_code'], raise_exception=1) + frappe.throw(_("Warehouse required for stock Item {0}").format(d["item_code"])) def update_current_stock(self): @@ -187,18 +181,13 @@ class DeliveryNote(SellingController): """ if not any([flt(d.get('packed_qty')) for d in self.get(self.fname)]): return - packing_error_list = [] + has_error = False for d in self.get(self.fname): if flt(d.get('qty')) != flt(d.get('packed_qty')): - packing_error_list.append([ - d.get('item_code', ''), - d.get('qty', 0), - d.get('packed_qty', 0) - ]) - if packing_error_list: - err_msg = "\n".join([("Item: " + d[0] + ", Qty: " + cstr(d[1]) \ - + ", Packed: " + cstr(d[2])) for d in packing_error_list]) - frappe.msgprint("Packing Error:\n" + err_msg, raise_exception=1) + frappe.msgprint(_("Packed quantity must equal quantity for Item {0} in row {1}").format(d.item_code, d.idx)) + has_error = True + if has_error: + raise frappe.ValidationError def check_next_docstatus(self): submit_rv = frappe.db.sql("""select t1.name @@ -206,16 +195,14 @@ class DeliveryNote(SellingController): where t1.name = t2.parent and t2.delivery_note = %s and t1.docstatus = 1""", (self.name)) if submit_rv: - msgprint("Sales Invoice : " + cstr(submit_rv[0][0]) + " has already been submitted !") - raise Exception , "Validation Error." + frappe.throw(_("Sales Invoice {0} has already been submitted").format(submit_rv[0][0])) submit_in = frappe.db.sql("""select t1.name from `tabInstallation Note` t1, `tabInstallation Note Item` t2 where t1.name = t2.parent and t2.prevdoc_docname = %s and t1.docstatus = 1""", (self.name)) if submit_in: - msgprint("Installation Note : "+cstr(submit_in[0][0]) +" has already been submitted !") - raise Exception , "Validation Error." + frappe.throw(_("Installation Note {0} has already been submitted").format(submit_in[0][0])) def cancel_packing_slips(self): """ @@ -228,7 +215,7 @@ class DeliveryNote(SellingController): for r in res: ps = frappe.get_doc('Packing Slip', r[0]) ps.cancel() - frappe.msgprint(_("Packing Slip(s) Cancelled")) + frappe.msgprint(_("Packing Slip(s) cancelled")) def update_stock_ledger(self): @@ -293,8 +280,7 @@ def make_sales_invoice(source_name, target_doc=None): si.run_method("onload_post_render") if len(si.get("entries")) == 0: - frappe.msgprint(_("All these items have already been invoiced."), - raise_exception=True) + frappe.throw(_("All these items have already been invoiced")) def update_item(source_doc, target_doc, source_parent): target_doc.qty = source_doc.qty - invoiced_qty_map.get(source_doc.name, 0) diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 1bdab9e5cd..45c571c0d8 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -18,13 +18,13 @@ class Item(WebsiteGenerator): from frappe.model.naming import make_autoname self.item_code = make_autoname(self.naming_series+'.#####') elif not self.item_code: - msgprint(_("Item Code (item_code) is mandatory because Item naming is not sequential."), raise_exception=1) + msgprint(_("Item Code is mandatory because Item is not automatically numbered"), raise_exception=1) self.name = self.item_code def validate(self): if not self.stock_uom: - msgprint(_("Please enter Default Unit of Measure"), raise_exception=1) + msgprint(_("Please enter default Unit of Measure"), raise_exception=1) self.check_warehouse_is_set_for_stock_item() self.check_stock_uom_with_bin() @@ -51,7 +51,7 @@ class Item(WebsiteGenerator): def check_warehouse_is_set_for_stock_item(self): if self.is_stock_item=="Yes" and not self.default_warehouse: - frappe.msgprint(_("Default Warehouse is mandatory for Stock Item."), + frappe.msgprint(_("Default Warehouse is mandatory for stock Item."), raise_exception=WarehouseNotSet) def add_default_uom_in_conversion_factor_table(self): @@ -97,17 +97,12 @@ class Item(WebsiteGenerator): check_list = [] for d in self.get('uom_conversion_details'): if cstr(d.uom) in check_list: - msgprint(_("UOM %s has been entered more than once in Conversion Factor Table." % - cstr(d.uom)), raise_exception=1) + frappe.throw(_("Unit of Measure {0} has been entered more than once in Conversion Factor Table").format(d.uom)) else: check_list.append(cstr(d.uom)) if d.uom and cstr(d.uom) == cstr(self.stock_uom) and flt(d.conversion_factor) != 1: - msgprint(_("""Conversion Factor of UOM: %s should be equal to 1. As UOM: %s is Stock UOM of Item: %s.""" % - (d.uom, d.uom, self.name)), raise_exception=1) - elif d.uom and cstr(d.uom)!= self.stock_uom and flt(d.conversion_factor) == 1: - msgprint(_("""Conversion Factor of UOM: %s should not be equal to 1. As UOM: %s is not Stock UOM of Item: %s""" % - (d.uom, d.uom, self.name)), raise_exception=1) + frappe.throw(_("Conversion factor for default Unit of Measure must be 1 in row {0}").format(d.idx)) def validate_item_type(self): if cstr(self.is_manufactured_item) == "No": @@ -118,7 +113,7 @@ class Item(WebsiteGenerator): it must be a stock item.")) if self.has_serial_no == 'Yes' and self.is_stock_item == 'No': - msgprint("'Has Serial No' can not be 'Yes' for non-stock item", raise_exception=1) + msgprint(_("'Has Serial No' can not be 'Yes' for non-stock item"), raise_exception=1) def check_for_active_boms(self): if self.is_purchase_item != "Yes": @@ -153,10 +148,10 @@ class Item(WebsiteGenerator): account_type = frappe.db.get_value("Account", d.tax_type, "account_type") if account_type not in ['Tax', 'Chargeable', 'Income Account', 'Expense Account']: - msgprint("'%s' is not Tax / Chargeable / Income / Expense Account" % d.tax_type, raise_exception=1) + frappe.throw(_("Item Tax Row {0} must have account of type Tax or Income or Expense or Chargeable").format(d.idx)) else: if d.tax_type in check_list: - msgprint("Rate is entered twice for: '%s'" % d.tax_type, raise_exception=1) + frappe.throw(_("{0} entered twice in Item Tax").format(d.tax_type)) else: check_list.append(d.tax_type) @@ -165,8 +160,7 @@ class Item(WebsiteGenerator): duplicate = frappe.db.sql("""select name from tabItem where barcode = %s and name != %s""", (self.barcode, self.name)) if duplicate: - msgprint("Barcode: %s already used in item: %s" % - (self.barcode, cstr(duplicate[0][0])), raise_exception = 1) + frappe.throw(_("Barcode {0} already used in Item {1}").format(self.barcode, duplicate[0][0])) def cant_change(self): if not self.get("__islocal"): @@ -182,8 +176,7 @@ class Item(WebsiteGenerator): def validate_item_type_for_reorder(self): if self.re_order_level or len(self.get("item_reorder", {"material_request_type": "Purchase"})): if not self.is_purchase_item: - frappe.msgprint(_("""To set reorder level, item must be Purchase Item"""), - raise_exception=1) + frappe.throw(_("""To set reorder level, item must be Purchase Item""")) def check_if_sle_exists(self): sle = frappe.db.sql("""select name from `tabStock Ledger Entry` @@ -193,9 +186,7 @@ class Item(WebsiteGenerator): def validate_name_with_item_group(self): # causes problem with tree build if frappe.db.exists("Item Group", self.name): - frappe.msgprint("An item group exists with same name (%s), \ - please change the item name or rename the item group" % - self.name, raise_exception=1) + frappe.throw(_("An Item Group exists with same name, please change the item name or rename the item group")) def update_item_price(self): frappe.db.sql("""update `tabItem Price` set item_name=%s, @@ -269,14 +260,7 @@ def validate_end_of_life(item_code, end_of_life=None, verbose=1): end_of_life = frappe.db.get_value("Item", item_code, "end_of_life") if end_of_life and getdate(end_of_life) <= now_datetime().date(): - msg = (_("Item") + " %(item_code)s: " + _("reached its end of life on") + \ - " %(date)s. " + _("Please check") + ": %(end_of_life_label)s " + \ - "in Item master") % { - "item_code": item_code, - "date": formatdate(end_of_life), - "end_of_life_label": frappe.get_meta("Item").get_label("end_of_life") - } - + msg = _("Item {0} has reached its end of life on {1}").format(item_code, formatdate(end_of_life)) _msgprint(msg, verbose) def validate_is_stock_item(item_code, is_stock_item=None, verbose=1): @@ -284,9 +268,7 @@ def validate_is_stock_item(item_code, is_stock_item=None, verbose=1): is_stock_item = frappe.db.get_value("Item", item_code, "is_stock_item") if is_stock_item != "Yes": - msg = (_("Item") + " %(item_code)s: " + _("is not a Stock Item")) % { - "item_code": item_code, - } + msg = _("Item {0} is not a stock Item").format(item_code) _msgprint(msg, verbose) @@ -295,10 +277,7 @@ def validate_cancelled_item(item_code, docstatus=None, verbose=1): docstatus = frappe.db.get_value("Item", item_code, "docstatus") if docstatus == 2: - msg = (_("Item") + " %(item_code)s: " + _("is a cancelled Item")) % { - "item_code": item_code, - } - + msg = _("Item {0} is cancelled").format(item_code) _msgprint(msg, verbose) def _msgprint(msg, verbose): diff --git a/erpnext/stock/doctype/landed_cost_wizard/landed_cost_wizard.py b/erpnext/stock/doctype/landed_cost_wizard/landed_cost_wizard.py index e7cb41035b..b1a67e25f3 100644 --- a/erpnext/stock/doctype/landed_cost_wizard/landed_cost_wizard.py +++ b/erpnext/stock/doctype/landed_cost_wizard/landed_cost_wizard.py @@ -9,20 +9,20 @@ from frappe import msgprint, _ from frappe.model.document import Document class LandedCostWizard(Document): - + def update_landed_cost(self): """ - Add extra cost and recalculate all values in pr, + Add extra cost and recalculate all values in pr, Recalculate valuation rate in all sle after pr posting date """ - purchase_receipts = [row.purchase_receipt for row in + purchase_receipts = [row.purchase_receipt for row in self.get("lc_pr_details")] - + self.validate_purchase_receipts(purchase_receipts) self.cancel_pr(purchase_receipts) self.add_charges_in_pr(purchase_receipts) self.submit_pr(purchase_receipts) - msgprint("Landed Cost updated successfully") + msgprint(_("Landed Cost updated successfully")) def validate_purchase_receipts(self, purchase_receipts): for pr in purchase_receipts: @@ -32,21 +32,21 @@ class LandedCostWizard(Document): def add_charges_in_pr(self, purchase_receipts): """ Add additional charges in selected pr proportionately""" total_amt = self.get_total_pr_amt(purchase_receipts) - + for pr in purchase_receipts: pr_doc = frappe.get_doc('Purchase Receipt', pr) pr_items = pr_doc.get("purchase_tax_details") - + for lc in self.get("landed_cost_details"): amt = flt(lc.amount) * flt(pr_doc.net_total)/ flt(total_amt) - + matched_row = pr_doc.get("other_charges", { "category": "Valuation", "add_deduct_tax": "Add", "charge_type": "Actual", "account_head": lc.account_head }) - + if not matched_row: # add if not exists ch = pr_doc.append("other_charges") ch.category = 'Valuation' @@ -63,30 +63,30 @@ class LandedCostWizard(Document): matched_row[0].rate = amt matched_row[0].tax_amount = amt matched_row[0].cost_center = lc.cost_center - + pr_doc.run_method("validate") for d in pr_doc.get_all_children(): d.db_update() - + def get_total_pr_amt(self, purchase_receipts): - return frappe.db.sql("""SELECT SUM(net_total) FROM `tabPurchase Receipt` - WHERE name in (%s)""" % ', '.join(['%s']*len(purchase_receipts)), + return frappe.db.sql("""SELECT SUM(net_total) FROM `tabPurchase Receipt` + WHERE name in (%s)""" % ', '.join(['%s']*len(purchase_receipts)), tuple(purchase_receipts))[0][0] - + def cancel_pr(self, purchase_receipts): for pr in purchase_receipts: pr_doc = frappe.get_doc("Purchase Receipt", pr) - + pr_doc.run_method("update_ordered_qty") - - frappe.db.sql("""delete from `tabStock Ledger Entry` + + frappe.db.sql("""delete from `tabStock Ledger Entry` where voucher_type='Purchase Receipt' and voucher_no=%s""", pr) - frappe.db.sql("""delete from `tabGL Entry` where voucher_type='Purchase Receipt' + frappe.db.sql("""delete from `tabGL Entry` where voucher_type='Purchase Receipt' and voucher_no=%s""", pr) - + def submit_pr(self, purchase_receipts): for pr in purchase_receipts: pr_doc = frappe.get_doc("Purchase Receipt", pr) pr_doc.run_method("update_ordered_qty") pr_doc.run_method("update_stock") - pr_doc.run_method("make_gl_entries") \ No newline at end of file + pr_doc.run_method("make_gl_entries") diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index 156751e89c..db97611918 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -114,7 +114,7 @@ class MaterialRequest(BuyingController): self.check_modified_date() self.update_bin(is_submit = (status == 'Submitted') and 1 or 0, is_stopped = 1) frappe.db.set(self, 'status', cstr(status)) - msgprint(self.doctype + ": " + self.name + " has been %s." % ((status == 'Submitted') and 'Unstopped' or cstr(status))) + frappe.msgprint(_("Status updated to {0}").format(_(status))) def on_cancel(self): # Step 1:=> Get Purchase Common Obj diff --git a/erpnext/stock/doctype/packing_slip/packing_slip.py b/erpnext/stock/doctype/packing_slip/packing_slip.py index b4b64cd648..e1a8f44a9d 100644 --- a/erpnext/stock/doctype/packing_slip/packing_slip.py +++ b/erpnext/stock/doctype/packing_slip/packing_slip.py @@ -4,7 +4,7 @@ from __future__ import unicode_literals import frappe from frappe.utils import flt, cint -from frappe import msgprint, _ +from frappe import _ from frappe.model.document import Document @@ -32,12 +32,12 @@ class PackingSlip(Document): Validates if delivery note has status as draft """ if cint(frappe.db.get_value("Delivery Note", self.delivery_note, "docstatus")) != 0: - msgprint(_("""Invalid Delivery Note. Delivery Note should exist and should be in draft state. Please rectify and try again."""), raise_exception=1) - + frappe.throw(_("Delivery Note {0} must not be submitted").format(self.delivery_note)) + def validate_items_mandatory(self): rows = [d.item_code for d in self.get("item_details")] if not rows: - frappe.msgprint(_("No Items to Pack"), raise_exception=1) + frappe.msgprint(_("No Items to pack"), raise_exception=1) def validate_case_nos(self): """ @@ -50,8 +50,8 @@ class PackingSlip(Document): elif self.from_case_no > self.to_case_no: frappe.msgprint(_("'To Case No.' cannot be less than 'From Case No.'"), raise_exception=1) - - + + res = frappe.db.sql("""SELECT name FROM `tabPacking Slip` WHERE delivery_note = %(delivery_note)s AND docstatus = 1 AND (from_case_no BETWEEN %(from_case_no)s AND %(to_case_no)s @@ -60,9 +60,7 @@ class PackingSlip(Document): """, self.as_dict()) if res: - frappe.msgprint(_("""Case No(s) already in use. Please rectify and try again. - Recommended From Case No. = %s""") % self.get_recommended_case_no(), - raise_exception=1) + frappe.throw(_("""Case No(s) already in use. Try from Case No {0}""").format(self.get_recommended_case_no())) def validate_qty(self): """ @@ -85,13 +83,13 @@ class PackingSlip(Document): * Item Quantity dict of current packing slip doc * No. of Cases of this packing slip """ - + rows = [d.item_code for d in self.get("item_details")] - + condition = "" if rows: condition = " and item_code in (%s)" % (", ".join(["%s"]*len(rows))) - + # gets item code, qty per item code, latest packed qty per item code and stock uom res = frappe.db.sql("""select item_code, ifnull(sum(qty), 0) as qty, (select sum(ifnull(psi.qty, 0) * (abs(ps.to_case_no - ps.from_case_no) + 1)) @@ -100,7 +98,7 @@ class PackingSlip(Document): and ps.delivery_note = dni.parent and psi.item_code=dni.item_code) as packed_qty, stock_uom, item_name from `tabDelivery Note Item` dni - where parent=%s %s + where parent=%s %s group by item_code""" % ("%s", condition), tuple([self.delivery_note] + rows), as_dict=1) @@ -117,12 +115,8 @@ class PackingSlip(Document): item['recommended_qty'] = (flt(item['qty']) - flt(item['packed_qty'])) / no_of_cases item['specified_qty'] = flt(ps_item_qty[item['item_code']]) if not item['packed_qty']: item['packed_qty'] = 0 - - frappe.msgprint(""" - Invalid Quantity specified (%(specified_qty)s %(stock_uom)s). - %(packed_qty)s out of %(qty)s %(stock_uom)s already packed for %(item_code)s. - Recommended quantity for %(item_code)s = %(recommended_qty)s - %(stock_uom)s""" % item, raise_exception=1) + + frappe.throw(_("Quantity for Item {0} must be less than {1}").format(item.get("item_code"), item.get("recommended_qty"))) def update_item_details(self): """ @@ -132,9 +126,9 @@ class PackingSlip(Document): self.from_case_no = self.get_recommended_case_no() for d in self.get("item_details"): - res = frappe.db.get_value("Item", d.item_code, + res = frappe.db.get_value("Item", d.item_code, ["net_weight", "weight_uom"], as_dict=True) - + if res and len(res)>0: d.net_weight = res["net_weight"] d.weight_uom = res["weight_uom"] @@ -146,12 +140,12 @@ class PackingSlip(Document): """ recommended_case_no = frappe.db.sql("""SELECT MAX(to_case_no) FROM `tabPacking Slip` WHERE delivery_note = %(delivery_note)s AND docstatus=1""", self.as_dict()) - + return cint(recommended_case_no[0][0]) + 1 - + def get_items(self): self.set("item_details", []) - + dn_details = self.get_details_for_packing()[0] for item in dn_details: if flt(item.qty) > flt(item.packed_qty): @@ -164,11 +158,11 @@ class PackingSlip(Document): def item_details(doctype, txt, searchfield, start, page_len, filters): from erpnext.controllers.queries import get_match_cond - return frappe.db.sql("""select name, item_name, description from `tabItem` - where name in ( select item_code FROM `tabDelivery Note Item` - where parent= %s - and ifnull(qty, 0) > ifnull(packed_qty, 0)) - and %s like "%s" %s - limit %s, %s """ % ("%s", searchfield, "%s", - get_match_cond(doctype), "%s", "%s"), - (filters["delivery_note"], "%%%s%%" % txt, start, page_len)) \ No newline at end of file + return frappe.db.sql("""select name, item_name, description from `tabItem` + where name in ( select item_code FROM `tabDelivery Note Item` + where parent= %s + and ifnull(qty, 0) > ifnull(packed_qty, 0)) + and %s like "%s" %s + limit %s, %s """ % ("%s", searchfield, "%s", + get_match_cond(doctype), "%s", "%s"), + (filters["delivery_note"], "%%%s%%" % txt, start, page_len)) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index 7626112f52..fa3571fe8e 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -6,7 +6,7 @@ import frappe from frappe.utils import cstr, flt, cint -from frappe import msgprint, _ +from frappe import _ import frappe.defaults from erpnext.stock.utils import update_bin @@ -86,21 +86,18 @@ class PurchaseReceipt(BuyingController): # Check Received Qty = Accepted Qty + Rejected Qty if ((flt(d.qty) + flt(d.rejected_qty)) != flt(d.received_qty)): - - msgprint("Sum of Accepted Qty and Rejected Qty must be equal to Received quantity. Error for Item: " + cstr(d.item_code)) - raise Exception + frappe.throw(_("Accepted + Rejected Qty must be equal to Received quantity for Item {0}").format(d.item_code)) def validate_challan_no(self): "Validate if same challan no exists for same supplier in a submitted purchase receipt" if self.challan_no: - exists = frappe.db.sql(""" + exists = frappe.db.sql_list(""" SELECT name FROM `tabPurchase Receipt` WHERE name!=%s AND supplier=%s AND challan_no=%s AND docstatus=1""", (self.name, self.supplier, self.challan_no)) if exists: - frappe.msgprint("Another Purchase Receipt using the same Challan No. already exists.\ - Please enter a valid Challan No.", raise_exception=1) + frappe.throw(_("Supplier delivery number duplicate in {0}").format(exists)) def validate_with_previous_doc(self): super(PurchaseReceipt, self).validate_with_previous_doc(self.tname, { @@ -129,8 +126,7 @@ class PurchaseReceipt(BuyingController): if frappe.db.get_value("Buying Settings", None, "po_required") == 'Yes': for d in self.get('purchase_receipt_details'): if not d.prevdoc_docname: - msgprint("Purchse Order No. required against item %s"%d.item_code) - raise Exception + frappe.throw(_("Purchase Order number required for Item {0}").format(d.item_code)) def update_stock(self): sl_entries = [] @@ -212,7 +208,7 @@ class PurchaseReceipt(BuyingController): (d.item_code,), as_dict = 1) ins_reqd = ins_reqd and ins_reqd[0]['inspection_required'] or 'No' if ins_reqd == 'Yes' and not d.qa_no: - msgprint("Item: " + d.item_code + " requires QA Inspection. Please enter QA No or report to authorized person to create Quality Inspection") + frappe.throw(_("Quality Inspection required for Item {0}").format(d.item_code)) # Check for Stopped status def check_for_stopped_status(self, pc_obj): @@ -251,9 +247,7 @@ class PurchaseReceipt(BuyingController): where t1.name = t2.parent and t2.purchase_receipt = %s and t1.docstatus = 1""", (self.name)) if submit_rv: - msgprint("Purchase Invoice : " + cstr(self.submit_rv[0][0]) + " has already been submitted !") - raise Exception , "Validation Error." - + frappe.throw(_("Purchase Invoice {0} is already submitted").format(self.submit_rv[0][0])) def on_cancel(self): pc_obj = frappe.get_doc('Purchase Common') diff --git a/erpnext/stock/doctype/serial_no/serial_no.py b/erpnext/stock/doctype/serial_no/serial_no.py index 90786550a4..37838ec51a 100644 --- a/erpnext/stock/doctype/serial_no/serial_no.py +++ b/erpnext/stock/doctype/serial_no/serial_no.py @@ -29,7 +29,7 @@ class SerialNo(StockController): if self.get("__islocal") and self.warehouse: frappe.throw(_("New Serial No cannot have Warehouse. Warehouse must be \ set by Stock Entry or Purchase Receipt"), SerialNoCannotCreateDirectError) - + self.set_maintenance_status() self.validate_warehouse() self.validate_item() @@ -38,28 +38,28 @@ class SerialNo(StockController): def set_maintenance_status(self): if not self.warranty_expiry_date and not self.amc_expiry_date: self.maintenance_status = None - + if self.warranty_expiry_date and self.warranty_expiry_date < nowdate(): self.maintenance_status = "Out of Warranty" - + if self.amc_expiry_date and self.amc_expiry_date < nowdate(): self.maintenance_status = "Out of AMC" - + if self.amc_expiry_date and self.amc_expiry_date >= nowdate(): self.maintenance_status = "Under AMC" - + if self.warranty_expiry_date and self.warranty_expiry_date >= nowdate(): self.maintenance_status = "Under Warranty" def validate_warehouse(self): if not self.get("__islocal"): - item_code, warehouse = frappe.db.get_value("Serial No", + item_code, warehouse = frappe.db.get_value("Serial No", self.name, ["item_code", "warehouse"]) if item_code != self.item_code: - frappe.throw(_("Item Code cannot be changed for Serial No."), + frappe.throw(_("Item Code cannot be changed for Serial No."), SerialNoCannotCannotChangeError) if not self.via_stock_ledger and warehouse != self.warehouse: - frappe.throw(_("Warehouse cannot be changed for Serial No."), + frappe.throw(_("Warehouse cannot be changed for Serial No."), SerialNoCannotCannotChangeError) def validate_item(self): @@ -69,17 +69,17 @@ class SerialNo(StockController): item = frappe.get_doc("Item", self.item_code) if item.has_serial_no!="Yes": frappe.throw(_("Item must have 'Has Serial No' as 'Yes'") + ": " + self.item_code) - + self.item_group = item.item_group self.description = item.description self.item_name = item.item_name self.brand = item.brand self.warranty_period = item.warranty_period - + def set_status(self, last_sle): if last_sle: if last_sle.voucher_type == "Stock Entry": - document_type = frappe.db.get_value("Stock Entry", last_sle.voucher_no, + document_type = frappe.db.get_value("Stock Entry", last_sle.voucher_no, "purpose") else: document_type = last_sle.voucher_type @@ -98,7 +98,7 @@ class SerialNo(StockController): self.status = "Not Available" else: self.status = "Not Available" - + def set_purchase_details(self, purchase_sle): if purchase_sle: self.purchase_document_type = purchase_sle.voucher_type @@ -108,13 +108,13 @@ class SerialNo(StockController): self.purchase_rate = purchase_sle.incoming_rate if purchase_sle.voucher_type == "Purchase Receipt": self.supplier, self.supplier_name = \ - frappe.db.get_value("Purchase Receipt", purchase_sle.voucher_no, + frappe.db.get_value("Purchase Receipt", purchase_sle.voucher_no, ["supplier", "supplier_name"]) else: - for fieldname in ("purchase_document_type", "purchase_document_no", + for fieldname in ("purchase_document_type", "purchase_document_no", "purchase_date", "purchase_time", "purchase_rate", "supplier", "supplier_name"): self.set(fieldname, None) - + def set_sales_details(self, delivery_sle): if delivery_sle: self.delivery_document_type = delivery_sle.voucher_type @@ -122,70 +122,70 @@ class SerialNo(StockController): self.delivery_date = delivery_sle.posting_date self.delivery_time = delivery_sle.posting_time self.customer, self.customer_name = \ - frappe.db.get_value(delivery_sle.voucher_type, delivery_sle.voucher_no, + frappe.db.get_value(delivery_sle.voucher_type, delivery_sle.voucher_no, ["customer", "customer_name"]) if self.warranty_period: - self.warranty_expiry_date = add_days(cstr(delivery_sle.posting_date), + self.warranty_expiry_date = add_days(cstr(delivery_sle.posting_date), cint(self.warranty_period)) else: - for fieldname in ("delivery_document_type", "delivery_document_no", - "delivery_date", "delivery_time", "customer", "customer_name", + for fieldname in ("delivery_document_type", "delivery_document_no", + "delivery_date", "delivery_time", "customer", "customer_name", "warranty_expiry_date"): self.set(fieldname, None) - + def get_last_sle(self): entries = {} sle_dict = self.get_stock_ledger_entries() if sle_dict: if sle_dict.get("incoming", []): entries["purchase_sle"] = sle_dict["incoming"][0] - + if len(sle_dict.get("incoming", [])) - len(sle_dict.get("outgoing", [])) > 0: entries["last_sle"] = sle_dict["incoming"][0] else: entries["last_sle"] = sle_dict["outgoing"][0] entries["delivery_sle"] = sle_dict["outgoing"][0] - + return entries - + def get_stock_ledger_entries(self): sle_dict = {} - for sle in frappe.db.sql("""select * from `tabStock Ledger Entry` - where serial_no like %s and item_code=%s and ifnull(is_cancelled, 'No')='No' - order by posting_date desc, posting_time desc, name desc""", + for sle in frappe.db.sql("""select * from `tabStock Ledger Entry` + where serial_no like %s and item_code=%s and ifnull(is_cancelled, 'No')='No' + order by posting_date desc, posting_time desc, name desc""", ("%%%s%%" % self.name, self.item_code), as_dict=1): if self.name.upper() in get_serial_nos(sle.serial_no): if sle.actual_qty > 0: sle_dict.setdefault("incoming", []).append(sle) else: sle_dict.setdefault("outgoing", []).append(sle) - + return sle_dict - + def on_trash(self): if self.status == 'Delivered': frappe.throw(_("Delivered Serial No ") + self.name + _(" can not be deleted")) if self.warehouse: frappe.throw(_("Cannot delete Serial No in warehouse. \ First remove from warehouse, then delete.") + ": " + self.name) - + def before_rename(self, old, new, merge=False): if merge: frappe.throw(_("Sorry, Serial Nos cannot be merged")) - + def after_rename(self, old, new, merge=False): """rename serial_no text fields""" - for dt in frappe.db.sql("""select parent from tabDocField + for dt in frappe.db.sql("""select parent from tabDocField where fieldname='serial_no' and fieldtype='Text'"""): - - for item in frappe.db.sql("""select name, serial_no from `tab%s` + + for item in frappe.db.sql("""select name, serial_no from `tab%s` where serial_no like '%%%s%%'""" % (dt[0], old)): - + serial_nos = map(lambda i: i==old and new or i, item[1].split('\n')) - frappe.db.sql("""update `tab%s` set serial_no = %s + frappe.db.sql("""update `tab%s` set serial_no = %s where name=%s""" % (dt[0], '%s', '%s'), ('\n'.join(serial_nos), item[0])) - + def on_stock_ledger_entry(self): if self.via_stock_ledger and not self.get("__islocal"): last_sle = self.get_last_sle() @@ -193,7 +193,7 @@ class SerialNo(StockController): self.set_purchase_details(last_sle.get("purchase_sle")) self.set_sales_details(last_sle.get("delivery_sle")) self.set_maintenance_status() - + def on_communication(self): return @@ -201,11 +201,11 @@ def process_serial_no(sle): item_det = get_item_details(sle.item_code) validate_serial_no(sle, item_det) update_serial_nos(sle, item_det) - + def validate_serial_no(sle, item_det): if item_det.has_serial_no=="No": if sle.serial_no: - frappe.throw(_("Serial Number should be blank for Non Serialized Item" + ": " + frappe.throw(_("Serial Number should be blank for Non Serialized Item" + ": " + sle.item_code), SerialNoNotRequiredError) else: if sle.serial_no: @@ -216,41 +216,41 @@ def validate_serial_no(sle, item_det): if len(serial_nos) and len(serial_nos) != abs(cint(sle.actual_qty)): frappe.throw(_("Serial Nos do not match with qty") + \ (": %s (%s)" % (sle.item_code, sle.actual_qty)), SerialNoQtyError) - + if len(serial_nos) != len(set(serial_nos)): - frappe.throw(_("Duplicate Serial No entered against item") + + frappe.throw(_("Duplicate Serial No entered against item") + (": %s" % sle.item_code), SerialNoDuplicateError) - + for serial_no in serial_nos: if frappe.db.exists("Serial No", serial_no): sr = frappe.get_doc("Serial No", serial_no) - + if sr.item_code!=sle.item_code: - frappe.throw(_("Serial No does not belong to Item") + + frappe.throw(_("Serial No does not belong to Item") + (": %s (%s)" % (sle.item_code, serial_no)), SerialNoItemError) - + if sr.warehouse and sle.actual_qty > 0: - frappe.throw(_("Same Serial No") + ": " + sr.name + + frappe.throw(_("Same Serial No") + ": " + sr.name + _(" can not be received twice"), SerialNoDuplicateError) - + if sle.actual_qty < 0: if sr.warehouse!=sle.warehouse: - frappe.throw(_("Serial No") + ": " + serial_no + - _(" does not belong to Warehouse") + ": " + sle.warehouse, + frappe.throw(_("Serial No") + ": " + serial_no + + _(" does not belong to Warehouse") + ": " + sle.warehouse, SerialNoWarehouseError) - + if sle.voucher_type in ("Delivery Note", "Sales Invoice") \ and sr.status != "Available": - frappe.throw(_("Serial No status must be 'Available' to Deliver") + frappe.throw(_("Serial No status must be 'Available' to Deliver") + ": " + serial_no, SerialNoStatusError) elif sle.actual_qty < 0: # transfer out frappe.throw(_("Serial No must exist to transfer out.") + \ ": " + serial_no, SerialNoNotExistsError) elif sle.actual_qty < 0 or not item_det.serial_no_series: - frappe.throw(_("Serial Number Required for Serialized Item" + ": " + frappe.throw(_("Serial Number Required for Serialized Item" + ": " + sle.item_code), SerialNoRequiredError) - + def update_serial_nos(sle, item_det): if sle.is_cancelled == "No" and not sle.serial_no and sle.actual_qty > 0 and item_det.serial_no_series: from frappe.model.naming import make_autoname @@ -258,7 +258,7 @@ def update_serial_nos(sle, item_det): for i in xrange(cint(sle.actual_qty)): serial_nos.append(make_autoname(item_det.serial_no_series)) frappe.db.set(sle, "serial_no", "\n".join(serial_nos)) - + if sle.serial_no: serial_nos = get_serial_nos(sle.serial_no) for serial_no in serial_nos: @@ -271,12 +271,12 @@ def update_serial_nos(sle, item_det): make_serial_no(serial_no, sle) def get_item_details(item_code): - return frappe.db.sql("""select name, has_batch_no, docstatus, - is_stock_item, has_serial_no, serial_no_series + return frappe.db.sql("""select name, has_batch_no, docstatus, + is_stock_item, has_serial_no, serial_no_series from tabItem where name=%s""", item_code, as_dict=True)[0] - + def get_serial_nos(serial_no): - return [s.strip() for s in cstr(serial_no).strip().upper().replace(',', '\n').split('\n') + return [s.strip() for s in cstr(serial_no).strip().upper().replace(',', '\n').split('\n') if s.strip()] def make_serial_no(serial_no, sle): @@ -290,14 +290,14 @@ def make_serial_no(serial_no, sle): sr.warehouse = sle.warehouse sr.status = "Available" sr.save() - frappe.msgprint(_("Serial No created") + ": " + sr.name) + frappe.msgprint(_("Serial No {0} created").format(sr.name)) return sr.name - + def update_serial_nos_after_submit(controller, parentfield): stock_ledger_entries = frappe.db.sql("""select voucher_detail_no, serial_no - from `tabStock Ledger Entry` where voucher_type=%s and voucher_no=%s""", + from `tabStock Ledger Entry` where voucher_type=%s and voucher_no=%s""", (controller.doctype, controller.name), as_dict=True) - + if not stock_ledger_entries: return for d in controller.get(parentfield): diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index cb130b2e3e..dfa2c62b9d 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -7,7 +7,7 @@ import frappe.defaults from frappe.utils import cstr, cint, flt, comma_or, nowdate -from frappe import msgprint, _ +from frappe import _ from erpnext.stock.utils import get_incoming_rate from erpnext.stock.stock_ledger import get_previous_sle from erpnext.controllers.queries import get_match_cond @@ -67,15 +67,13 @@ class StockEntry(StockController): valid_purposes = ["Material Issue", "Material Receipt", "Material Transfer", "Manufacture/Repack", "Subcontract", "Sales Return", "Purchase Return"] if self.purpose not in valid_purposes: - msgprint(_("Purpose must be one of ") + comma_or(valid_purposes), - raise_exception=True) + frappe.throw(_("Purpose must be one of {0}").format(comma_or(valid_purposes))) def validate_item(self): stock_items = self.get_stock_items() for item in self.get("mtn_details"): if item.item_code not in stock_items: - msgprint(_("""Only Stock Items are allowed for Stock Entry"""), - raise_exception=True) + frappe.throw(_("""Only Stock Items are allowed for Stock Entry""")) def validate_warehouse(self, pro_obj): """perform various (sometimes conditional) validations on warehouse""" @@ -100,15 +98,13 @@ class StockEntry(StockController): d.t_warehouse = self.to_warehouse if not (d.s_warehouse or d.t_warehouse): - msgprint(_("Atleast one warehouse is mandatory"), raise_exception=1) + frappe.throw(_("Atleast one warehouse is mandatory")) if self.purpose in source_mandatory and not d.s_warehouse: - msgprint(_("Row # ") + "%s: " % cint(d.idx) - + _("Source Warehouse") + _(" is mandatory"), raise_exception=1) + frappe.throw(_("Source warehouse is mandatory for row {0}").format(d.idx)) if self.purpose in target_mandatory and not d.t_warehouse: - msgprint(_("Row # ") + "%s: " % cint(d.idx) - + _("Target Warehouse") + _(" is mandatory"), raise_exception=1) + frappe.throw(_("Target warehouse is mandatory for row {0}").format(d.idx)) if self.purpose == "Manufacture/Repack": if validate_for_manufacture_repack: @@ -116,23 +112,18 @@ class StockEntry(StockController): d.s_warehouse = None if not d.t_warehouse: - msgprint(_("Row # ") + "%s: " % cint(d.idx) - + _("Target Warehouse") + _(" is mandatory"), raise_exception=1) + frappe.throw(_("Target warehouse is mandatory for row {0}").format(d.idx)) elif pro_obj and cstr(d.t_warehouse) != pro_obj.fg_warehouse: - msgprint(_("Row # ") + "%s: " % cint(d.idx) - + _("Target Warehouse") + _(" should be same as that in ") - + _("Production Order"), raise_exception=1) + frappe.throw(_("Target warehouse in row {0} must be same as Production Order").format(d.idx)) else: d.t_warehouse = None if not d.s_warehouse: - msgprint(_("Row # ") + "%s: " % cint(d.idx) - + _("Source Warehouse") + _(" is mandatory"), raise_exception=1) + frappe.throw(_("Source warehouse is mandatory for row {0}").format(d.idx)) if cstr(d.s_warehouse) == cstr(d.t_warehouse): - msgprint(_("Source and Target Warehouse cannot be same"), - raise_exception=1) + frappe.throw(_("Source and target warehouse cannot be same for row {0}").format(d.idx)) def validate_production_order(self, pro_obj=None): if not pro_obj: @@ -228,17 +219,13 @@ class StockEntry(StockController): if d.bom_no and not frappe.db.sql("""select name from `tabBOM` where item = %s and name = %s and docstatus = 1 and is_active = 1""", (d.item_code, d.bom_no)): - msgprint(_("Item") + " %s: " % cstr(d.item_code) - + _("does not belong to BOM: ") + cstr(d.bom_no) - + _(" or the BOM is cancelled or inactive"), raise_exception=1) + frappe.throw(_("BOM {0} is not submitted or inactive BOM for Item {1}").format(d.bom_no, d.item_code)) def validate_finished_goods(self): """validation: finished good quantity should be same as manufacturing quantity""" - import json for d in self.get('mtn_details'): if d.bom_no and flt(d.transfer_qty) != flt(self.fg_completed_qty): - msgprint(_("Row #") + " %s: " % d.idx - + _("Quantity should be equal to Manufacturing Quantity. To fetch items again, click on 'Get Items' button or update the Quantity manually."), raise_exception=1) + frappe.throw(_("Quantity in row {0} must be same as manufactured quantity").format(d.idx)) def validate_return_reference_doc(self): """validate item with reference doc""" @@ -247,14 +234,12 @@ class StockEntry(StockController): if ref.doc: # validate docstatus if ref.doc.docstatus != 1: - frappe.msgprint(_(ref.doc.doctype) + ' "' + ref.doc.name + '": ' - + _("Status should be Submitted"), raise_exception=frappe.InvalidStatusError) + frappe.throw(_("{0} {1} must be submitted").format(ref.doc.doctype, ref.doc.name), + frappe.InvalidStatusError) # update stock check if ref.doc.doctype == "Sales Invoice" and cint(ref.doc.update_stock) != 1: - frappe.msgprint(_(ref.doc.doctype) + ' "' + ref.doc.name + '": ' - + _("Update Stock should be checked."), - raise_exception=NotUpdateStockError) + frappe.throw(_("'Update Stock' for Sales Invoice {0} must be set").format(ref.doc.name), NotUpdateStockError) # posting date check ref_posting_datetime = "%s %s" % (cstr(ref.doc.posting_date), @@ -263,9 +248,7 @@ class StockEntry(StockController): cstr(self.posting_time)) if this_posting_datetime < ref_posting_datetime: from frappe.utils.dateutils import datetime_in_user_format - frappe.msgprint(_("Posting Date Time cannot be before") - + ": " + datetime_in_user_format(ref_posting_datetime), - raise_exception=True) + frappe.throw(_("Posting timestamp must be after {0}").format(datetime_in_user_format(ref_posting_datetime))) stock_items = get_stock_items_for_return(ref.doc, ref.parentfields) already_returned_item_qty = self.get_already_returned_item_qty(ref.fieldname) @@ -273,9 +256,8 @@ class StockEntry(StockController): for item in self.get("mtn_details"): # validate if item exists in the ref doc and that it is a stock item if item.item_code not in stock_items: - msgprint(_("Item") + ': "' + item.item_code + _("\" does not exist in ") + - ref.doc.doctype + ": " + ref.doc.name, - raise_exception=frappe.DoesNotExistError) + frappe.throw(_("Item {0} does not exist in {1} {2}").format(item.item_code, ref.doc.doctype, ref.doc.name), + frappe.DoesNotExistError) # validate quantity <= ref item's qty - qty already returned ref_item = ref.doc.getone({"item_code": item.item_code}) @@ -328,12 +310,10 @@ class StockEntry(StockController): def update_production_order(self): def _validate_production_order(pro_doc): if flt(pro_doc.docstatus) != 1: - frappe.throw(_("Production Order must be submitted") + ": " + - self.production_order) + frappe.throw(_("Production Order {0} must be submitted").format(self.production_order)) if pro_doc.status == 'Stopped': - msgprint(_("Transaction not allowed against stopped Production Order") + ": " + - self.production_order) + frappe.throw(_("Transaction not allowed against stopped Production Order {0}").format(self.production_order)) if self.production_order: pro_doc = frappe.get_doc("Production Order", self.production_order) @@ -372,7 +352,7 @@ class StockEntry(StockController): where name = %s and (ifnull(end_of_life,'')='' or end_of_life > now())""", (arg.get('item_code')), as_dict = 1) if not item: - msgprint("Item is not active", raise_exception=1) + frappe.throw(_("Item {0} is not active or end of life has been reached").format(arg.get("item_code"))) ret = { 'uom' : item and item[0]['stock_uom'] or '', @@ -398,8 +378,7 @@ class StockEntry(StockController): uom = frappe.db.sql("""select conversion_factor from `tabUOM Conversion Detail` where parent = %s and uom = %s""", (arg['item_code'], arg['uom']), as_dict = 1) if not uom or not flt(uom[0].conversion_factor): - msgprint("There is no Conversion Factor for UOM '%s' in Item '%s'" % (arg['uom'], - arg['item_code'])) + frappe.msgprint(_("UOM coversion factor required for UOM {0} in Item {1}").format(arg["uom"], arg["item_code"])) ret = {'uom' : ''} else: ret = { @@ -531,12 +510,10 @@ class StockEntry(StockController): # show some message if not len(item_dict): - frappe.msgprint(_("""All items have already been transferred \ - for this Production Order.""")) + frappe.msgprint(_("""All items have already been transferred for this Production Order.""")) elif only_pending_fetched: - frappe.msgprint(_("""Only quantities pending to be transferred \ - were fetched for the following items:\n""" + "\n".join(only_pending_fetched))) + frappe.msgprint(_("Pending Items {0} updated").format(only_pending_fetched)) return item_dict @@ -589,10 +566,8 @@ class StockEntry(StockController): {"name": item.material_request_item, "parent": item.material_request}, ["item_code", "warehouse", "idx"], as_dict=True) if mreq_item.item_code != item.item_code or mreq_item.warehouse != item.t_warehouse: - msgprint(_("Row #") + (" %d: " % item.idx) + _("does not match") - + " " + _("Row #") + (" %d %s " % (mreq_item.idx, _("of"))) - + _("Material Request") + (" - %s" % item.material_request), - raise_exception=frappe.MappingMismatchError) + frappe.throw(_("Item or Warehouse for row {0} does not match Material Request").format(item.idx), + frappe.MappingMismatchError) @frappe.whitelist() def get_party_details(ref_dt, ref_dn): diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index 34558fbbc4..3717bf1595 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals import frappe -from frappe import msgprint +from frappe import _ from frappe.utils import cint, flt, cstr, now from erpnext.stock.utils import get_valuation_method import json @@ -309,17 +309,11 @@ def get_fifo_values(qty_after_transaction, sle, stock_queue): def _raise_exceptions(args, verbose=1): deficiency = min(e["diff"] for e in _exceptions) - msg = """Negative stock error: - Cannot complete this transaction because stock will start - becoming negative (%s) for Item %s in Warehouse - %s on %s %s in Transaction %s %s. - Total Quantity Deficiency: %s""" % \ - (_exceptions[0]["diff"], args.get("item_code"), args.get("warehouse"), - _exceptions[0]["posting_date"], _exceptions[0]["posting_time"], - _exceptions[0]["voucher_type"], _exceptions[0]["voucher_no"], - abs(deficiency)) + msg = _("Negative Stock Error ({6}) for Item {0} in Warehouse {1} on {2} {3} in {4} {5}").format(args["item_code"], + args.get("warehouse"), _exceptions[0]["posting_date"], _exceptions[0]["posting_time"], + _(_exceptions[0]["voucher_type"]), _exceptions[0]["voucher_no"], deficiency) if verbose: - msgprint(msg, raise_exception=NegativeStockError) + frappe.throw(msg, NegativeStockError) else: raise NegativeStockError, msg diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py index bce94f389d..1c5458e6b5 100644 --- a/erpnext/stock/utils.py +++ b/erpnext/stock/utils.py @@ -2,7 +2,7 @@ # License: GNU General Public License v3. See license.txt import frappe -from frappe import msgprint, _ +from frappe import _ import json from frappe.utils import flt, cstr, nowdate, add_days, cint from frappe.defaults import get_global_default @@ -58,8 +58,7 @@ def update_bin(args): bin.update_stock(args) return bin else: - msgprint("[Stock Update] Ignored %s since it is not a stock item" - % args.get("item_code")) + frappe.msgprint(_("Item {0} ignored since it is not a stock item").format(args.get("item_code"))) def get_incoming_rate(args): """Get Incoming Rate based on valuation method""" @@ -134,22 +133,20 @@ def get_valid_serial_nos(sr_nos, qty=0, item_code=''): if val: val = val.strip() if val in valid_serial_nos: - msgprint("You have entered duplicate serial no: '%s'" % val, raise_exception=1) + frappe.throw(_("Serial number {0} entered more than once").format(val)) else: valid_serial_nos.append(val) if qty and len(valid_serial_nos) != abs(qty): - msgprint("Please enter serial nos for " - + cstr(abs(qty)) + " quantity against item code: " + item_code, - raise_exception=1) + frappe.throw(_("{0} valid serial nos for Item {1}").format(abs(qty), item_code)) return valid_serial_nos def validate_warehouse_company(warehouse, company): warehouse_company = frappe.db.get_value("Warehouse", warehouse, "company") if warehouse_company and warehouse_company != company: - frappe.msgprint(_("Warehouse does not belong to company.") + " (" + \ - warehouse + ", " + company +")", raise_exception=InvalidWarehouseCompany) + frappe.throw(_("Warehouse {0} does not belong to company {1}").format(warehouse, company), + InvalidWarehouseCompany) def get_sales_bom_buying_amount(item_code, warehouse, voucher_type, voucher_no, voucher_detail_no, stock_ledger_entries, item_sales_bom):