fixed strings for translation

This commit is contained in:
Rushabh Mehta 2014-04-15 14:36:12 +05:30
parent 5d4ffa6cf8
commit 2c45899a02
20 changed files with 516 additions and 562 deletions

View File

@ -114,7 +114,7 @@ class JournalVoucher(AccountsController):
if self.cheque_no:
if self.cheque_date:
r.append(_('Reference #{0} dated {1}').format(self.cheque_no, formatdate(self.cheque_date)))
else :
else:
msgprint(_("Please enter Reference date"), raise_exception=1)
for d in self.get('entries'):

View File

@ -86,9 +86,7 @@ class Customer(TransactionBase):
def validate_name_with_customer_group(self):
if frappe.db.exists("Customer Group", self.name):
frappe.msgprint("An Customer Group exists with same name (%s), \
please change the Customer name or rename the Customer Group" %
self.name, raise_exception=1)
frappe.throw("A Customer Group exists with same name please change the Customer name or rename the Customer Group")
def delete_customer_address(self):
addresses = frappe.db.sql("""select name, lead from `tabAddress`
@ -140,7 +138,7 @@ class Customer(TransactionBase):
@frappe.whitelist()
def get_dashboard_info(customer):
if not frappe.has_permission("Customer", "read", customer):
frappe.msgprint("No Permission", raise_exception=True)
frappe.msgprint(_("Not permitted"), raise_exception=True)
out = {}
for doctype in ["Opportunity", "Quotation", "Sales Order", "Delivery Note", "Sales Invoice"]:

View File

@ -4,38 +4,33 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import add_days, cstr, flt, nowdate, cint, now
from frappe import session, msgprint
from erpnext.stock.utils import get_valid_serial_nos
from frappe.utils import flt, now
from frappe.model.document import Document
class StockLedger(Document):
def update_stock(self, values, is_amended = 'No'):
for v in values:
sle_id = ''
# reverse quantities for cancel
if v.get('is_cancelled') == 'Yes':
v['actual_qty'] = -flt(v['actual_qty'])
# cancel matching entry
frappe.db.sql("""update `tabStock Ledger Entry` set is_cancelled='Yes',
modified=%s, modified_by=%s
where voucher_no=%s and voucher_type=%s""",
where voucher_no=%s and voucher_type=%s""",
(now(), frappe.session.user, v['voucher_no'], v['voucher_type']))
if v.get("actual_qty"):
sle_id = self.make_entry(v)
args = v.copy()
args.update({
"sle_id": sle_id,
"is_amended": is_amended
})
frappe.get_doc('Warehouse', v["warehouse"]).update_bin(args)
@ -45,7 +40,7 @@ class StockLedger(Document):
sle.ignore_permissions = 1
sle.insert()
return sle.name
def repost(self):
"""
Repost everything!

View File

@ -4,15 +4,14 @@
from __future__ import unicode_literals
import frappe
from frappe import msgprint
from frappe.utils import flt, getdate, add_days
from frappe import _
from frappe.utils import flt, getdate, add_days, formatdate
from frappe.model.controller import DocListController
from datetime import date
class StockFreezeError(frappe.ValidationError): pass
class StockLedgerEntry(DocListController):
def validate(self):
from erpnext.stock.utils import validate_warehouse_company
self.validate_mandatory()
@ -55,11 +54,7 @@ class StockLedgerEntry(DocListController):
mandatory = ['warehouse','posting_date','voucher_type','voucher_no','actual_qty','company']
for k in mandatory:
if not self.get(k):
msgprint("Stock Ledger Entry: '%s' is mandatory" % k, raise_exception = 1)
elif k == 'warehouse':
if not frappe.db.exists("Warehouse", self.get(k)):
msgprint("Warehouse: '%s' does not exist in the system. Please check." %
self.get(k), raise_exception = 1)
frappe.throw(_("{0} is required").format(k))
def validate_item(self):
item_det = frappe.db.sql("""select name, has_batch_no, docstatus,
@ -89,15 +84,14 @@ class StockLedgerEntry(DocListController):
if stock_frozen_upto:
stock_auth_role = frappe.db.get_value('Stock Settings', None,'stock_auth_role')
if getdate(self.posting_date) <= getdate(stock_frozen_upto) and not stock_auth_role in frappe.user.get_roles():
msgprint("You are not authorized to do / modify back dated stock entries before %s" % getdate(stock_frozen_upto).strftime('%d-%m-%Y'), raise_exception=StockFreezeError)
frappe.throw(_("Entries before {0} are frozen").format(formatdate(stock_frozen_upto)), StockFreezeError)
stock_frozen_upto_days = int(frappe.db.get_value('Stock Settings', None, 'stock_frozen_upto_days') or 0)
if stock_frozen_upto_days:
stock_auth_role = frappe.db.get_value('Stock Settings', None,'stock_auth_role')
older_than_x_days_ago = (add_days(getdate(self.posting_date), stock_frozen_upto_days) <= date.today())
if older_than_x_days_ago and not stock_auth_role in frappe.user.get_roles():
msgprint("You are not authorized to do / modify back dated stock entries older than %d days ago" %stock_frozen_upto_days, raise_exception=StockFreezeError)
frappe.throw(_("Not allowed to update entries older than {0}").format(stock_frozen_upto_days), StockFreezeError)
def scrub_posting_time(self):
if not self.posting_time or self.posting_time == '00:0':

View File

