fixed strings for translation
This commit is contained in:
parent
5d4ffa6cf8
commit
2c45899a02
@ -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'):
|
||||
|
@ -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"]:
|
||||
|
@ -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!
|
||||
|
@ -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':
|
||||
|
@ -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')) }
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user