@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import cstr, flt, cint
from frappe import msgprint, _
from frappe import _
from frappe.model.document import Document
@ -12,71 +12,66 @@ from frappe.model.document import Document
class StockUOMReplaceUtility(Document):
def validate_mandatory(self):
if not cstr(self.item_code):
msgprint("Please Enter an Item.")
raise Exception
frappe.throw(_("Item is required"))
if not cstr(self.new_stock_uom):
msgprint("Please Enter New Stock UOM.")
raise Exception
frappe.throw(_("New Stock UOM is required"))
if cstr(self.current_stock_uom) == cstr(self.new_stock_uom):
msgprint("Current Stock UOM and Stock UOM are same.")
raise Exception
frappe.throw(_("New Stock UOM must be different from current stock UOM"))
# check conversion factor
if not flt(self.conversion_factor):
msgprint("Please Enter Conversion Factor.")
raise Exception
frappe.throw(_("Conversion Factor is required"))
stock_uom = frappe.db.get_value("Item", self.item_code, "stock_uom")
if cstr(self.new_stock_uom) == cstr(stock_uom):
msgprint("Item Master is already updated with New Stock UOM " + cstr(self.new_stock_uom))
raise Exception
frappe.throw(_("Item is updated"))
def update_item_master(self):
item_doc = frappe.get_doc("Item", self.item_code)
item_doc.stock_uom = self.new_stock_uom
item_doc.save()
msgprint(_("Default UOM updated in item ") + self.item_code)
frappe.msgprint(_("Stock UOM updatd for Item {0}").format(self.item_code))
def update_bin(self):
# update bin
if flt(self.conversion_factor) != flt(1):
frappe.db.sql("""update `tabBin`
set stock_uom = %s,
indented_qty = ifnull(indented_qty,0) * %s,
ordered_qty = ifnull(ordered_qty,0) * %s,
reserved_qty = ifnull(reserved_qty,0) * %s,
planned_qty = ifnull(planned_qty,0) * %s,
projected_qty = actual_qty + ordered_qty + indented_qty +
planned_qty - reserved_qty
where item_code = %s""", (self.new_stock_uom, self.conversion_factor,
self.conversion_factor, self.conversion_factor,
frappe.db.sql("""update `tabBin`
set stock_uom = %s,
indented_qty = ifnull(indented_qty,0) * %s,
ordered_qty = ifnull(ordered_qty,0) * %s,
reserved_qty = ifnull(reserved_qty,0) * %s,
planned_qty = ifnull(planned_qty,0) * %s,
projected_qty = actual_qty + ordered_qty + indented_qty +
planned_qty - reserved_qty
where item_code = %s""", (self.new_stock_uom, self.conversion_factor,
self.conversion_factor, self.conversion_factor,
self.conversion_factor, self.item_code))
else:
frappe.db.sql("update `tabBin` set stock_uom = %s where item_code = %s",
frappe.db.sql("update `tabBin` set stock_uom = %s where item_code = %s",
(self.new_stock_uom, self.item_code) )
# acknowledge user
msgprint(" All Bins Updated Successfully.")
frappe.msgprint(_("Stock balances updated"))
def update_stock_ledger_entry(self):
# update stock ledger entry
from erpnext.stock.stock_ledger import update_entries_after
if flt(self.conversion_factor) != flt(1):
frappe.db.sql("""update `tabStock Ledger Entry`
set stock_uom = %s, actual_qty = ifnull(actual_qty,0) * %s
where item_code = %s""",
frappe.db.sql("""update `tabStock Ledger Entry`
set stock_uom = %s, actual_qty = ifnull(actual_qty,0) * %s
where item_code = %s""",
(self.new_stock_uom, self.conversion_factor, self.item_code))
else:
frappe.db.sql("""update `tabStock Ledger Entry` set stock_uom=%s
frappe.db.sql("""update `tabStock Ledger Entry` set stock_uom=%s
where item_code=%s""", (self.new_stock_uom, self.item_code))
# acknowledge user
msgprint("Stock Ledger Entries Updated Successfully.")
frappe.msgprint(_("Stock Ledger entries balances updated"))
# update item valuation
if flt(self.conversion_factor) != flt(1):
wh = frappe.db.sql("select name from `tabWarehouse`")
@ -84,34 +79,31 @@ class StockUOMReplaceUtility(Document):
update_entries_after({"item_code": self.item_code, "warehouse": w[0]})
# acknowledge user
msgprint("Item Valuation Updated Successfully.")
frappe.msgprint(_("Item valuation updated"))
# Update Stock UOM
# Update Stock UOM
def update_stock_uom(self):
self.validate_mandatory()
self.validate_uom_integer_type()
self.update_stock_ledger_entry()
self.update_bin()
self.update_item_master()
def validate_uom_integer_type(self):
current_is_integer = frappe.db.get_value("UOM", self.current_stock_uom, "must_be_whole_number")
new_is_integer = frappe.db.get_value("UOM", self.new_stock_uom, "must_be_whole_number")
if current_is_integer and not new_is_integer:
frappe.msgprint("New UOM must be of type Whole Number", raise_exception=True)
if not current_is_integer and new_is_integer:
frappe.msgprint("New UOM must NOT be of type Whole Number", raise_exception=True)
frappe.throw(_("New UOM must NOT be of type Whole Number"))
if current_is_integer and new_is_integer and cint(self.conversion_factor)!=self.conversion_factor:
frappe.msgprint("Conversion Factor cannot be fraction", raise_exception=True)
frappe.throw(_("Conversion factor cannot be in fractions"))
@frappe.whitelist()
def get_stock_uom(item_code):
return { 'current_stock_uom': cstr(frappe.db.get_value('Item', item_code, 'stock_uom')) }

View File

@ -9,7 +9,7 @@ from frappe import throw, msgprint, _
from frappe.model.document import Document
class Warehouse(Document):
def autoname(self):
suffix = " - " + frappe.db.get_value("Company", self.company, "abbr")
if not self.warehouse_name.endswith(suffix):
@ -18,78 +18,78 @@ class Warehouse(Document):
def validate(self):
if self.email_id and not validate_email_add(self.email_id):
throw(_("Please enter valid Email Id"))
self.update_parent_account()
def update_parent_account(self):
if not getattr(self, "__islocal", None) and (self.create_account_under !=
if not getattr(self, "__islocal", None) and (self.create_account_under !=
frappe.db.get_value("Warehouse", self.name, "create_account_under")):
warehouse_account = frappe.db.get_value("Account",
{"account_type": "Warehouse", "company": self.company,
warehouse_account = frappe.db.get_value("Account",
{"account_type": "Warehouse", "company": self.company,
"master_name": self.name}, ["name", "parent_account"])
if warehouse_account and warehouse_account[1] != self.create_account_under:
acc_doc = frappe.get_doc("Account", warehouse_account[0])
acc_doc.parent_account = self.create_account_under
acc_doc.save()
def on_update(self):
self.create_account_head()
def create_account_head(self):
if cint(frappe.defaults.get_global_default("auto_accounting_for_stock")):
if not frappe.db.get_value("Account", {"account_type": "Warehouse",
"master_name": self.name}) and not frappe.db.get_value("Account",
if not frappe.db.get_value("Account", {"account_type": "Warehouse",
"master_name": self.name}) and not frappe.db.get_value("Account",
{"account_name": self.warehouse_name}):
if self.get("__islocal") or not frappe.db.get_value(
"Stock Ledger Entry", {"warehouse": self.name}):
self.validate_parent_account()
ac_doc = frappe.get_doc({
"doctype": "Account",
'account_name': self.warehouse_name,
'parent_account': self.create_account_under,
'group_or_ledger':'Ledger',
'company':self.company,
'account_name': self.warehouse_name,
'parent_account': self.create_account_under,
'group_or_ledger':'Ledger',
'company':self.company,
"account_type": "Warehouse",
"master_name": self.name,
"freeze_account": "No"
})
ac_doc.ignore_permissions = True
ac_doc.insert()
msgprint(_("Account Head") + ": " + ac_doc.name + _(" created"))
msgprint(_("Account head {0} created"))
def validate_parent_account(self):
if not self.create_account_under:
parent_account = frappe.db.get_value("Account",
parent_account = frappe.db.get_value("Account",
{"account_name": "Stock Assets", "company": self.company})
if parent_account:
self.create_account_under = parent_account
else:
frappe.throw(_("Please enter account group under which account \
for warehouse ") + self.name +_(" will be created"))
def on_trash(self):
# delete bin
bins = frappe.db.sql("select * from `tabBin` where warehouse = %s",
bins = frappe.db.sql("select * from `tabBin` where warehouse = %s",
self.name, as_dict=1)
for d in bins:
if d['actual_qty'] or d['reserved_qty'] or d['ordered_qty'] or \
d['indented_qty'] or d['projected_qty'] or d['planned_qty']:
throw("""Warehouse: %s can not be deleted as qty exists for item: %s"""
throw("""Warehouse: %s can not be deleted as qty exists for item: %s"""
% (self.name, d['item_code']))
else:
frappe.db.sql("delete from `tabBin` where name = %s", d['name'])
warehouse_account = frappe.db.get_value("Account",
warehouse_account = frappe.db.get_value("Account",
{"account_type": "Warehouse", "master_name": self.name})
if warehouse_account:
frappe.delete_doc("Account", warehouse_account)
if frappe.db.sql("""select name from `tabStock Ledger Entry`
if frappe.db.sql("""select name from `tabStock Ledger Entry`
where warehouse = %s""", self.name):
throw(_("""Warehouse can not be deleted as stock ledger entry
throw(_("""Warehouse can not be deleted as stock ledger entry
exists for this warehouse."""))
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
@ -98,12 +98,12 @@ class Warehouse(Document):
if merge:
if not frappe.db.exists("Warehouse", new_warehouse):
frappe.throw(_("Warehouse ") + new_warehouse +_(" does not exists"))
if self.company != frappe.db.get_value("Warehouse", new_warehouse, "company"):
frappe.throw(_("Both Warehouse must belong to same Company"))
frappe.db.sql("delete from `tabBin` where warehouse=%s", olddn)
from erpnext.accounts.utils import rename_account_for
rename_account_for("Warehouse", olddn, newdn, merge, self.company)
@ -112,18 +112,18 @@ class Warehouse(Document):
def after_rename(self, olddn, newdn, merge=False):
if merge:
self.recalculate_bin_qty(newdn)
def recalculate_bin_qty(self, newdn):
from erpnext.utilities.repost_stock import repost_stock
frappe.db.auto_commit_on_many_writes = 1
frappe.db.set_default("allow_negative_stock", 1)
for item in frappe.db.sql("""select distinct item_code from (
select name as item_code from `tabItem` where ifnull(is_stock_item, 'Yes')='Yes'
union
union
select distinct item_code from tabBin) a"""):
repost_stock(item[0], newdn)
frappe.db.set_default("allow_negative_stock",
frappe.db.set_default("allow_negative_stock",
frappe.db.get_value("Stock Settings", None, "allow_negative_stock"))
frappe.db.auto_commit_on_many_writes = 0
frappe.db.auto_commit_on_many_writes = 0

View File

@ -3,31 +3,32 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import flt
def execute(filters=None):
if not filters: filters = {}
columns = get_columns(filters)
item_map = get_item_details(filters)
iwb_map = get_item_warehouse_batch_map(filters)
data = []
for item in sorted(iwb_map):
for wh in sorted(iwb_map[item]):
for batch in sorted(iwb_map[item][wh]):
qty_dict = iwb_map[item][wh][batch]
data.append([item, item_map[item]["item_name"],
item_map[item]["description"], wh, batch,
qty_dict.opening_qty, qty_dict.in_qty,
data.append([item, item_map[item]["item_name"],
item_map[item]["description"], wh, batch,
qty_dict.opening_qty, qty_dict.in_qty,
qty_dict.out_qty, qty_dict.bal_qty
])
return columns, data
def get_columns(filters):
"""return columns based on filters"""
columns = ["Item:Link/Item:100"] + ["Item Name::150"] + ["Description::150"] + \
["Warehouse:Link/Warehouse:100"] + ["Batch:Link/Batch:100"] + ["Opening Qty::90"] + \
["In Qty::80"] + ["Out Qty::80"] + ["Balance Qty::90"]
@ -37,21 +38,21 @@ def get_columns(filters):
def get_conditions(filters):
conditions = ""
if not filters.get("from_date"):
frappe.msgprint("Please enter From Date", raise_exception=1)
frappe.throw(_("'From Date' is required"))
if filters.get("to_date"):
conditions += " and posting_date <= '%s'" % filters["to_date"]
else:
frappe.msgprint("Please enter To Date", raise_exception=1)
frappe.throw(_("'To Date' is required"))
return conditions
#get all details
def get_stock_ledger_entries(filters):
conditions = get_conditions(filters)
return frappe.db.sql("""select item_code, batch_no, warehouse,
posting_date, actual_qty
from `tabStock Ledger Entry`
return frappe.db.sql("""select item_code, batch_no, warehouse,
posting_date, actual_qty
from `tabStock Ledger Entry`
where docstatus < 2 %s order by item_code, warehouse""" %
conditions, as_dict=1)
@ -82,4 +83,4 @@ def get_item_details(filters):
for d in frappe.db.sql("select name, item_name, description from tabItem", as_dict=1):
item_map.setdefault(d.name, d)
return item_map
return item_map

View File

@ -2,6 +2,7 @@
# License: GNU General Public License v3. See license.txt
import frappe
from frappe import _
from frappe.utils import getdate, flt
def execute(filters=None):
@ -13,7 +14,7 @@ def execute(filters=None):
avg_daily_outgoing = 0
diff = ((getdate(filters.get("to_date")) - getdate(filters.get("from_date"))).days)+1
if diff <= 0:
frappe.msgprint("To Date should not be less than eual to From Date",raise_exception=1)
frappe.throw(_("'From Date' must be after 'To Date'"))
columns = get_columns()
items = get_item_info()
@ -27,8 +28,8 @@ def execute(filters=None):
avg_daily_outgoing = flt(total_outgoing/diff, float_preceision)
reorder_level = (avg_daily_outgoing * flt(item.lead_time_days)) + flt(item.min_order_qty)
data.append([item.name, item.item_name, item.description, item.min_order_qty, item.lead_time_days,
consumed_item_map.get(item.name, 0), delivered_item_map.get(item.name,0), total_outgoing,
data.append([item.name, item.item_name, item.description, item.min_order_qty, item.lead_time_days,
consumed_item_map.get(item.name, 0), delivered_item_map.get(item.name,0), total_outgoing,
avg_daily_outgoing, reorder_level])
return columns , data
@ -36,7 +37,7 @@ def execute(filters=None):
def get_columns():
return[
"Item:Link/Item:120", "Item name:Data:120", "Description::160",
"Minimum Inventory Level:Float:160", "Lead Time Days:Float:120", "Consumed:Float:120",
"Minimum Inventory Level:Float:160", "Lead Time Days:Float:120", "Consumed:Float:120",
"Delivered:Float:120", "Total Outgoing:Float:120", "Avg Daily Outgoing:Float:160",
"Reorder Level:Float:120"
]
@ -47,10 +48,10 @@ def get_item_info():
def get_consumed_items(condition):
cn_items = frappe.db.sql("""select se_item.item_code,
cn_items = frappe.db.sql("""select se_item.item_code,
sum(se_item.actual_qty) as 'consume_qty'
from `tabStock Entry` se, `tabStock Entry Detail` se_item
where se.name = se_item.parent and se.docstatus = 1
where se.name = se_item.parent and se.docstatus = 1
and ifnull(se_item.t_warehouse, '') = '' %s
group by se_item.item_code""" % (condition), as_dict=1)
@ -64,13 +65,13 @@ def get_delivered_items(condition):
dn_items = frappe.db.sql("""select dn_item.item_code, sum(dn_item.qty) as dn_qty
from `tabDelivery Note` dn, `tabDelivery Note Item` dn_item
where dn.name = dn_item.parent and dn.docstatus = 1 %s
where dn.name = dn_item.parent and dn.docstatus = 1 %s
group by dn_item.item_code""" % (condition), as_dict=1)
si_items = frappe.db.sql("""select si_item.item_name, sum(si_item.qty) as si_qty
from `tabSales Invoice` si, `tabSales Invoice Item` si_item
where si.name = si_item.parent and si.docstatus = 1 and
ifnull(si.update_stock, 0) = 1 and ifnull(si.is_pos, 0) = 1 %s
where si.name = si_item.parent and si.docstatus = 1 and
ifnull(si.update_stock, 0) = 1 and ifnull(si.is_pos, 0) = 1 %s
group by si_item.item_name""" % (condition), as_dict=1)
dn_item_map = {}
@ -87,5 +88,5 @@ def get_condition(filters):
if filters.get("from_date") and filters.get("to_date"):
conditions += " and posting_date between '%s' and '%s'" % (filters["from_date"],filters["to_date"])
else:
frappe.msgprint("Please set date in from date field",raise_exception=1)
return conditions
frappe.throw(_("From and To dates required"))
return conditions

View File

@ -3,31 +3,32 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils import flt
def execute(filters=None):
if not filters: filters = {}
columns = get_columns(filters)
item_map = get_item_details(filters)
iwb_map = get_item_warehouse_map(filters)
data = []
for company in sorted(iwb_map):
for item in sorted(iwb_map[company]):
for wh in sorted(iwb_map[company][item]):
qty_dict = iwb_map[company][item][wh]
data.append([item, item_map[item]["item_name"],
item_map[item]["description"], wh,
qty_dict.opening_qty, qty_dict.in_qty,
data.append([item, item_map[item]["item_name"],
item_map[item]["description"], wh,
qty_dict.opening_qty, qty_dict.in_qty,
qty_dict.out_qty, qty_dict.bal_qty, company
])
return columns, data
def get_columns(filters):
"""return columns based on filters"""
columns = ["Item:Link/Item:100", "Item Name::150", "Description::150", \
"Warehouse:Link/Warehouse:100", "Opening Qty:Float:90", \
"In Qty:Float:80", "Out Qty:Float:80", "Balance Qty:Float:90", "Company:Link/Company:100"]
@ -37,21 +38,21 @@ def get_columns(filters):
def get_conditions(filters):
conditions = ""
if not filters.get("from_date"):
frappe.msgprint("Please enter From Date", raise_exception=1)
frappe.throw(_("'From Date' is required"))
if filters.get("to_date"):
conditions += " and posting_date <= '%s'" % filters["to_date"]
else:
frappe.msgprint("Please enter To Date", raise_exception=1)
frappe.throw(_("'To Date' is required"))
return conditions
#get all details
def get_stock_ledger_entries(filters):
conditions = get_conditions(filters)
return frappe.db.sql("""select item_code, warehouse,
posting_date, actual_qty, company
from `tabStock Ledger Entry`
return frappe.db.sql("""select item_code, warehouse,
posting_date, actual_qty, company
from `tabStock Ledger Entry`
where docstatus < 2 %s order by item_code, warehouse""" %
conditions, as_dict=1)
@ -82,4 +83,4 @@ def get_item_details(filters):
for d in frappe.db.sql("select name, item_name, description from tabItem", as_dict=1):
item_map.setdefault(d.name, d)
return item_map
return item_map

View File

@ -4,34 +4,32 @@
from __future__ import unicode_literals
import frappe
from frappe import session, msgprint
from frappe import session, _
from frappe.utils import today
from erpnext.utilities.transaction_base import TransactionBase
class CustomerIssue(TransactionBase):
def validate(self):
if session['user'] != 'Guest' and not self.customer:
msgprint("Please select Customer from whom issue is raised",
raise_exception=True)
frappe.throw(_("Customer is required"))
if self.status=="Closed" and \
frappe.db.get_value("Customer Issue", self.name, "status")!="Closed":
self.resolution_date = today()
self.resolved_by = frappe.session.user
def on_cancel(self):
lst = 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!=2""",
lst = 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!=2""",
(self.name))
if lst:
lst1 = ','.join([x[0] for x in lst])
msgprint("Maintenance Visit No. "+lst1+" already created against this customer issue. So can not be Cancelled")
raise Exception
frappe.throw(_("Cancel Material Visit {0} before cancelling this Customer Issue").format(lst1))
else:
frappe.db.set(self, 'status', 'Cancelled')
@ -41,22 +39,22 @@ class CustomerIssue(TransactionBase):
@frappe.whitelist()
def make_maintenance_visit(source_name, target_doc=None):
from frappe.model.mapper import get_mapped_doc
visit = frappe.db.sql("""select t1.name
from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2
where t2.parent=t1.name and t2.prevdoc_docname=%s
visit = 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 and t1.completion_status='Fully Completed'""", source_name)
if not visit:
doclist = get_mapped_doc("Customer Issue", source_name, {
"Customer Issue": {
"doctype": "Maintenance Visit",
"doctype": "Maintenance Visit",
"field_map": {
"complaint": "description",
"doctype": "prevdoc_doctype",
"complaint": "description",
"doctype": "prevdoc_doctype",
"name": "prevdoc_docname"
}
}
}, target_doc)
return doclist
return doclist

View File

@ -1,302 +1,303 @@
{
"autoname": "MV.#####",
"creation": "2013-01-10 16:34:31.000000",
"docstatus": 0,
"doctype": "DocType",
"autoname": "MV.#####",
"creation": "2013-01-10 16:34:31.000000",
"docstatus": 0,
"doctype": "DocType",
"fields": [
{
"fieldname": "customer_details",
"fieldtype": "Section Break",
"label": "Customer Details",
"oldfieldtype": "Section Break",
"options": "icon-user",
"fieldname": "customer_details",
"fieldtype": "Section Break",
"label": "Customer Details",
"oldfieldtype": "Section Break",
"options": "icon-user",
"permlevel": 0
},
},
{
"fieldname": "column_break0",
"fieldtype": "Column Break",
"oldfieldtype": "Column Break",
"fieldname": "column_break0",
"fieldtype": "Column Break",
"oldfieldtype": "Column Break",
"permlevel": 0
},
},
{
"fieldname": "customer",
"fieldtype": "Link",
"in_filter": 1,
"label": "Customer",
"oldfieldname": "customer",
"oldfieldtype": "Link",
"options": "Customer",
"permlevel": 0,
"print_hide": 1,
"reqd": 1,
"fieldname": "customer",
"fieldtype": "Link",
"in_filter": 1,
"label": "Customer",
"oldfieldname": "customer",
"oldfieldtype": "Link",
"options": "Customer",
"permlevel": 0,
"print_hide": 1,
"reqd": 1,
"search_index": 0
},
},
{
"fieldname": "customer_name",
"fieldtype": "Data",
"hidden": 1,
"in_list_view": 1,
"label": "Customer Name",
"permlevel": 0,
"fieldname": "customer_name",
"fieldtype": "Data",
"hidden": 1,
"in_list_view": 1,
"label": "Customer Name",
"permlevel": 0,
"read_only": 1
},
},
{
"fieldname": "address_display",
"fieldtype": "Small Text",
"hidden": 1,
"label": "Address",
"permlevel": 0,
"fieldname": "address_display",
"fieldtype": "Small Text",
"hidden": 1,
"label": "Address",
"permlevel": 0,
"read_only": 1
},
},
{
"fieldname": "contact_display",
"fieldtype": "Small Text",
"hidden": 1,
"label": "Contact",
"permlevel": 0,
"fieldname": "contact_display",
"fieldtype": "Small Text",
"hidden": 1,
"label": "Contact",
"permlevel": 0,
"read_only": 1
},
},
{
"fieldname": "contact_mobile",
"fieldtype": "Data",
"hidden": 1,
"label": "Mobile No",
"permlevel": 0,
"fieldname": "contact_mobile",
"fieldtype": "Data",
"hidden": 1,
"label": "Mobile No",
"permlevel": 0,
"read_only": 1
},
},
{
"fieldname": "contact_email",
"fieldtype": "Data",
"hidden": 1,
"label": "Contact Email",
"permlevel": 0,
"fieldname": "contact_email",
"fieldtype": "Data",
"hidden": 1,
"label": "Contact Email",
"permlevel": 0,
"read_only": 1
},
},
{
"fieldname": "column_break1",
"fieldtype": "Column Break",
"oldfieldtype": "Column Break",
"permlevel": 0,
"fieldname": "column_break1",
"fieldtype": "Column Break",
"oldfieldtype": "Column Break",
"permlevel": 0,
"width": "50%"
},
},
{
"default": "Today",
"fieldname": "mntc_date",
"fieldtype": "Date",
"label": "Maintenance Date",
"no_copy": 1,
"oldfieldname": "mntc_date",
"oldfieldtype": "Date",
"permlevel": 0,
"default": "Today",
"fieldname": "mntc_date",
"fieldtype": "Date",
"label": "Maintenance Date",
"no_copy": 1,
"oldfieldname": "mntc_date",
"oldfieldtype": "Date",
"permlevel": 0,
"reqd": 1
},
},
{
"fieldname": "mntc_time",
"fieldtype": "Time",
"label": "Maintenance Time",
"no_copy": 1,
"oldfieldname": "mntc_time",
"oldfieldtype": "Time",
"fieldname": "mntc_time",
"fieldtype": "Time",
"label": "Maintenance Time",
"no_copy": 1,
"oldfieldname": "mntc_time",
"oldfieldtype": "Time",
"permlevel": 0
},
},
{
"fieldname": "maintenance_details",
"fieldtype": "Section Break",
"label": "Maintenance Details",
"oldfieldtype": "Section Break",
"options": "icon-wrench",
"fieldname": "maintenance_details",
"fieldtype": "Section Break",
"label": "Maintenance Details",
"oldfieldtype": "Section Break",
"options": "icon-wrench",
"permlevel": 0
},
},
{
"fieldname": "completion_status",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Completion Status",
"oldfieldname": "completion_status",
"oldfieldtype": "Select",
"options": "\nPartially Completed\nFully Completed",
"permlevel": 0,
"fieldname": "completion_status",
"fieldtype": "Select",
"in_list_view": 1,
"label": "Completion Status",
"oldfieldname": "completion_status",
"oldfieldtype": "Select",
"options": "\nPartially Completed\nFully Completed",
"permlevel": 0,
"reqd": 1
},
},
{
"fieldname": "column_break_14",
"fieldtype": "Column Break",
"fieldname": "column_break_14",
"fieldtype": "Column Break",
"permlevel": 0
},
},
{
"default": "Unscheduled",
"fieldname": "maintenance_type",
"fieldtype": "Select",
"in_filter": 1,
"in_list_view": 1,
"label": "Maintenance Type",
"oldfieldname": "maintenance_type",
"oldfieldtype": "Select",
"options": "\nScheduled\nUnscheduled\nBreakdown",
"permlevel": 0,
"reqd": 1,
"default": "Unscheduled",
"fieldname": "maintenance_type",
"fieldtype": "Select",
"in_filter": 1,
"in_list_view": 1,
"label": "Maintenance Type",
"oldfieldname": "maintenance_type",
"oldfieldtype": "Select",
"options": "\nScheduled\nUnscheduled\nBreakdown",
"permlevel": 0,
"reqd": 1,
"search_index": 0
},
},
{
"fieldname": "section_break0",
"fieldtype": "Section Break",
"oldfieldtype": "Section Break",
"options": "icon-wrench",
"fieldname": "section_break0",
"fieldtype": "Section Break",
"oldfieldtype": "Section Break",
"options": "icon-wrench",
"permlevel": 0
},
},
{
"fieldname": "maintenance_visit_details",
"fieldtype": "Table",
"label": "Maintenance Visit Purpose",
"oldfieldname": "maintenance_visit_details",
"oldfieldtype": "Table",
"options": "Maintenance Visit Purpose",
"permlevel": 0
},
{
"fieldname": "more_info",
"fieldtype": "Section Break",
"label": "More Info",
"oldfieldtype": "Section Break",
"options": "icon-file-text",
"permlevel": 0
},
{
"fieldname": "customer_feedback",
"fieldtype": "Small Text",
"label": "Customer Feedback",
"oldfieldname": "customer_feedback",
"oldfieldtype": "Small Text",
"permlevel": 0
},
{
"fieldname": "col_break3",
"fieldtype": "Column Break",
"permlevel": 0
},
{
"default": "Draft",
"fieldname": "status",
"fieldtype": "Data",
"label": "Status",
"no_copy": 1,
"oldfieldname": "status",
"oldfieldtype": "Data",
"options": "\nDraft\nCancelled\nSubmitted",
"permlevel": 0,
"read_only": 1,
"fieldname": "maintenance_visit_details",
"fieldtype": "Table",
"label": "Maintenance Visit Purpose",
"oldfieldname": "maintenance_visit_details",
"oldfieldtype": "Table",
"options": "Maintenance Visit Purpose",
"permlevel": 0,
"reqd": 1
},
},
{
"fieldname": "amended_from",
"fieldtype": "Data",
"ignore_restrictions": 1,
"label": "Amended From",
"no_copy": 1,
"oldfieldname": "amended_from",
"oldfieldtype": "Data",
"permlevel": 0,
"print_hide": 1,
"read_only": 1,
"fieldname": "more_info",
"fieldtype": "Section Break",
"label": "More Info",
"oldfieldtype": "Section Break",
"options": "icon-file-text",
"permlevel": 0
},
{
"fieldname": "customer_feedback",
"fieldtype": "Small Text",
"label": "Customer Feedback",
"oldfieldname": "customer_feedback",
"oldfieldtype": "Small Text",
"permlevel": 0
},
{
"fieldname": "col_break3",
"fieldtype": "Column Break",
"permlevel": 0
},
{
"default": "Draft",
"fieldname": "status",
"fieldtype": "Data",
"label": "Status",
"no_copy": 1,
"oldfieldname": "status",
"oldfieldtype": "Data",
"options": "\nDraft\nCancelled\nSubmitted",
"permlevel": 0,
"read_only": 1,
"reqd": 1
},
{
"fieldname": "amended_from",
"fieldtype": "Data",
"ignore_restrictions": 1,
"label": "Amended From",
"no_copy": 1,
"oldfieldname": "amended_from",
"oldfieldtype": "Data",
"permlevel": 0,
"print_hide": 1,
"read_only": 1,
"width": "150px"
},
},
{
"fieldname": "company",
"fieldtype": "Select",
"in_filter": 1,
"label": "Company",
"oldfieldname": "company",
"oldfieldtype": "Select",
"options": "link:Company",
"permlevel": 0,
"print_hide": 1,
"reqd": 1,
"fieldname": "company",
"fieldtype": "Select",
"in_filter": 1,
"label": "Company",
"oldfieldname": "company",
"oldfieldtype": "Select",
"options": "link:Company",
"permlevel": 0,
"print_hide": 1,
"reqd": 1,
"search_index": 0
},
},
{
"fieldname": "fiscal_year",
"fieldtype": "Select",
"in_filter": 1,
"label": "Fiscal Year",
"oldfieldname": "fiscal_year",
"oldfieldtype": "Select",
"options": "link:Fiscal Year",
"permlevel": 0,
"print_hide": 1,
"reqd": 1,
"fieldname": "fiscal_year",
"fieldtype": "Select",
"in_filter": 1,
"label": "Fiscal Year",
"oldfieldname": "fiscal_year",
"oldfieldtype": "Select",
"options": "link:Fiscal Year",
"permlevel": 0,
"print_hide": 1,
"reqd": 1,
"search_index": 0
},
},
{
"depends_on": "customer",
"fieldname": "contact_info_section",
"fieldtype": "Section Break",
"label": "Contact Info",
"options": "icon-bullhorn",
"depends_on": "customer",
"fieldname": "contact_info_section",
"fieldtype": "Section Break",
"label": "Contact Info",
"options": "icon-bullhorn",
"permlevel": 0
},
},
{
"fieldname": "customer_address",
"fieldtype": "Link",
"label": "Customer Address",
"options": "Address",
"permlevel": 0,
"fieldname": "customer_address",
"fieldtype": "Link",
"label": "Customer Address",
"options": "Address",
"permlevel": 0,
"print_hide": 1
},
},
{
"fieldname": "contact_person",
"fieldtype": "Link",
"label": "Contact Person",
"options": "Contact",
"permlevel": 0,
"fieldname": "contact_person",
"fieldtype": "Link",
"label": "Contact Person",
"options": "Contact",
"permlevel": 0,
"print_hide": 1
},
},
{
"fieldname": "col_break4",
"fieldtype": "Column Break",
"fieldname": "col_break4",
"fieldtype": "Column Break",
"permlevel": 0
},
},
{
"description": "<a href=\"#Sales Browser/Territory\">Add / Edit</a>",
"fieldname": "territory",
"fieldtype": "Link",
"label": "Territory",
"options": "Territory",
"permlevel": 0,
"description": "<a href=\"#Sales Browser/Territory\">Add / Edit</a>",
"fieldname": "territory",
"fieldtype": "Link",
"label": "Territory",
"options": "Territory",
"permlevel": 0,
"print_hide": 1
},
},
{
"description": "<a href=\"#Sales Browser/Customer Group\">Add / Edit</a>",
"fieldname": "customer_group",
"fieldtype": "Link",
"label": "Customer Group",
"options": "Customer Group",
"permlevel": 0,
"description": "<a href=\"#Sales Browser/Customer Group\">Add / Edit</a>",
"fieldname": "customer_group",
"fieldtype": "Link",
"label": "Customer Group",
"options": "Customer Group",
"permlevel": 0,
"print_hide": 1
}
],
"icon": "icon-file-text",
"idx": 1,
"is_submittable": 1,
"modified": "2014-01-20 17:48:57.000000",
"modified_by": "Administrator",
"module": "Support",
"name": "Maintenance Visit",
"owner": "ashwini@webnotestech.com",
],
"icon": "icon-file-text",
"idx": 1,
"is_submittable": 1,
"modified": "2014-01-20 17:48:57.000001",
"modified_by": "Administrator",
"module": "Support",
"name": "Maintenance Visit",
"owner": "ashwini@webnotestech.com",
"permissions": [
{
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Maintenance User",
"submit": 1,
"amend": 1,
"cancel": 1,
"create": 1,
"delete": 1,
"email": 1,
"permlevel": 0,
"print": 1,
"read": 1,
"report": 1,
"role": "Maintenance User",
"submit": 1,
"write": 1
}
],
],
"search_fields": "status,maintenance_type,customer,customer_name, address,mntc_date,company,fiscal_year"
}
}

View File

@ -3,33 +3,24 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import cstr
from frappe import msgprint
from frappe import _
from erpnext.utilities.transaction_base import TransactionBase
class MaintenanceVisit(TransactionBase):
def get_item_details(self, item_code):
return frappe.db.get_value("Item", item_code, ["item_name", "description"], as_dict=1)
def validate_serial_no(self):
for d in self.get('maintenance_visit_details'):
if d.serial_no and not frappe.db.exists("Serial No", d.serial_no):
frappe.throw("Serial No: "+ d.serial_no + " not exists in the system")
def validate(self):
if not self.get('maintenance_visit_details'):
msgprint("Please enter maintenance details")
raise Exception
def validate(self):
self.validate_serial_no()
def update_customer_issue(self, flag):
for d in self.get('maintenance_visit_details'):
if d.prevdoc_docname and d.prevdoc_doctype == 'Customer Issue' :
@ -43,7 +34,7 @@ class MaintenanceVisit(TransactionBase):
status = 'Work In Progress'
else:
nm = frappe.db.sql("select t1.name, t1.mntc_date, t2.service_person, t2.work_done from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent = t1.name and t1.completion_status = 'Partially Completed' and t2.prevdoc_docname = %s and t1.name!=%s and t1.docstatus = 1 order by t1.name desc limit 1", (d.prevdoc_docname, self.name))
if nm:
status = 'Work In Progress'
mntc_date = nm and nm[0][1] or ''
@ -54,9 +45,9 @@ class MaintenanceVisit(TransactionBase):
mntc_date = ''
service_person = ''
work_done = ''
frappe.db.sql("update `tabCustomer Issue` set resolution_date=%s, resolved_by=%s, resolution_details=%s, status=%s where name =%s",(mntc_date,service_person,work_done,status,d.prevdoc_docname))
def check_if_last_visit(self):
"""check if last maintenance visit against same sales order/ customer issue"""
@ -65,25 +56,25 @@ class MaintenanceVisit(TransactionBase):
if d.prevdoc_docname:
check_for_docname = d.prevdoc_docname
check_for_doctype = d.prevdoc_doctype
if check_for_docname:
check = frappe.db.sql("select t1.name from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2 where t2.parent = t1.name and t1.name!=%s and t2.prevdoc_docname=%s and t1.docstatus = 1 and (t1.mntc_date > %s or (t1.mntc_date = %s and t1.mntc_time > %s))", (self.name, check_for_docname, self.mntc_date, self.mntc_date, self.mntc_time))
if check:
check_lst = [x[0] for x in check]
check_lst =','.join(check_lst)
msgprint("To cancel this, you need to cancel Maintenance Visit(s) "+cstr(check_lst)+" created after this maintenance visit against same "+check_for_doctype)
frappe.throw(_("Cancel Material Visits {0} before cancelling this Maintenance Visit").format(check_lst))
raise Exception
else:
self.update_customer_issue(0)
def on_submit(self):
self.update_customer_issue(1)
self.update_customer_issue(1)
frappe.db.set(self, 'status', 'Submitted')
def on_cancel(self):
self.check_if_last_visit()
self.check_if_last_visit()
frappe.db.set(self, 'status', 'Cancelled')
def on_update(self):
pass
pass

View File

@ -6,7 +6,7 @@ from __future__ import unicode_literals
import frappe
import frappe.utils
from frappe.utils import cstr
from frappe import msgprint, throw, _
from frappe import throw, _
from frappe.model.document import Document
class Newsletter(Document):
@ -20,10 +20,7 @@ class Newsletter(Document):
self.recipients = self.test_email_id.split(",")
self.send_to_doctype = "Lead"
self.send_bulk()
msgprint("{send} {email}".format**{
"send": _("Scheduled to send to"),
"email": self.test_email_id
})
frappe.msgprint(_("Scheduled to send to {0}").format(self.test_email_id))
def send_emails(self):
"""send emails to leads and customers"""
@ -32,27 +29,23 @@ class Newsletter(Document):
self.recipients = self.get_recipients()
self.send_bulk()
msgprint("{send} {recipients} {doctype}(s)".format(**{
"send": _("Scheduled to send to"),
"recipients": len(self.recipients),
"doctype": self.send_to_doctype
}))
frappe.msgprint(_("Scheduled to send to {0} recipients").format(len(self.recipients)))
frappe.db.set(self, "email_sent", 1)
def get_recipients(self):
self.email_field = None
if self.send_to_type=="Contact":
self.send_to_doctype = "Contact"
if self.contact_type == "Customer":
return frappe.db.sql_list("""select email_id from tabContact
if self.contact_type == "Customer":
return frappe.db.sql_list("""select email_id from tabContact
where ifnull(email_id, '') != '' and ifnull(customer, '') != ''""")
elif self.contact_type == "Supplier":
return frappe.db.sql_list("""select email_id from tabContact
elif self.contact_type == "Supplier":
return frappe.db.sql_list("""select email_id from tabContact
where ifnull(email_id, '') != '' and ifnull(supplier, '') != ''""")
elif self.send_to_type=="Lead":
self.send_to_doctype = "Lead"
conditions = []
@ -63,37 +56,37 @@ class Newsletter(Document):
if conditions:
conditions = "".join(conditions)
return frappe.db.sql_list("""select email_id from tabLead
return frappe.db.sql_list("""select email_id from tabLead
where ifnull(email_id, '') != '' %s""" % (conditions or ""))
elif self.send_to_type=="Employee":
self.send_to_doctype = "Employee"
self.email_field = "company_email"
return frappe.db.sql_list("""select
if(ifnull(company_email, '')!='', company_email, personal_email) as email_id
return frappe.db.sql_list("""select
if(ifnull(company_email, '')!='', company_email, personal_email) as email_id
from `tabEmployee` where status='Active'""")
elif self.email_list:
email_list = [cstr(email).strip() for email in self.email_list.split(",")]
for email in email_list:
create_lead(email)
self.send_to_doctype = "Lead"
return email_list
def send_bulk(self):
self.validate_send()
sender = self.send_from or frappe.utils.get_formatted_email(self.owner)
from frappe.utils.email_lib.bulk import send
if not frappe.flags.in_test:
frappe.db.auto_commit_on_many_writes = True
send(recipients = self.recipients, sender = sender,
send(recipients = self.recipients, sender = sender,
subject = self.subject, message = self.message,
doctype = self.send_to_doctype, email_field = self.email_field or "email_id",
ref_doctype = self.doctype, ref_docname = self.name)
@ -103,19 +96,18 @@ class Newsletter(Document):
def validate_send(self):
if self.get("__islocal"):
throw(_("Please save the Newsletter before sending."))
throw(_("Please save the Newsletter before sending"))
from frappe import conf
if (conf.get("status") or None) == "Trial":
throw(_("Sending newsletters is not allowed for Trial users, \
to prevent abuse of this feature."))
throw(_("Newsletters is not allowed for Trial users"))
@frappe.whitelist()
def get_lead_options():
return {
"sources": ["All"] + filter(None,
"sources": ["All"] + filter(None,
frappe.db.sql_list("""select distinct source from tabLead""")),
"statuses": ["All"] + filter(None,
"statuses": ["All"] + filter(None,
frappe.db.sql_list("""select distinct status from tabLead"""))
}
@ -125,10 +117,10 @@ def create_lead(email_id):
from email.utils import parseaddr
from frappe.model.naming import get_default_naming_series
real_name, email_id = parseaddr(email_id)
if frappe.db.get_value("Lead", {"email_id": email_id}):
return
lead = frappe.get_doc({
"doctype": "Lead",
"email_id": email_id,
@ -138,4 +130,4 @@ def create_lead(email_id):
"company": frappe.db.get_default("company"),
"source": "Email"
})
lead.insert()
lead.insert()

View File

@ -5,24 +5,24 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.model.document import Document
from frappe.utils.email_lib.receive import POP3Mailbox
import _socket, poplib
class SupportEmailSettings(Document):
def validate(self):
"""
Checks support ticket email settings
"""
if self.sync_support_mails and self.mail_server:
if self.sync_support_mails and self.mail_server:
inc_email = frappe.get_doc('Incoming Email Settings')
# inc_email.encode()
inc_email.host = self.mail_server
inc_email.use_ssl = self.use_ssl
try:
err_msg = 'User Name or Support Password missing. Please enter and try again.'
err_msg = _('User Name or Support Password missing. Please enter and try again.')
if not (self.mail_login and self.mail_password):
raise AttributeError, err_msg
inc_email.username = self.mail_login
@ -32,14 +32,13 @@ class SupportEmailSettings(Document):
raise
pop_mb = POP3Mailbox(inc_email)
try:
pop_mb.connect()
except _socket.error, e:
# Invalid mail server -- due to refusing connection
frappe.msgprint('Invalid POP3 Mail Server. Please rectify and try again.')
frappe.msgprint(_('Invalid Mail Server. Please rectify and try again.'))
raise
except poplib.error_proto, e:
frappe.msgprint('Invalid User Name or Support Password. Please rectify and try again.')
frappe.msgprint(_('Invalid User Name or Support Password. Please rectify and try again.'))
raise

View File

@ -1,27 +1,27 @@
# ERPNext - web based ERP (http://erpnext.com)
# Copyright (C) 2012 Web Notes Technologies Pvt Ltd
#
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
import frappe
from frappe import _, msgprint
from frappe import _
from frappe.utils import cint, comma_or
def validate_status(status, options):
if status not in options:
msgprint(_("Status must be one of ") + comma_or(options), raise_exception=True)
frappe.throw(_("Status must be one of {0}").format(comma_or(options)))
def build_filter_conditions(filters):
conditions, filter_values = [], []
@ -30,4 +30,4 @@ def build_filter_conditions(filters):
filter_values.append(filters[key])
conditions = conditions and " and " + " and ".join(conditions) or ""
return conditions, filter_values
return conditions, filter_values

View File

@ -4,8 +4,8 @@
from __future__ import unicode_literals
import frappe
from frappe import msgprint, throw, _
from frappe.utils import cstr, cint
from frappe import throw, _
from frappe.utils import cstr
from frappe.model.document import Document
@ -20,30 +20,30 @@ class Address(Document):
self.name = cstr(self.address_title).strip() + "-" + cstr(self.address_type).strip()
else:
throw(_("Address Title is mandatory."))
def validate(self):
self.validate_primary_address()
self.validate_shipping_address()
def validate_primary_address(self):
"""Validate that there can only be one primary address for particular customer, supplier"""
if self.is_primary_address == 1:
self._unset_other("is_primary_address")
elif self.is_shipping_address != 1:
for fieldname in ["customer", "supplier", "sales_partner", "lead"]:
if self.get(fieldname):
if not frappe.db.sql("""select name from `tabAddress` where is_primary_address=1
and `%s`=%s and name!=%s""" % (fieldname, "%s", "%s"),
and `%s`=%s and name!=%s""" % (fieldname, "%s", "%s"),
(self.get(fieldname), self.name)):
self.is_primary_address = 1
break
def validate_shipping_address(self):
"""Validate that there can only be one shipping address for particular customer, supplier"""
if self.is_shipping_address == 1:
self._unset_other("is_shipping_address")
def _unset_other(self, is_address_type):
for fieldname in ["customer", "supplier", "sales_partner", "lead"]:
if self.get(fieldname):
@ -55,21 +55,21 @@ class Address(Document):
def get_address_display(address_dict):
if not isinstance(address_dict, dict):
address_dict = frappe.db.get_value("Address", address_dict, "*", as_dict=True) or {}
meta = frappe.get_meta("Address")
sequence = (("", "address_line1"),
("\n", "address_line2"),
sequence = (("", "address_line1"),
("\n", "address_line2"),
("\n", "city"),
("\n", "state"),
("\n" + meta.get_label("pincode") + ": ", "pincode"),
("\n", "state"),
("\n" + meta.get_label("pincode") + ": ", "pincode"),
("\n", "country"),
("\n" + meta.get_label("phone") + ": ", "phone"),
("\n" + meta.get_label("phone") + ": ", "phone"),
("\n" + meta.get_label("fax") + ": ", "fax"))
display = ""
for separator, fieldname in sequence:
if address_dict.get(fieldname):
display += separator + address_dict.get(fieldname)
return display.strip()

View File

@ -5,24 +5,24 @@
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.model.document import Document
class Note(Document):
def autoname(self):
# replace forbidden characters
import re
self.name = re.sub("[%'\"#*?`]", "", self.title.strip())
def onload(self):
if not self.public and frappe.session.user != self.owner:
if frappe.session.user not in [d.user for d in self.get("share_with")]:
frappe.msgprint("You are not authorized to read this record.", raise_exception=True)
frappe.throw(_("Not permitted"), frappe.PermissionError)
def validate(self):
if not self.get("__islocal"):
if frappe.session.user != self.owner:
if frappe.session.user not in frappe.db.sql_list("""select user from `tabNote User`
if frappe.session.user not in frappe.db.sql_list("""select user from `tabNote User`
where parent=%s and permission='Edit'""", self.name):
frappe.msgprint("You are not authorized to edit this record.", raise_exception=True)
frappe.throw(_("Not permitted"), frappe.PermissionError)

View File

@ -11,34 +11,32 @@ from frappe.model.document import Document
class RenameTool(Document):
pass
@frappe.whitelist()
def get_doctypes():
return frappe.db.sql_list("""select name from tabDocType
where ifnull(allow_rename,0)=1 and module!='Core' order by name""")
@frappe.whitelist()
def upload(select_doctype=None, rows=None):
from frappe.utils.datautils import read_csv_content_from_uploaded_file
from frappe.modules import scrub
from frappe.model.rename_doc import rename_doc
if not select_doctype:
select_doctype = frappe.form_dict.select_doctype
if not frappe.has_permission(select_doctype, "write"):
raise frappe.PermissionError
if not rows:
rows = read_csv_content_from_uploaded_file()
if not rows:
frappe.msgprint(_("Please select a valid csv file with data."))
raise Exception
if len(rows) > 500:
frappe.msgprint(_("Max 500 rows only."))
raise Exception
frappe.throw(_("Please select a valid csv file with data"))
max_rows = 500
if len(rows) > max_rows:
frappe.throw(_("Maximum {0} rows allowed").format(max_rows))
rename_log = []
for row in rows:
# if row has some content
@ -53,5 +51,5 @@ def upload(select_doctype=None, rows=None):
rename_log.append("<span style='color: RED'>" + \
_("Failed: ") + row[0] + " -> " + row[1] + "</span>")
rename_log.append("<span style='margin-left: 20px;'>" + repr(e) + "</span>")
return rename_log
return rename_log

View File

@ -19,7 +19,7 @@ class SMSControl(Document):
invalid_char_list = [' ', '+', '-', '(', ')']
for x in invalid_char_list:
d = d.replace(x, '')
validated_receiver_list.append(d)
if not validated_receiver_list:
@ -34,21 +34,18 @@ class SMSControl(Document):
'ERPNXT'
if len(sender_name) > 6 and \
frappe.db.get_default("country") == "India":
throw(_("""
As per TRAI rule, sender name must be exactly 6 characters.
throw("""As per TRAI rule, sender name must be exactly 6 characters.
Kindly change sender name in Setup --> Global Defaults.
Note: Hyphen, space, numeric digit, special characters are not allowed.
"""))
Note: Hyphen, space, numeric digit, special characters are not allowed.""")
return sender_name
def get_contact_number(self, arg):
"returns mobile number of the contact"
args = json.loads(arg)
number = frappe.db.sql("""select mobile_no, phone from tabContact where name=%s and %s=%s""" %
number = frappe.db.sql("""select mobile_no, phone from tabContact where name=%s and %s=%s""" %
('%s', args['key'], '%s'), (args['contact_name'], args['value']))
return number and (number[0][0] or number[0][1]) or ''
def send_form_sms(self, arg):
"called from client side"
args = json.loads(arg)
@ -72,7 +69,7 @@ class SMSControl(Document):
args = {ss.message_parameter : arg.get('message')}
for d in ss.get("static_parameter_details"):
args[d.parameter] = d.value
resp = []
for d in arg.get('receiver_list'):
args[ss.receiver_parameter] = d

View File

@ -15,26 +15,26 @@ class TransactionBase(StatusUpdater):
if int(frappe.db.get_value("Notification Control", None, dt) or 0):
self.set("__notification_message",
frappe.db.get_value("Notification Control", None, dt + "_message"))
def validate_posting_time(self):
if not self.posting_time:
self.posting_time = now_datetime().strftime('%H:%M:%S')
def add_calendar_event(self, opts, force=False):
if self.contact_by != cstr(self._prev.contact_by) or \
self.contact_date != cstr(self._prev.contact_date) or force:
self.delete_events()
self._add_calendar_event(opts)
def delete_events(self):
frappe.delete_doc("Event", frappe.db.sql_list("""select name from `tabEvent`
where ref_type=%s and ref_name=%s""", (self.doctype, self.name)),
frappe.delete_doc("Event", frappe.db.sql_list("""select name from `tabEvent`
where ref_type=%s and ref_name=%s""", (self.doctype, self.name)),
ignore_permissions=True)
def _add_calendar_event(self, opts):
opts = frappe._dict(opts)
if self.contact_date:
event_doclist = frappe.get_doc({
"doctype": "Event",
@ -46,18 +46,18 @@ class TransactionBase(StatusUpdater):
"ref_type": self.doctype,
"ref_name": self.name
})
if frappe.db.exists("User", self.contact_by):
event_doclist.append("event_individuals", {
"doctype": "Event User",
"person": self.contact_by
})
event_doclist.insert()
def validate_uom_is_integer(self, uom_field, qty_fields):
validate_uom_is_integer(self, uom_field, qty_fields)
def validate_with_previous_doc(self, source_dt, ref):
for key, val in ref.items():
is_child = val.get("is_child_table")
@ -71,27 +71,26 @@ class TransactionBase(StatusUpdater):
if ref_dn not in item_ref_dn:
item_ref_dn.append(ref_dn)
elif not val.get("allow_duplicate_prev_row_id"):
frappe.msgprint(_("Row ") + cstr(d.idx + 1) +
_(": Duplicate row from same ") + key, raise_exception=1)
frappe.throw(_("Duplicate row {0} with same {1}").format(d.idx, key))
elif ref_dn:
ref_doc.setdefault(key, [])
if ref_dn not in ref_doc[key]:
ref_doc[key].append(ref_dn)
if ref_doc:
self.compare_values(ref_doc, val["compare_fields"])
def compare_values(self, ref_doc, fields, doc=None):
for ref_doctype, ref_dn_list in ref_doc.items():
for ref_docname in ref_dn_list:
prevdoc_values = frappe.db.get_value(ref_doctype, ref_docname,
prevdoc_values = frappe.db.get_value(ref_doctype, ref_docname,
[d[0] for d in fields], as_dict=1)
for field, condition in fields:
if prevdoc_values[field] is not None:
self.validate_value(field, condition, prevdoc_values[field], doc)
def delete_events(ref_type, ref_name):
frappe.delete_doc("Event", frappe.db.sql_list("""select name from `tabEvent`
frappe.delete_doc("Event", frappe.db.sql_list("""select name from `tabEvent`
where ref_type=%s and ref_name=%s""", (ref_type, ref_name)), for_reload=True)
class UOMMustBeIntegerError(frappe.ValidationError): pass
@ -99,11 +98,11 @@ class UOMMustBeIntegerError(frappe.ValidationError): pass
def validate_uom_is_integer(doc, uom_field, qty_fields):
if isinstance(qty_fields, basestring):
qty_fields = [qty_fields]
distinct_uoms = list(set([d.get(uom_field) for d in doc.get_all_children()]))
integer_uoms = filter(lambda uom: frappe.db.get_value("UOM", uom,
integer_uoms = filter(lambda uom: frappe.db.get_value("UOM", uom,
"must_be_whole_number") or None, distinct_uoms)
if not integer_uoms:
return
@ -112,7 +111,4 @@ def validate_uom_is_integer(doc, uom_field, qty_fields):
for f in qty_fields:
if d.get(f):
if cint(d.get(f))!=d.get(f):
frappe.msgprint(_("For UOM") + " '" + d.get(uom_field) \
+ "': " + _("Quantity cannot be a fraction.") \
+ " " + _("In Row") + ": " + str(d.idx),
raise_exception=UOMMustBeIntegerError)
frappe.throw(_("Quantity cannot be a fraction in row {0}").format(d.idx), UOMMustBeIntegerError)